Claude Code skills: packaged expertise the agent loads on demand

A skill is a folder the agent opens only when it needs to. That laziness is the entire design: you can ship a great deal of expertise without paying for any of it on the turns that do not use it.

By the Continuum team. We build a workbench that runs Claude Code, Codex, and their peers, so the model rates quoted here are the ones our own cost analytics ship with.

The short version

A skill is a directory containing SKILL.md with YAML frontmatter, optionally alongside scripts and reference files. Only the name and description sit in context; the body loads when the skill is invoked, by you with /skill-name or by the model when the description matches. Custom commands and skills are now the same mechanism, so .claude/commands/deploy.md and .claude/skills/deploy/SKILL.md both produce /deploy.

What you need to know
  • A skill is a directory with SKILL.md at its root. The directory name is the command.
  • Only name and description stay in context. The body loads on invocation.
  • That is the difference from CLAUDE.md, which is sent at the start of every session.
  • Custom commands are skills now. The two directories produce the same slash command.
  • The description is the routing logic, and it is capped at 1,536 characters. Key use case first.

The shape of a skill

A skill is a directory, not a file.
.claude/skills/
  release-notes/
    SKILL.md          <- required, the entrypoint
    template.md       <- optional reference, read on demand
    scripts/
      collect.sh      <- optional script, executed not read
.claude/skills/release-notes/SKILL.md
---
name: release-notes
description: Writes release notes from merged pull requests between two git tags. Use when asked to draft release notes, a changelog entry, or a summary of what shipped.
allowed-tools: Bash(git log *) Bash(gh pr list *)
---

# Release notes

## Gathering the input

Run `${CLAUDE_SKILL_DIR}/scripts/collect.sh <from-tag> <to-tag>`. It outputs one
line per merged PR with number, title, and author.

## Writing them

Follow `template.md` exactly. Rules that matter:

- Group by user-visible impact, never by component.
- One line per change, written from the user point of view. "Sessions no
  longer drop on reconnect", not "fixed WebSocket handler".
- Omit anything invisible to a user: refactors, test changes, CI.
- Breaking changes go first, under their own heading, with the migration.
- Never invent a change that is not in the input.

Where a skill can live, and who gets it.

LocationPathApplies to
EnterpriseManaged settingsEveryone in the organisation
Personal~/.claude/skills/<name>/SKILL.mdAll your projects
Project.claude/skills/<name>/SKILL.mdThis project, committed
Plugin<plugin>/skills/<name>/SKILL.mdWherever the plugin is enabled
  • On a name clash, enterprise beats personal beats project, and any of them beats a bundled skill of the same name.
  • Plugin skills are namespaced plugin-name:skill-name, so they cannot collide.
  • Project skills also load from every parent directory up to the repository root, so starting in a subdirectory still picks up the root ones.
  • Nested .claude/skills/ below your starting directory load lazily, the first time the agent reads or edits a file in that subtree. A monorepo package can therefore ship skills that only appear when you work on it.
  • Skill directories are watched live: adding or editing a SKILL.md takes effect in the running session with no restart.

Why progressive disclosure is the whole point

This is the property that makes skills worth using rather than a stylistic alternative to project memory.

What is in context, and when.

ContentAlways loaded?Cost
CLAUDE.mdYes, at every session startPaid on every session forever
Skill name and descriptionYes, in the skill listingSmall, but budgeted
Skill bodyNo, only when invokedPaid only when used
Bundled reference filesNo, only if the agent reads onePaid only when read

The listing is not free, though, and it is budgeted. Claude Code allocates roughly 1 percent of the model context window to skill names and descriptions. The listing always contains every skill name; when it overflows, descriptions are dropped starting with the skills you invoke least. Each entry combining description and when_to_use is capped at 1,536 characters regardless of budget.

Finding out what your listing costs.
/doctor        # estimates the listing cost and names the biggest contributors
/context       # the Skills row reports the listing size after the budget is applied
Context cost across four moments in a session: at session start and while you ask only the skill listing is loaded, when the skill fires the SKILL.md body is added, and only if a bundled file is opened is that added too, all compared against a dashed line showing the same content held permanently in CLAUDE.md WHAT A SKILL COSTS height = tokens in context reference file SKILL.md body the same content in CLAUDE.md, paid at every session start name + description only, ~1% of the window session start every skill listed you ask descriptions matched the skill fires SKILL.md body loads it opens a file reference file read You ship the whole folder. You pay for the part the turn actually needed.

The frontmatter, field by field

Every field is optional. Only description is genuinely recommended, because it is how the model decides the skill applies.

The fields worth knowing, per Claude Code documentation in August 2026.

FieldWhat it does
descriptionWhat the skill does and when to use it. The routing logic. Capped at 1,536 characters with when_to_use
when_to_useExtra trigger phrases, appended to the description in the listing
nameDisplay label. For personal and project skills the directory name still sets the command
disable-model-invocationtrue means only you can run it. Use for anything with side effects
user-invocablefalse hides it from the / menu. Use for background knowledge
allowed-toolsPre-approves tools for the turn that invokes the skill. Clears on your next message
disallowed-toolsRemoves tools from the pool while the skill is active
modelModel for the rest of the current turn. Not saved to settings
effortEffort level while this skill is active. Overrides the session level
context: forkRuns the skill in a subagent instead of your conversation
pathsGlobs that limit automatic activation to matching files
argument-hint / argumentsAutocomplete hint, and named positional arguments for $name substitution

Pre-approving tools, and the trust question

A commit skill that does not prompt on every git call.
---
name: commit
description: Stage and commit the current changes
disable-model-invocation: true
allowed-tools: Bash(git add *) Bash(git commit *) Bash(git status *)
---

Stage the relevant changes and commit with a message that explains why,
not what. Never use --no-verify. Never commit to main.

Skills, commands, and subagents

Custom commands were merged into skills. A file at .claude/commands/deploy.md and a directory at .claude/skills/deploy/SKILL.md both create /deploy and behave the same way. Existing command files keep working; skills add a directory for supporting files, frontmatter, and automatic invocation.

Two mechanisms that overlap and are not interchangeable.

SkillSubagent
Invoked byYou with /name, or the modelThe model, when delegating
ContextYours, unless context: forkA fresh one
Loaded up frontDescription onlyDescription only
Own tool permissionsFor the invoking turnFor its whole run
Own model and effortFor the invoking turnFor its whole run
Best forKnowledge and procedureIsolated work with a lot of reading
  • Use a skill when the agent should know how to do something in the conversation you are already having.
  • Use a skill with context: fork when the skill is a self-contained task and you want it out of your context. It runs in the background by default; set background: false to wait for the result in the invoking turn.
  • Use a subagent when you want a reusable agent type with its own system prompt and tool set that the model delegates to on its own judgement.

Writing one that actually fires

The most common complaint about skills is that they never trigger, and the cause is nearly always the description.

Weak descriptionStrong description
"Release helper""Writes release notes from merged PRs between two git tags. Use when asked to draft release notes, a changelog entry, or a summary of what shipped."
"Database stuff""Writes and reviews Drizzle migrations. Use when adding, altering, or dropping a table or column."
"Style guide""Applies this repository React conventions. Use when creating or editing a component under src/ui/."

The three failures and what causes each.

SymptomCauseFix
Never triggersDescription names the topic, not the triggerRewrite as "does X. Use when Y."
Never triggers, and /name worksMalformed YAML; the body loaded with empty metadataRun claude --debug to see the parse error
Triggers on the wrong requestsDescription too broadNarrow it, or set disable-model-invocation: true
Stops mattering after one replyContent is present; the model chose otherwiseStrengthen the instructions, or enforce with a hook
Lost after a long sessionCompaction budget dropped itRe-invoke it, and keep the top of the file load-bearing

That last row is worth stating precisely. Once invoked, the rendered SKILL.md stays in the conversation for the rest of the session, and the file is not re-read on later turns. After a compaction, Claude Code re-attaches the most recent invocation of each skill, keeping the first 5,000 tokens of each within a 25,000 token combined budget, newest first. Invoke six skills in one long session and the earliest are simply gone.

Questions people ask

A directory containing SKILL.md with YAML frontmatter, optionally with scripts and reference files. Claude keeps the name and description in context and reads the body only when the skill is invoked, either by you with /skill-name or by the model when the description matches.

CLAUDE.md loads at the start of every session, so its length is a permanent cost. A skill body loads only when it is used. Long procedural content belongs in a skill; short project facts belong in CLAUDE.md.

Yes. A file at .claude/commands/deploy.md and a directory at .claude/skills/deploy/SKILL.md both create /deploy and work the same way. Existing command files keep working, and skills add supporting files, frontmatter, and automatic invocation.

Personal skills in ~/.claude/skills/, project skills in .claude/skills/ committed to the repo, plugin skills under a plugin, and enterprise skills through managed settings. On a name clash, enterprise beats personal beats project.

Almost always the description. Write it as "does X. Use when Y." and name the specific situations. If /skill-name works but automatic invocation never does, the YAML is probably malformed, which loads the body with empty metadata. Run claude --debug to see the parse error.

Yes. Bundle them in the skill directory, reference them from SKILL.md using ${CLAUDE_SKILL_DIR} so the path resolves anywhere, and pre-approve the command with allowed-tools if you do not want a prompt each time.

A skill when the agent should know how to do something in your current conversation. A subagent when the work should happen in a fresh context. A skill with context: fork is the middle option: your task, run in isolation.

The skill listing is budgeted at about 1 percent of the model context window, and each entry is capped at 1,536 characters. When the listing overflows, descriptions are dropped starting with the skills you invoke least. Run /doctor to see the cost and its biggest contributors.

Sources

Every figure above was read from these pages on August 2026. Vendors reprice without notice; if you find a stale number, tell us.

  1. Claude Code: extend Claude with skills
  2. Claude Code: explore the context window
  3. Claude Code: best practices
Try it

Skills, visible
in the palette.

Continuum scans project and personal skill directories and surfaces them as you type, across every repo you work in.

free app · your subscriptions · local-first