How a skill loads: progressive disclosure
- Descriptionalways in context, so Claude knows it exists
- Invokedby you (
/name) or by Claude when relevant - SKILL.md bodyfull instructions load and stay for the session
- Supporting files
reference.md, scripts — read only if needed
Commands and skills are now one mechanism
Claude Code used to have two ideas: custom slash commands (a Markdown file in .claude/commands/) and skills (a folder with a SKILL.md). The current documentation says custom commands have been merged into skills. A file at .claude/commands/deploy.md and a skill at .claude/skills/deploy/SKILL.md both create /deploy and behave the same way. Existing command files keep working; if both exist with the same name, the skill wins.
Command file versus skill folder
.claude/commands/review.md
- A single Markdown file
- Creates
/review - Still supported — existing files keep working
- No room for bundled reference files or scripts
.claude/skills/review/SKILL.md
- A folder:
SKILL.mdplus any supporting files - Creates
/review— and wins if both exist - Frontmatter controls who invokes it and how it runs
- The recommended format for new workflows
Where a skill lives decides who gets it
The same scoping logic as CLAUDE.md applies (see 3.1). A skill in the repository is shared through version control; a skill in your home directory follows you across projects but no one else sees it.
| Location | Path | Who can use it |
|---|---|---|
| Project | .claude/skills/<name>/SKILL.md (or .claude/commands/<name>.md) | Everyone who clones the repo |
| Personal | ~/.claude/skills/<name>/SKILL.md (or ~/.claude/commands/) | You, in every project |
| Enterprise | Deployed through managed settings | Everyone in the organisation |
| Plugin | <plugin>/skills/<name>/ | Whoever installs the plugin; invoked as /plugin-name:skill-name |
| Nested | packages/api/.claude/skills/<name>/ | Discovered when Claude works in that part of the tree |
When two skills share a name, enterprise beats personal and personal beats project. Plugin skills never collide because they are namespaced. A team workflow that everyone must run the same way therefore belongs in the project’s .claude/skills/ and is reviewed like code; a personal shortcut belongs in ~/.claude/skills/.
Anatomy of a SKILL.md
A skill is YAML frontmatter followed by Markdown instructions. The frontmatter must start on the very first line, or the whole file is treated as content. The body is the prompt Claude follows when the skill runs.
---
name: fix-issue
description: Fix a GitHub issue end to end. Use when asked to fix issue #N.
argument-hint: [issue-number]
disable-model-invocation: true # only a person can start this
allowed-tools: Bash(gh issue view *) Bash(npm test *)
---
Fix GitHub issue $ARGUMENTS.
## Recent commits (injected before Claude reads this)
!`git log --oneline -5`
1. Run `gh issue view $ARGUMENTS` to read the issue
2. Find the relevant code and existing patterns
3. Write a failing test that reproduces the issue
4. Fix it and run `npm test` until it passes
5. Summarise the change and the test you added| Field | What it does |
|---|---|
description | What the skill does and when to use it. Claude reads this to decide whether to invoke the skill. Combined with when_to_use, it is truncated at 1,536 characters in the listing — put the key use case first. |
argument-hint | Autocomplete hint such as [issue-number]. |
disable-model-invocation | true means only a person can run it; Claude can’t trigger it and its description is not loaded. |
user-invocable | false hides it from the / menu; Claude can still load it as background knowledge. |
allowed-tools | Pre-approves the listed tools for the turn that invokes the skill, so they run without a permission prompt. |
disallowed-tools | Removes tools from Claude’s pool while the skill is active. |
context: fork + agent | Runs the skill in an isolated subagent; agent picks which one (for example Explore). |
model / effort | Override the model or effort level for this skill. |
paths | Glob patterns; Claude loads the skill automatically only when working with matching files. |
In the body, $ARGUMENTS expands to everything typed after the command, and $0, $1 (short for $ARGUMENTS[0], $ARGUMENTS[1]) pick out positional arguments. An exclamation mark followed by a backticked command, like the git log line above, runs that command before Claude sees the skill and pastes its output in — useful for feeding live state into the prompt. Supporting files in the skill folder (a reference.md, a script) are linked from SKILL.md and read only when needed.
Who may invoke it
By default both you and Claude can invoke a skill: you by typing /name, Claude by matching your request against the description. That default is right for knowledge (“our API conventions”) but wrong for anything with side effects. You don’t want Claude deciding to deploy because your code looks ready.
Choosing the invocation setting
- Has side effects (deploy, send)Person onlytyped as
/name; Claude can’t start it - Background knowledge onlyClaude onlyloaded when relevant; hidden from menu
- Useful either wayEitherthe default setting
disable-model-invocation: true. “Claude only” is user-invocable: false. Leave both unset for the default.Running a skill in isolation with context: fork
A normal skill runs inline: its instructions join the main conversation and everything it reads fills your context. With context: fork, the skill runs in a subagent with its own fresh context; the skill body becomes the subagent’s task, and only its result comes back. This suits skills that read a lot (codebase research, log analysis) or that you want kept away from the main session’s history. The subagent does not see your conversation, so the skill must carry everything it needs.
A forked skill, message by message
/trace-auth token refreshTraps the wrong answers are built from
| Tempting but wrong | Do this instead |
|---|---|
| Leaving a deploy or “send” workflow with default invocation | Set disable-model-invocation: true so only a person can trigger side effects. |
Using allowed-tools to lock a skill down | It only pre-approves tools; use disallowed-tools, a restricted agent via context: fork, or permission rules to restrict. |
Putting a team workflow in ~/.claude/skills/ | Commit it to the project’s .claude/skills/ so everyone gets the same version. |
| A vague description such as “helper for stuff” | State what it does and when to use it, key use case first, so Claude can match requests to it. |
| Running a file-heavy research skill inline | Add context: fork so the reading stays in a subagent and only the summary returns. |
You should now be able to
- Create a skill (or legacy command file) at project or personal scope according to who should use it.
- Write frontmatter that sets the description, argument hint and invocation control.
- Use
$ARGUMENTS, positional arguments and!command injection in a skill body. - Explain what
allowed-toolsdoes and does not do, and how to restrict tools instead. - Decide when a skill should run in a forked subagent with
context: fork. - Choose between CLAUDE.md and a skill for a given piece of guidance.