AI & Development

skills.md Explained: Give Claude Code Persistent Project Expertise

skills.md files let you store specialized instructions for Claude Code that activate on specific tasks.

Every time you give Claude Code a non-trivial task, you face the same problem: context. The model does not remember your last session. It does not know your project's conventions, the reason a particular architecture decision was made, or the specific format your team expects for test files. You either re-explain this context with each task - which is tedious and error-prone - or you find a way to make the context persistent. Skills.md files are that way.

What a skills.md file is

A skills.md file is a Markdown file that defines a named skill for Claude Code. When that skill is invoked - either by name or by matching a trigger pattern - Claude Code reads the skill file and executes the task with the full context, workflow, and constraints defined in it.

Skills live in a .claude/skills/ directory at the root of your project (or in a shared location for organization-wide skills). Each skill file has a frontmatter header and a body:

---
name: deploy
description: Deploy the production build to Firebase Hosting. Triggers on keywords: deploy, publish, release.
tools:
  - Bash
  - Read
---

[Full deployment workflow and checklist here]

The frontmatter declares the skill's name, when it should activate, and which tools it has access to. The body is the full instruction set - workflow steps, constraints, what to check before acting, what to do if something fails.

Skills versus CLAUDE.md - what goes where

CLAUDE.md is the general project context that Claude Code loads at the start of every session: coding conventions, testing setup, architecture overview, environment configuration, known gotchas. It applies to everything.

A skills.md file is specialized context for a specific type of task. It does not load on every session - it loads when its skill is invoked. This distinction matters because general context and specialized workflow are different kinds of information. Loading a full deployment checklist on every session would add noise to every task; loading it only when you run the deploy skill means it is always there when you need it and invisible when you do not.

Think of CLAUDE.md as the project handbook and skills.md files as the specific SOPs (standard operating procedures) for individual workflows. Both are needed; neither replaces the other.

Writing a skills.md file that actually works

The most common mistake in writing skills is being too general. "Deploy the app" is not a useful skill description. "Run the production build, verify the bundle size is under 500KB, deploy to Firebase Hosting with firebase deploy --only hosting, and confirm the deployment URL is accessible before marking the task complete" is a useful skill description.

A well-written skills.md file has five components:

1. A precise trigger definition. What keywords, file patterns, or explicit invocations activate this skill? Be specific enough that the skill activates when intended and not when unintended. A deploy skill should trigger on "deploy", "publish", and "release" - not on "update" or "change".

2. Pre-conditions to verify. What must be true before the skill executes? A deploy skill should verify that the working tree is clean, that tests pass, and that the build succeeds before touching the hosting environment. Pre-condition checking prevents the skill from taking destructive actions when the system is in an unexpected state.

3. The step-by-step workflow. What does the skill do, in what order? Number the steps. For skills that involve destructive or irreversible actions, specify that user confirmation is required before proceeding. Do not describe what the skill does in abstract terms - specify the exact commands, file paths, and outputs expected at each step.

4. Error handling and fallbacks. What should the skill do if a step fails? For a deploy skill: if the build fails, stop and report the error without attempting to deploy. If the deployment fails, report the Firebase error output. Never silently swallow failures in a skill - failures should surface immediately.

5. Scope boundaries. What is explicitly out of scope for this skill? A frontend deploy skill should not touch backend configuration. A blog-writing skill should not modify sitemap.xml directly. Explicit scope boundaries prevent the skill from over-reaching into adjacent areas that belong to different workflows.

Tool access - give only what the skill needs

The tools frontmatter field controls which tools the skill can use. This is a security and reliability control. A skill that only needs to read files should declare only Read. A skill that needs to read and write files and run shell commands declares Read, Write, and Bash.

Giving a skill access to tools it does not need increases the risk of unintended actions. A blog-writing skill with access to Bash could theoretically run git commands - if you only intend it to read and write content files, restrict it to Read, Write, and Edit.

The tool access restriction also serves as documentation: looking at a skill's tool list tells you immediately what category of actions it can take. A skill with only Read and Write access cannot run commands or browse the web. This predictability is valuable when reviewing skills written by others or revisiting your own skills after time away.

Organization-wide versus project-specific skills

Skills can live at the project level (in .claude/skills/ inside the repo) or at the user level (in ~/.claude/skills/ on the developer's machine). Project-level skills are committed to the repository and shared with all developers. User-level skills are personal and portable across projects.

Project-level skills are appropriate for: deployment procedures, test run scripts, code review checklists, project-specific formatting rules, release workflows. These are things every developer working on the project should use consistently.

User-level skills are appropriate for: personal workflow preferences, editor-specific integrations, cross-project utilities like "summarize the git log since last week". These are personal productivity tools that may not make sense to impose on the entire team.

Iterating on skills

A skills.md file is not a set-and-forget artifact. The first version of any skill will have gaps - steps that assumed context the model does not have, missing error conditions, ambiguous instructions that produce inconsistent behavior. The workflow for improving a skill is the same as improving any specification: run it, observe where it fails or produces unexpected output, and add specificity to the instructions at that point.

Three iterations is a reasonable expectation for a skill to stabilize. By the third revision of a non-trivial skill, the common failure modes are addressed and the output is consistent enough to trust without manual review for every run.