Claude Code Skills: How to Write, Share, and Govern Them at Scale
Ampliflow
Advanced AI frontier lab and business growth agency. Helping UK businesses deploy agentic AI systems.
A Claude Code skill is a directory containing a `SKILL.md` file with YAML frontmatter and markdown instructions. Claude loads skills automatically when their description matches what you are asking for, or you can invoke them by name with /skill-name. The detail that no competitor article explains clearly: the description field is not documentation — it is a fuzzy-match trigger. The right way to write a skill is to start with the description, write it as a sentence describing when it should fire, then write the body second. Most teams do the opposite, and their skills sit unused.
Last updated: May 2026 · Covers Claude Code v2 skills + plugin system · Verified against official Anthropic docs
TL;DR:
- A skill is a directory with a
SKILL.mdfile. Frontmatter on top, markdown instructions below - Skills cost zero context budget until invoked — long procedures belong in skills, not in
CLAUDE.md - The description field is the trigger — write it as "Use when…" and lead with verbs users naturally type
- Project skills go in
.claude/skills/, personal skills in~/.claude/skills/, plugin skills are namespaced and shared via the marketplace - For dangerous skills (deploy, send email, commit), set
disable-model-invocation: trueso Claude cannot fire them autonomously
What is a Claude Code skill?
Two types of skill, one shared format.
Anthropic's official guidance distinguishes two kinds of skill:
Capability uplift — teaches Claude an ability it does not have natively. Examples: running your specific deploy script with the right environment variables, generating an interactive HTML visualisation of test coverage data, fetching live data from your internal API.
Encoded preference — Claude already knows the underlying task, but the skill captures your team's specific way of doing it. Examples: your commit-message format, your NDA review checklist, your incident-response process, your brand-voice rules for marketing copy.
Both types share the same structure. Both live in a directory. Both are described by a SKILL.md file with YAML frontmatter on top and instructions below. The only meaningful difference is whether the skill teaches Claude something new or codifies how you want something done.
The official heuristic from Anthropic: "Create a skill when you keep pasting the same instructions, checklist, or multi-step procedure into chat, or when a section of `CLAUDE.md` has grown into a procedure rather than a fact."
If you find yourself starting sessions with "remember, when you write commits in this repo…" — that is a skill waiting to be written.
Skill anatomy — the file you actually write
Minimal working example, taken verbatim from Anthropic's official docs:
`yaml
description: Summarises uncommitted changes and flags anything risky. Use when the user asks what changed, wants a commit message, or asks to review their diff.
Current changes
!git diff HEAD
Instructions
Summarise the changes above in two or three bullet points, then list any risks… `
That is it. Three sections in the body, one frontmatter field. This skill triggers automatically when you ask Claude what changed in your repo, and the !git diff HEAD`` line runs the shell command before Claude sees the prompt — so the diff is injected into the context, not requested by Claude.
The directory structure can be more elaborate when needed:
` my-skill/ ├── SKILL.md # Required — the entry point ├── template.md # Optional — a template Claude fills in ├── examples/ │ └── sample.md # Optional — expected output format └── scripts/ └── validate.sh # Optional — executable Claude can run `
Two filename rules that catch people: SKILL.md is case-sensitive (skill.md will not be found). The directory name becomes the slash command (my-skill/ → /my-skill).
Frontmatter fields that matter
The full reference is long; these are the ones you will actually use:
| Field | Purpose |
|---|---|
| `description` | The most important field. Used for auto-triggering. Write as a "Use when…" sentence with the verbs users would naturally type. |
| `when_to_use` | Optional addition to `description` — appended in the skill listing. Useful for adding negative examples ("Do not use when…"). |
| `disable-model-invocation` | `true` = only the user can invoke. Mandatory for any skill with side effects (deploy, send email, post to Slack). |
| `user-invocable` | `false` = hidden from the `/` menu, only Claude can invoke. Useful for background skills the user should not call directly. |
| `allowed-tools` | Pre-approve specific tools (e.g. `Bash(git add *)`) without per-use prompts. |
| `paths` | Glob patterns — only activate when working on matching files. |
| `model` | Override which model runs the skill (use `haiku-4-5` for cheap reference-lookup skills). |
| `effort` | Override effort level: `low`, `medium`, `high`, `xhigh`, `max`. |
| `context: fork` | Run the skill in an isolated subagent with a clean context window — useful for large skills that would otherwise pollute the main context. |
Dynamic context injection — the underexplained feature
The !command`` syntax runs a shell command and replaces the placeholder with its output before Claude sees the prompt. This is preprocessing — Claude is not running the command — and it is the cleanest way to inject live data into a skill.
`yaml
description: Reviews open PRs for staleness. Use when the user asks about open PRs, wants a triage, or mentions PR backlog.
Open pull requests
!gh pr list --state open --json number,title,createdAt,labels --limit 50
Instructions
Review the PRs above. Group by staleness (under 7 days, 7-30 days, 30+ days)… `
When a user asks about open PRs, Claude sees the actual gh pr list output, not a request to fetch it. This is faster, more reliable, and uses fewer tokens than tool calls.
Multi-line shell injection uses the fenced `! block syntax. Variables you can use: ${CLAUDE_SESSION_ID}, ${CLAUDE_SKILL_DIR} (critical for plugin-bundled scripts), ${CLAUDE_EFFORT}, $ARGUMENTS, $ARGUMENTS[0].
How to write your first Claude Code skill
Eight steps from "I keep typing the same thing" to "the skill is doing the work."
1. Identify the trigger pattern
You have a skill waiting to be written when:
- You start sessions with the same context-setting block
- You paste the same checklist into multiple conversations
- A section of your
CLAUDE.mdhas grown from a fact ("we use Convex") into a procedure ("when adding a new mutation, do X then Y then Z") - You explain the same workflow to new team members repeatedly
2. Pick the directory location
| Scope | Path |
|---|---|
| Personal, all your projects | `~/.claude/skills/my-skill/` |
| This repo only | `.claude/skills/my-skill/` |
| Shared via plugin | `my-plugin/skills/my-skill/` |
The directory name becomes the slash command. Lowercase with hyphens (open-pr-triage, not OpenPRTriage).
3. Write the description first
This is the most important sentence in the entire skill. Lead with verbs users naturally type. Use "Use when…" framing. Include negative examples if needed.
Bad: "A skill for git diffs." Better: "Summarises uncommitted changes." Best: "Summarises uncommitted changes and flags anything risky. Use when the user asks what changed, wants a commit message, or asks to review their diff. Do not use for committing — use /commit instead."
4. Write the body concisely
Use imperative instructions ("Run X. Then Y."), not documentation prose. Anthropic's official guidance: keep `SKILL.md` under 500 lines. Every line is a recurring token cost once loaded.
A common mistake is writing the skill like a tutorial. The skill is for Claude, not for a human reader. Claude does not need preamble, motivation, or context-setting. Skip to the procedure.
5. Decide invocation control
For skills with side effects, set disable-model-invocation: true so Claude cannot trigger them autonomously:
`yaml
description: Deploys the production application. Use only when the user explicitly asks to deploy. disable-model-invocation: true
`
For background-knowledge skills the user should not invoke directly, set user-invocable: false. The skill stays available to Claude but does not appear in the / menu.
6. Add dynamic context if needed
Use !command`` for live data injection. Common patterns:
!git diff HEAD`` — current uncommitted changes!gh pr list --state open`` — open PRs!cat package.json | jq .scripts`` — available npm scripts!npm test 2>&1 | tail -50`` — recent test output
7. Test two ways
Restart Claude Code (or run /reload-plugins). Then:
- Ask Claude something matching the description. It should auto-trigger. If it does not, the description is wrong — rewrite it.
- Type `/my-skill` directly. Confirm it runs. Check
/skillsto confirm it appears in the listing.
8. Pre-approve tools if appropriate
If your skill always uses certain tools, pre-approve them via allowed-tools to avoid the per-use approval dialog:
`yaml
description: Runs the test suite and summarises failures. allowed-tools:
- Bash(npm test*)
- Bash(npx vitest*)
`
This makes the skill flow without interruption while keeping unrelated tool use under approval.
Skill vs CLAUDE.md — the line you should hold
`CLAUDE.md` is for always-on facts. Skills are for triggered procedures.
Most teams put too much in CLAUDE.md. The reason matters: CLAUDE.md loads on every session. A 200-line deployment checklist in CLAUDE.md costs tokens on every turn, even when you are asking Claude to rename a variable. Skills load only when their description matches your prompt — they cost zero context budget until invoked.
The right split:
| Belongs in `CLAUDE.md` | Belongs in a skill |
|---|---|
| "We use Convex for backend" | "How to add a new Convex mutation" |
| "Path alias: `@/` maps to `src/`" | "How to refactor an import path across the codebase" |
| "Never run `taskkill /IM node.exe`" | "How to find and kill a stuck dev server process" |
| "British English throughout" | "Convert American English copy to British English" |
| "Tests must hit a real database" | "How to write a Vitest integration test" |
When a section of CLAUDE.md grows from a fact into a procedure, move it to a skill. Your CLAUDE.md should stay thin. Your skills folder can grow to dozens.
Sharing skills across a team
Four levels of sharing, in priority order from most to least authoritative.
1. Project skills (.claude/skills/ committed to git)
The primary team-sharing pattern. Commit your .claude/skills/ directory to version control. Every developer cloning the repo gets the skills automatically. New skills appear with the next pull.
Security note: project skills can grant broad tool access via allowed-tools. Review the skills before trusting a repo. Claude Code prompts for workspace trust the first time you open a repo with skills — accept only if you trust the source.
2. Personal skills (~/.claude/skills/)
Your skills, your machine, all projects. Useful for cross-project workflows you have developed personally — commit message conventions you use everywhere, code-review patterns, debugging approaches.
3. Plugin-distributed skills
The right answer for sharing across multiple projects, multiple repos, or with the wider community.
Plugin structure:
` my-plugin/ ├── .claude-plugin/ │ └── plugin.json # Manifest: name, description, version, author └── skills/ └── my-skill/ └── SKILL.md `
Plugin skills are always namespaced (my-plugin:my-skill), so they never conflict with skills from other plugins.
Plugins distribute via marketplaces — host in a private git repo for internal team plugins, or submit to Anthropic's official marketplace at claude.ai/settings/plugins/submit for public distribution.
For UK SMEs running multi-team or multi-client work, the plugin pattern is what makes skills sustainable. We package shared skills as a plugin (ampliflow-engineering), version it, and distribute it across all client repos. New skills go to all teams with one update.
4. Enterprise managed deployment
For organisations that need centralised governance — compliance teams enforcing review checklists, security teams enforcing scan procedures — Claude Code supports enterprise managed settings that deploy skills organisation-wide. Enterprise-level skills cannot be overridden by users.
This is rarely needed for SMEs but matters for regulated UK industries (financial services, healthcare, legal) where standardisation is a compliance requirement.
Monorepo discovery — the detail that saves real time
Claude Code automatically discovers skills from `.claude/skills/` in the starting directory and every parent up to the repo root. When editing files in a subdirectory, it also looks in nested .claude/skills/ (e.g. packages/frontend/.claude/skills/).
For a monorepo, this means:
apps/marketing-site/.claude/skills/— skills only relevant to the marketing sitepackages/ui/.claude/skills/— skills only relevant when working in the shared UI package.claude/skills/(repo root) — skills available everywhere
No configuration. No setup. Just put skills in the right folder and the right ones load when working in the right place.
The seven anti-patterns (and how to avoid each)
Bad skills are easy to write. Diagnostic patterns to look out for.
1. Vague description that never triggers
"A skill for code reviews" gives Claude nothing to match against. Rewrite as a trigger sentence: "Use when reviewing pull requests, checking code quality, or the user asks for feedback on their implementation."
2. The mega-skill trap
Bundling commits, PR creation, branch naming, and changelog generation into one SKILL.md. Mega-skills load late, fire less reliably, and confuse Claude when sections conflict. One responsibility per skill.
3. Long procedures in CLAUDE.md instead of skills
A 200-line deployment checklist in CLAUDE.md costs tokens on every turn. Move it to a skill. CLAUDE.md stays thin.
4. Over-scripting
Shipping complex shell or Python scripts when plain imperative markdown instructions would work. Markdown is easier to maintain, easier to audit, and Claude is better at following written instructions than executing custom scripts.
5. Wrong folder for the intended scope
Putting a personal cross-project skill in .claude/skills/ (project only) or committing a project-specific skill to ~/.claude/skills/ (global). Silent failures with no error message.
6. Ignoring invocation control for dangerous skills
A /deploy skill without disable-model-invocation: true means Claude can decide to deploy because the code "looks ready." Catastrophic. High-stakes actions must be user-only.
7. Exceeding token budget silently
Default budget for skill descriptions is 1% of model context window. With many skills loaded, the budget overflows and Claude loses context for lower-priority skills with no visible warning. Use /doctor to audit. Set skillListingBudgetFraction to increase. Switch low-priority skills to name-only in skillOverrides to free budget.
How Ampliflow runs skills for UK clients
A three-tier skill architecture, layered per project.
Tier 1 — Universal skills (in ~/.claude/skills/): the patterns we use across every project. Commit message format, code review checklist, our CLAUDE.md writing convention. Maybe 8-10 skills. Stable.
Tier 2 — Stack skills (in a plugin we distribute internally, ampliflow-engineering): the patterns specific to our stack — Next.js + Convex + Sanity + shadcn workflows, our deployment procedure, our test patterns. 15-20 skills. Versioned. Updated quarterly.
Tier 3 — Project skills (in each repo's .claude/skills/): the patterns specific to one client codebase — their domain logic, their custom conventions, their oddities. 5-15 skills per project. Lives with the code.
This three-tier split keeps the skill library maintainable. Universal skills almost never change. Stack skills change quarterly with the stack. Project skills change as the project evolves. No tier becomes a dumping ground.
For UK clients new to Claude Code, we set up the universal + stack tiers automatically as part of the Claude Code rollout and add project skills as we discover them. The patterns compound — every new client benefits from the patterns we have refined for previous clients.
Frequently asked questions
What is a Claude Code skill and how is it different from a custom command?
A skill is a directory containing a SKILL.md file with YAML frontmatter and markdown instructions. It can include supporting files (templates, examples, scripts). Custom commands (.claude/commands/foo.md) were the older format and are now considered a subset of skills. Skills win when both define the same name. New work should use skills.
Where do I put skills in Claude Code?
Personal skills (across all your projects): ~/.claude/skills/my-skill/. Project skills (this repo only): .claude/skills/my-skill/. Plugin skills (distributed across teams): inside a plugin directory at my-plugin/skills/my-skill/.
How does Claude know when to use a skill automatically?
By matching your prompt against each skill's description field. The description is a fuzzy-match trigger, not documentation — write it as a "Use when…" sentence with the verbs users naturally type. Combined description and when_to_use are truncated at 1,536 characters in the skill listing.
Can I share Claude Code skills with my team?
Yes. The simplest pattern is to commit .claude/skills/ to your repo — every developer who clones gets the skills. For sharing across multiple projects or with the wider community, package as a plugin and distribute via a marketplace.
What goes in the SKILL.md frontmatter?
At minimum: description (the auto-trigger sentence). Optionally: when_to_use, disable-model-invocation, user-invocable, allowed-tools, paths, model, effort, context: fork. The full reference is in the official Anthropic docs.
What is the difference between skills and CLAUDE.md?
CLAUDE.md is for always-on facts that load every session (architecture decisions, tech stack, code style). Skills are for triggered procedures that load only when their description matches your prompt. Long procedures in CLAUDE.md bloat the main context and waste tokens.
How do I stop Claude from triggering a skill automatically?
Add disable-model-invocation: true to the frontmatter. The skill becomes user-only — you can still invoke it with /skill-name, but Claude cannot trigger it autonomously. Mandatory for any skill with side effects (deploy, send, commit, write to production).
How many skills should I have active at once?
Anthropic's documentation suggests under 20 active skills before description-budget overflow becomes a concern. Practically, most teams stabilise at 8-15 active skills per project. Use /doctor to audit and skillOverrides to silence low-priority ones.
Can Claude Code skills run scripts and shell commands?
Yes, in two ways. The !command` syntax runs a shell command and injects its output into the prompt (preprocessing — Claude does not run the command). Skills can also include executable scripts in their directory and reference them via ${CLAUDE_SKILL_DIR}/scripts/foo.sh`.
Related reading
- ↑ What is Claude Code? A UK Business Guide — the foundational pillar
- ↔ How to Install Claude Code — UK Business Guide — the install guide where the skills folder gets created
- ↔ Claude Code MCP Servers — 7 Worth Installing — the other big extensibility lever beyond skills
- ↔ Claude Code Pricing 2026 — including the agent-team and MCP token-cost traps that interact with skills
- ↔ Hermes Agent Skills — Build Custom Extensions — the parallel concept on the Hermes side, for operational-automation skills
What should you do next?
Skills become valuable around the moment your team writes the second one — when you stop thinking of skills as a curiosity and start thinking of them as the team's institutional memory. The first three skills are the hardest because you do not yet have the patterns. We can help with that.
Book a free Claude Code working session →
Forty-five minutes, free, no commitment. We cover your team's most repeated workflows, scope your first three skills, and walk through the patterns that prevent your skill library from becoming unmaintainable. You leave with a skill set you can write that afternoon.