Claude Skills
Overview
Agent Skills = open format by Anthropic (2025) for extending agents. Claude Code adds invocation control, subagent execution, and dynamic context injection.
Progressive Disclosure
- Discovery: only
name+descriptionloaded at startup. - Activation: task matches description → full
SKILL.mdread. - Execution: follows instructions, loads referenced files or runs scripts.
Layout & Locations
my-skill/
├── SKILL.md # required: frontmatter (name, description) + instructions
├── scripts/ # optional executable code
├── references/ # optional docs
└── assets/ # optional templates
| Scope | Path |
|---|---|
| Personal | ~/.claude/skills/<name>/SKILL.md |
| Project | .claude/skills/<name>/SKILL.md |
| Plugin | <plugin>/skills/<name>/SKILL.md |
| Enterprise | managed settings dir .claude/skills/ |
| Nested | <subdir>/.claude/skills/<name>/SKILL.md |
| claude.ai account | synced to ~/.claude/skills/synced/ |
/skills lists user skills (built-ins don't appear). Invoke directly with /skill-name args or let Claude trigger it.
Bundled: /doctor, /code-review (/review), /simplify, /batch, /debug, /loop, /claude-api, /verify, /run, /run-skill-generator, /skill-doctor (context cost per skill), /workflow-authoring (only with dynamic workflows). Disable with disableBundledSkills. /reload-skills picks up new skill folders.
Kinds: reference (adds knowledge) vs task (does something).
Frontmatter
All fields optional; description recommended. Unknown fields are ignored.
| Field | Effect |
|---|---|
name | Command name (defaults to folder name) |
description, when_to_use | Trigger text (combined, truncated at 1,536 chars in the listing) |
argument-hint, arguments | Autocomplete hint; named args for $name substitution |
disable-model-invocation: true | Only you can invoke it |
user-invocable: false | Hidden from / menu, Claude-only |
allowed-tools, disallowed-tools | Pre-approve / remove tools while active |
model, effort | Overrides for the turn |
context: fork + agent: Explore | Run in an isolated subagent (background: wait or not) |
hooks | Hooks registered while the skill runs |
paths | Globs that limit automatic activation |
shell | bash (default) or powershell for injected commands |
Substitutions: $ARGUMENTS, $ARGUMENTS[N]/$N, $name, ${CLAUDE_SESSION_ID}, ${CLAUDE_EFFORT}, ${CLAUDE_SKILL_DIR}, ${CLAUDE_PROJECT_DIR}, ${CLAUDE_PLUGIN_ROOT}.
Dynamic injection: inline !`gh pr diff` or a fenced block opened with ```!. A non-zero exit aborts the skill (append || true). disableSkillShellExecution: true turns it off.
---
name: pr-summary
description: Summarize changes in a pull request
context: fork
agent: Explore
allowed-tools: Bash(gh *)
---
PR diff: !`gh pr diff`
Summarize $ARGUMENTS ...
Scripts
- List scripts in SKILL.md with relative paths (
bash scripts/validate.sh "$INPUT"). - One-off commands can be inline (
go run golang.org/x/tools/cmd/goimports@v0.28.0 .). - Agents run non-interactive shells: a script that prompts will hang.
Writing a Description that Triggers
- Write it as an instruction: "Use this skill when the user wants to…"
- Describe the user's goal, not internals; list contexts and trigger words ("even if they don't say 'ETL'").
- Combined
description+when_to_useis cut at 1,536 chars, so put the key use case first (the open Agent Skills spec says 1024 fordescription). - Agents skip skills for tasks they can do unaided.
Testing
Trigger eval (eval_queries.json): 20 queries (10 should trigger, 10 shouldn't), run each ≥3x, keep a 60/40 train/validation split; trigger rate > 0.5 is a pass.
[{ "query": "add a profit margin column to ~/data/q4.xlsx", "should_trigger": true },
{ "query": "convert this json to yaml", "should_trigger": false }]
Output eval: each case = realistic prompt + expected_output description + optional files.
Disable / Restrict
- Deny the
Skilltool in/permissionsto disable all. Skill(commit)allow,Skill(deploy *)deny for specific ones.
Related: Claude Subagents and Teams, Claude MCP and Plugins, Claude Permissions