File Deleted
View Diff
1> ## Documentation Index
2> Fetch the complete documentation index at: https://code.claude.com/docs/llms.txt
3> Use this file to discover all available pages before exploring further.
4
5# Extend Claude with skills
6
7> Create, manage, and share skills to extend Claude's capabilities in Claude Code. Includes custom commands and bundled skills.
8
9Skills extend what Claude can do. Create a `SKILL.md` file with instructions, and Claude adds it to its toolkit. Claude uses skills when relevant, or you can invoke one directly with `/skill-name`.
10
11Create 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. Unlike CLAUDE.md content, a skill's body loads only when it's used, so long reference material costs almost nothing until you need it.
12
13<Note>
14 For built-in commands like `/help` and `/compact`, and bundled skills like `/debug` and `/code-review`, see the [commands reference](/en/commands).
15
16 **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 work the same way. Your existing `.claude/commands/` files keep working. Skills add optional features: a directory for supporting files, frontmatter to [control whether you or Claude invokes them](#control-who-invokes-a-skill), and the ability for Claude to load them automatically when relevant.
17</Note>
18
19Claude Code skills follow the [Agent Skills](https://agentskills.io) open standard, which works across multiple AI tools. Claude Code extends the standard with additional features like [invocation control](#control-who-invokes-a-skill), [subagent execution](#run-skills-in-a-subagent), and [dynamic context injection](#inject-dynamic-context).
20
21## Bundled skills
22
23Claude Code includes a set of bundled skills that are available in every session unless disabled with the [`disableBundledSkills`](/en/settings#available-settings) setting, including `/code-review`, `/batch`, `/debug`, `/loop`, and `/claude-api`. Unlike most built-in commands, which execute fixed logic directly, bundled skills are prompt-based: they give Claude detailed instructions and let it orchestrate the work using its tools. You invoke them the same way as any other skill, by typing `/` followed by the skill name.
24
25Bundled skills are listed alongside built-in commands in the [commands reference](/en/commands), marked **Skill** in the Purpose column.
26
27### Run and verify your app
28
29Three bundled skills work together to launch your app and confirm changes against the running app instead of just tests:
30
31| Skill | Purpose |
32| :--------------------- | :---------------------------------------------------------------------------------------------------------------- |
33| `/run` | Launch and drive your app to see a change working |
34| `/verify` | Build and run your app to confirm a code change does what it should, without falling back to tests or type checks |
35| `/run-skill-generator` | Teach `/run` and `/verify` how to build and launch your project |
36
37{/* min-version: 2.1.145 */}All three skills require Claude Code v2.1.145 or later.
38
39`/run` and `/verify` work without setup. They infer the launch from your project type (CLI, server, TUI, browser-driven) and from what's in your README, `package.json`, or `Makefile`. That inference gets unreliable for projects that need anything beyond a standard launch: a database, an env file, a graphical session, a multi-step build.
40
41`/run-skill-generator` records the recipe instead. It gets your app running from a clean environment, captures what worked (the install commands, the env vars, the launch script), and commits it as a per-project skill at `.claude/skills/run-<name>/`. After that, `/run`, `/verify`, and any other agent in the repo follow the recorded recipe instead of rediscovering it. Run `/run-skill-generator` once per project, and again if the build or launch process changes.
42
43## Getting started
44
45### Create your first skill
46
47This example creates a skill that summarizes the uncommitted changes in your git repository and flags anything risky. It pulls the live diff into the prompt before Claude reads it, so the response is grounded in your actual working tree rather than what Claude can guess from open files. Claude loads the skill automatically when you ask about your changes, or you can invoke it directly with `/summarize-changes`.
48
49<Steps>
50 <Step title="Create the skill directory">
51 Create a directory for the skill in your personal skills folder. Personal skills are available across all your projects.
52
53 ```bash theme={null}
54 mkdir -p ~/.claude/skills/summarize-changes
55 ```
56 </Step>
57
58 <Step title="Write SKILL.md">
59 Every skill needs a `SKILL.md` file with two parts: YAML frontmatter between `---` markers that tells Claude when to use the skill, and markdown content with the instructions Claude follows when the skill runs. The directory name becomes the command you type, and the `description` helps Claude decide when to load the skill automatically.
60
61 Save this to `~/.claude/skills/summarize-changes/SKILL.md`:
62
63 ```yaml theme={null}
64 ---
65 description: Summarizes uncommitted changes and flags anything risky. Use when the user asks what changed, wants a commit message, or asks to review their diff.
66 ---
67
68 ## Current changes
69
70 !`git diff HEAD`
71
72 ## Instructions
73
74 Summarize the changes above in two or three bullet points, then list any risks you notice such as missing error handling, hardcoded values, or tests that need updating. If the diff is empty, say there are no uncommitted changes.
75 ```
76
77 The `` !`git diff HEAD` `` line uses [dynamic context injection](#inject-dynamic-context): Claude Code runs the command and replaces the line with its output before Claude sees the skill content, so the instructions arrive with the current diff already inlined.
78 </Step>
79
80 <Step title="Test the skill">
81 Open a git project, make a small edit to any file, and start Claude Code by running `claude`. You can test the skill two ways.
82
83 **Let Claude invoke it automatically** by asking something that matches the description:
84
85 ```text theme={null}
86 What did I change?
87 ```
88
89 **Or invoke it directly** with the skill name:
90
91 ```text theme={null}
92 /summarize-changes
93 ```
94
95 Either way, Claude should respond with a short summary of your edit and a list of risks.
96 </Step>
97</Steps>
98
99### Where skills live
100
101Where you store a skill determines who can use it:
102
103| Location | Path | Applies to |
104| :--------- | :-------------------------------------------------- | :----------------------------- |
105| Enterprise | See [managed settings](/en/settings#settings-files) | All users in your organization |
106| Personal | `~/.claude/skills/<skill-name>/SKILL.md` | All your projects |
107| Project | `.claude/skills/<skill-name>/SKILL.md` | This project only |
108| Plugin | `<plugin>/skills/<skill-name>/SKILL.md` | Where plugin is enabled |
109
110When skills share the same name across levels, enterprise overrides personal, and personal overrides project. Plugin skills use a `plugin-name:skill-name` namespace, so they cannot conflict with other levels. If you have files in `.claude/commands/`, those work the same way, but if a skill and a command share the same name, the skill takes precedence.
111
112<Note>
113 Add a `.claude-plugin/plugin.json` to a skill folder and it loads as a [plugin](/en/plugins-reference#skills-directory-plugins) named `<name>@skills-dir`, so it can bundle agents, hooks, and MCP servers. In a project's `.claude/skills/`, this requires accepting the workspace trust dialog first.
114</Note>
115
116#### Live change detection
117
118Claude Code watches skill directories for file changes. Adding, editing, or removing a skill under `~/.claude/skills/`, the project `.claude/skills/`, or a `.claude/skills/` inside an `--add-dir` directory takes effect within the current session without restarting. Creating a top-level skills directory that did not exist when the session started requires restarting Claude Code so the new directory can be watched.
119
120<Note>
121 Live change detection covers `SKILL.md` text only. For a skill folder that is also a [plugin](/en/plugins-reference#skills-directory-plugins), changes to `hooks/`, `.mcp.json`, `agents/`, and `output-styles/` need `/reload-plugins` to take effect.
122</Note>
123
124#### Automatic discovery from parent and nested directories
125
126Project skills load from `.claude/skills/` in your starting directory and in every parent directory up to the repository root, so starting Claude in a subdirectory still picks up skills defined at the root. When you work with files in subdirectories below your starting directory, Claude Code also discovers skills from nested `.claude/skills/` directories on demand. For example, if you're editing a file in `packages/frontend/`, Claude Code also looks for skills in `packages/frontend/.claude/skills/`. This supports monorepo setups where packages have their own skills.
127
128Each skill is a directory with `SKILL.md` as the entrypoint:
129
130```text theme={null}
131my-skill/
132├── SKILL.md # Main instructions (required)
133├── template.md # Template for Claude to fill in
134├── examples/
135│ └── sample.md # Example output showing expected format
136└── scripts/
137 └── validate.sh # Script Claude can execute
138```
139
140The `SKILL.md` contains the main instructions and is required. Other files are optional and let you build more powerful skills: templates for Claude to fill in, example outputs showing the expected format, scripts Claude can execute, or detailed reference documentation. Reference these files from your `SKILL.md` so Claude knows what they contain and when to load them. See [Add supporting files](#add-supporting-files) for more details.
141
142<Note>
143 Files in `.claude/commands/` still work and support the same [frontmatter](#frontmatter-reference). Skills are recommended since they support additional features like supporting files.
144</Note>
145
146#### Skills from additional directories
147
148The `--add-dir` flag and `/add-dir` command [grant file access](/en/permissions#additional-directories-grant-file-access-not-configuration) rather than configuration discovery, but skills are an exception: `.claude/skills/` within an added directory is loaded automatically. This exception applies only to `--add-dir` and `/add-dir`. The `permissions.additionalDirectories` setting in `settings.json` grants file access only and does not load skills. See [Live change detection](#live-change-detection) for how edits are picked up during a session.
149
150Other `.claude/` configuration such as subagents, commands, and output styles is not loaded from additional directories. See the [exceptions table](/en/permissions#additional-directories-grant-file-access-not-configuration) for the complete list of what is and isn't loaded, and the recommended ways to share configuration across projects.
151
152<Note>
153 CLAUDE.md files from `--add-dir` directories are not loaded by default. To load them, set `CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1`. See [Load from additional directories](/en/memory#load-from-additional-directories).
154</Note>
155
156## Configure skills
157
158Skills are configured through YAML frontmatter at the top of `SKILL.md` and the markdown content that follows.
159
160### Types of skill content
161
162Skill files can contain any instructions, but thinking about how you want to invoke them helps guide what to include:
163
164**Reference content** adds knowledge Claude applies to your current work. Conventions, patterns, style guides, domain knowledge. This content runs inline so Claude can use it alongside your conversation context.
165
166```yaml theme={null}
167name: api-conventions
168description: API design patterns for this codebase
169
170When writing API endpoints:
171- Use RESTful naming conventions
172- Return consistent error formats
173- Include request validation
174```
175
176**Task content** gives Claude step-by-step instructions for a specific action, like deployments, commits, or code generation. These are often actions you want to invoke directly with `/skill-name` rather than letting Claude decide when to run them. Add `disable-model-invocation: true` to prevent Claude from triggering it automatically.
177
178```yaml theme={null}
179name: deploy
180description: Deploy the application to production
181context: fork
182disable-model-invocation: true
183
184Deploy the application:
1851. Run the test suite
1862. Build the application
1873. Push to the deployment target
188```
189
190Your `SKILL.md` can contain anything, but thinking through how you want the skill invoked (by you, by Claude, or both) and where you want it to run (inline or in a subagent) helps guide what to include. For complex skills, you can also [add supporting files](#add-supporting-files) to keep the main skill focused.
191
192Keep the body itself concise. Once a skill loads, its content [stays in context across turns](#skill-content-lifecycle), so every line is a recurring token cost. State what to do rather than narrating how or why, and apply the same conciseness test you would for [CLAUDE.md content](/en/best-practices#write-an-effective-claude-md).
193
194### Frontmatter reference
195
196Beyond the markdown content, you can configure skill behavior using YAML frontmatter fields between `---` markers at the top of your `SKILL.md` file:
197
198```yaml theme={null}
199name: my-skill
200description: What this skill does
201disable-model-invocation: true
202allowed-tools: Read Grep
203
204Your skill instructions here...
205```
206
207All fields are optional. Only `description` is recommended so Claude knows when to use the skill.
208
209| Field | Required | Description |
210| :------------------------- | :---------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
211| `name` | No | Display name shown in skill listings. Defaults to the directory name. See [How a skill gets its command name](#how-a-skill-gets-its-command-name) for how this differs from the name you type to invoke the skill. |
212| `description` | Recommended | What the skill does and when to use it. Claude uses this to decide when to apply the skill. If omitted, uses the first paragraph of markdown content. Put the key use case first: the combined `description` and `when_to_use` text is truncated at 1,536 characters in the skill listing to reduce context usage. |
213| `when_to_use` | No | Additional context for when Claude should invoke the skill, such as trigger phrases or example requests. Appended to `description` in the skill listing and counts toward the 1,536-character cap. |
214| `argument-hint` | No | Hint shown during autocomplete to indicate expected arguments. Example: `[issue-number]` or `[filename] [format]`. |
215| `arguments` | No | Named positional arguments for [`$name` substitution](#available-string-substitutions) in the skill content. Accepts a space-separated string or a YAML list. Names map to argument positions in order. |
216| `disable-model-invocation` | No | Set to `true` to prevent Claude from automatically loading this skill. Use for workflows you want to trigger manually with `/name`. Also prevents the skill from being [preloaded into subagents](/en/sub-agents#preload-skills-into-subagents). Default: `false`. |
217| `user-invocable` | No | Set to `false` to hide from the `/` menu. Use for background knowledge users shouldn't invoke directly. Default: `true`. |
218| `allowed-tools` | No | Tools Claude can use without asking permission when this skill is active. Accepts a space- or comma-separated string, or a YAML list. |
219| `disallowed-tools` | No | Tools removed from Claude's available pool while this skill is active. Use for autonomous skills that should never call certain tools, such as `AskUserQuestion` for a background loop. Accepts a space- or comma-separated string, or a YAML list. The restriction clears when you send your next message. |
220| `model` | No | Model to use when this skill is active. The override applies for the rest of the current turn and is not saved to settings; the session model resumes on your next prompt. Accepts the same values as [`/model`](/en/model-config), or `inherit` to keep the active model. |
221| `effort` | No | [Effort level](/en/model-config#adjust-effort-level) when this skill is active. Overrides the session effort level. Default: inherits from session. Options: `low`, `medium`, `high`, `xhigh`, `max`; available levels depend on the model. |
222| `context` | No | Set to `fork` to run in a forked subagent context. |
223| `agent` | No | Which subagent type to use when `context: fork` is set. |
224| `hooks` | No | Hooks scoped to this skill's lifecycle. See [Hooks in skills and agents](/en/hooks#hooks-in-skills-and-agents) for configuration format. |
225| `paths` | No | Glob patterns that limit when this skill is activated. Accepts a comma-separated string or a YAML list. When set, Claude loads the skill automatically only when working with files matching the patterns. Uses the same format as [path-specific rules](/en/memory#path-specific-rules). |
226| `shell` | No | Shell to use for `` !`command` `` and ` ```! ` blocks in this skill. Accepts `bash` (default) or `powershell`. Setting `powershell` runs inline shell commands via PowerShell on Windows. Requires `CLAUDE_CODE_USE_POWERSHELL_TOOL=1`. |
227
228#### How a skill gets its command name
229
230The command you type to invoke a skill comes from where the skill file lives. The frontmatter `name` field sets the display label shown in skill listings and, except for a plugin-root `SKILL.md`, does not change what you type after `/`.
231
232The table below shows where the command name comes from for each layout:
233
234| Skill location | Command name source | Example |
235| :------------------------------------------------------------- | :--------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------- |
236| Skill directory under `~/.claude/skills/` or `.claude/skills/` | Directory name | `.claude/skills/deploy-staging/SKILL.md` → `/deploy-staging` |
237| File under `.claude/commands/` | File name without extension | `.claude/commands/deploy.md` → `/deploy` |
238| Plugin `skills/` subdirectory | Directory name, namespaced by plugin | `my-plugin/skills/review/SKILL.md` → `/my-plugin:review` |
239| Plugin root `SKILL.md` | Frontmatter `name`, with the plugin directory name as a fallback | `my-plugin/SKILL.md` with `name: review` → `/my-plugin:review`. See [Path behavior rules](/en/plugins-reference#path-behavior-rules) |
240
241The plugin-root case is the one place where `name` does set the command name, because there is no skill directory to take it from. If `name` is not set in the frontmatter, the plugin's directory name is used instead.
242
243#### Available string substitutions
244
245Skills support string substitution for dynamic values in the skill content:
246
247| Variable | Description |
248| :--------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
249| `$ARGUMENTS` | All arguments passed when invoking the skill. If `$ARGUMENTS` is not present in the content, arguments are appended as `ARGUMENTS: <value>`. |
250| `$ARGUMENTS[N]` | Access a specific argument by 0-based index, such as `$ARGUMENTS[0]` for the first argument. |
251| `$N` | Shorthand for `$ARGUMENTS[N]`, such as `$0` for the first argument or `$1` for the second. |
252| `$name` | Named argument declared in the [`arguments`](#frontmatter-reference) frontmatter list. Names map to positions in order, so with `arguments: [issue, branch]` the placeholder `$issue` expands to the first argument and `$branch` to the second. |
253| `${CLAUDE_SESSION_ID}` | The current session ID. Useful for logging, creating session-specific files, or correlating skill output with sessions. |
254| `${CLAUDE_EFFORT}` | The current effort level: `low`, `medium`, `high`, `xhigh`, or `max`. Ultracode is not a distinct level and reports as `xhigh`. Use this to adapt skill instructions to the active effort setting. |
255| `${CLAUDE_SKILL_DIR}` | The directory containing the skill's `SKILL.md` file. For plugin skills, this is the skill's subdirectory within the plugin, not the plugin root. Use this in bash injection commands to reference scripts or files bundled with the skill, regardless of the current working directory. |
256
257Indexed arguments use shell-style quoting, so wrap multi-word values in quotes to pass them as a single argument. For example, `/my-skill "hello world" second` makes `$0` expand to `hello world` and `$1` to `second`. The `$ARGUMENTS` placeholder always expands to the full argument string as typed.
258
259To include a literal `$` before a digit, `ARGUMENTS`, or a declared argument name, such as `$1.00` in prose, escape it with a backslash: `\$1.00`. A backslash before any other `$` is left unchanged. Only a single backslash directly before the token escapes it. A doubled backslash such as `\\$1` leaves both backslashes in place, and `$1` still expands to the argument value.
260
261**Example using substitutions:**
262
263```yaml theme={null}
264name: session-logger
265description: Log activity for this session
266
267Log the following to logs/${CLAUDE_SESSION_ID}.log:
268
269$ARGUMENTS
270```
271
272### Add supporting files
273
274Skills can include multiple files in their directory. This keeps `SKILL.md` focused on the essentials while letting Claude access detailed reference material only when needed. Large reference docs, API specifications, or example collections don't need to load into context every time the skill runs.
275
276```text theme={null}
277my-skill/
278├── SKILL.md (required - overview and navigation)
279├── reference.md (detailed API docs - loaded when needed)
280├── examples.md (usage examples - loaded when needed)
281└── scripts/
282 └── helper.py (utility script - executed, not loaded)
283```
284
285Reference supporting files from `SKILL.md` so Claude knows what each file contains and when to load it:
286
287```markdown theme={null}
288## Additional resources
289
290- For complete API details, see [reference.md](reference.md)
291- For usage examples, see [examples.md](examples.md)
292```
293
294<Tip>Keep `SKILL.md` under 500 lines. Move detailed reference material to separate files.</Tip>
295
296### Control who invokes a skill
297
298By default, both you and Claude can invoke any skill. You can type `/skill-name` to invoke it directly, and Claude can load it automatically when relevant to your conversation. Two frontmatter fields let you restrict this:
299
300* **`disable-model-invocation: true`**: Only you can invoke the skill. Use this for workflows with side effects or that you want to control timing, like `/commit`, `/deploy`, or `/send-slack-message`. You don't want Claude deciding to deploy because your code looks ready.
301
302* **`user-invocable: false`**: Only Claude can invoke the skill. Use this for background knowledge that isn't actionable as a command. A `legacy-system-context` skill explains how an old system works. Claude should know this when relevant, but `/legacy-system-context` isn't a meaningful action for users to take.
303
304This example creates a deploy skill that only you can trigger. The `disable-model-invocation: true` field prevents Claude from running it automatically:
305
306```yaml theme={null}
307name: deploy
308description: Deploy the application to production
309disable-model-invocation: true
310
311Deploy $ARGUMENTS to production:
312
3131. Run the test suite
3142. Build the application
3153. Push to the deployment target
3164. Verify the deployment succeeded
317```
318
319Here's how the two fields affect invocation and context loading:
320
321| Frontmatter | You can invoke | Claude can invoke | When loaded into context |
322| :------------------------------- | :------------- | :---------------- | :----------------------------------------------------------- |
323| (default) | Yes | Yes | Description always in context, full skill loads when invoked |
324| `disable-model-invocation: true` | Yes | No | Description not in context, full skill loads when you invoke |
325| `user-invocable: false` | No | Yes | Description always in context, full skill loads when invoked |
326
327<Note>
328 In a regular session, skill descriptions are loaded into context so Claude knows what's available, but full skill content only loads when invoked. [Subagents with preloaded skills](/en/sub-agents#preload-skills-into-subagents) work differently: the full skill content is injected at startup.
329</Note>
330
331### Skill content lifecycle
332
333When you or Claude invoke a skill, the rendered `SKILL.md` content enters the conversation as a single message and stays there for the rest of the session. Claude Code does not re-read the skill file on later turns, so write guidance that should apply throughout a task as standing instructions rather than one-time steps.
334
335[Auto-compaction](/en/how-claude-code-works#when-context-fills-up) carries invoked skills forward within a token budget. When the conversation is summarized to free context, Claude Code re-attaches the most recent invocation of each skill after the summary, keeping the first 5,000 tokens of each. Re-attached skills share a combined budget of 25,000 tokens. Claude Code fills this budget starting from the most recently invoked skill, so older skills can be dropped entirely after compaction if you have invoked many in one session.
336
337If a skill seems to stop influencing behavior after the first response, the content is usually still present and the model is choosing other tools or approaches. Strengthen the skill's `description` and instructions so the model keeps preferring it, or use [hooks](/en/hooks) to enforce behavior deterministically. If the skill is large or you invoked several others after it, re-invoke it after compaction to restore the full content.
338
339### Pre-approve tools for a skill
340
341The `allowed-tools` field grants permission for the listed tools while the skill is active, so Claude can use them without prompting you for approval. It does not restrict which tools are available: every tool remains callable, and your [permission settings](/en/permissions) still govern tools that are not listed.
342
343For skills checked into a project's `.claude/skills/` directory, `allowed-tools` takes effect after you accept the workspace trust dialog for that folder, the same as permission rules in `.claude/settings.json`. Review project skills before trusting a repository, since a skill can grant itself broad tool access.
344
345This skill lets Claude run git commands without per-use approval whenever you invoke it:
346
347```yaml theme={null}
348name: commit
349description: Stage and commit the current changes
350disable-model-invocation: true
351allowed-tools: Bash(git add *) Bash(git commit *) Bash(git status *)
352```
353
354To remove tools from Claude's available pool while a skill is active, list them in `disallowed-tools` in the skill's frontmatter. The restriction clears when you send your next message. To block tools across all skills and prompts, add deny rules in your [permission settings](/en/permissions).
355
356### Pass arguments to skills
357
358Both you and Claude can pass arguments when invoking a skill. Arguments are available via the `$ARGUMENTS` placeholder.
359
360This skill fixes a GitHub issue by number. The `$ARGUMENTS` placeholder gets replaced with whatever follows the skill name:
361
362```yaml theme={null}
363name: fix-issue
364description: Fix a GitHub issue
365disable-model-invocation: true
366
367Fix GitHub issue $ARGUMENTS following our coding standards.
368
3691. Read the issue description
3702. Understand the requirements
3713. Implement the fix
3724. Write tests
3735. Create a commit
374```
375
376When you run `/fix-issue 123`, Claude receives "Fix GitHub issue 123 following our coding standards..."
377
378If you invoke a skill with arguments but the skill doesn't include `$ARGUMENTS`, Claude Code appends `ARGUMENTS: <your input>` to the end of the skill content so Claude still sees what you typed.
379
380To access individual arguments by position, use `$ARGUMENTS[N]` or the shorter `$N`:
381
382```yaml theme={null}
383name: migrate-component
384description: Migrate a component from one framework to another
385
386Migrate the $ARGUMENTS[0] component from $ARGUMENTS[1] to $ARGUMENTS[2].
387Preserve all existing behavior and tests.
388```
389
390Running `/migrate-component SearchBar React Vue` replaces `$ARGUMENTS[0]` with `SearchBar`, `$ARGUMENTS[1]` with `React`, and `$ARGUMENTS[2]` with `Vue`. The same skill using the `$N` shorthand:
391
392```yaml theme={null}
393name: migrate-component
394description: Migrate a component from one framework to another
395
396Migrate the $0 component from $1 to $2.
397Preserve all existing behavior and tests.
398```
399
400## Advanced patterns
401
402### Inject dynamic context
403
404The `` !`<command>` `` syntax runs shell commands before the skill content is sent to Claude. The command output replaces the placeholder, so Claude receives actual data, not the command itself.
405
406This skill summarizes a pull request by fetching live PR data with the GitHub CLI. The `` !`gh pr diff` `` and other commands run first, and their output gets inserted into the prompt:
407
408```yaml theme={null}
409name: pr-summary
410description: Summarize changes in a pull request
411context: fork
412agent: Explore
413allowed-tools: Bash(gh *)
414
415## Pull request context
416- PR diff: !`gh pr diff`
417- PR comments: !`gh pr view --comments`
418- Changed files: !`gh pr diff --name-only`
419
420## Your task
421Summarize this pull request...
422```
423
424When this skill runs:
425
4261. Each `` !`<command>` `` executes immediately (before Claude sees anything)
4272. The output replaces the placeholder in the skill content
4283. Claude receives the fully-rendered prompt with actual PR data
429
430This is preprocessing, not something Claude executes. Claude only sees the final result.
431
432Substitution runs once over the original file. Command output is inserted as plain text and is not re-scanned for further `` !`<command>` `` placeholders, so a command cannot emit a placeholder for a later pass to expand.
433
434The inline form is only recognized when `!` appears at the start of a line or immediately after whitespace. If `!` follows another character, as in `` KEY=!`cmd` ``, the placeholder is left as literal text and the command does not run.
435
436For multi-line commands, use a fenced code block opened with ` ```! ` instead of the inline form:
437
438````markdown theme={null}
439## Environment
440```!
441node --version
442npm --version
443git status --short
444```
445````
446
447To disable this behavior for skills and custom commands from user, project, plugin, or [additional-directory](#skills-from-additional-directories) sources, set `"disableSkillShellExecution": true` in [settings](/en/settings). Each command is replaced with `[shell command execution disabled by policy]` instead of being run. Bundled and managed skills are not affected. This setting is most useful in [managed settings](/en/permissions#managed-settings), where users cannot override it.
448
449<Tip>
450 To request deeper reasoning when a skill runs, include `ultrathink` anywhere in the skill content. See [Use ultrathink for one-off deep reasoning](/en/model-config#use-ultrathink-for-one-off-deep-reasoning).
451</Tip>
452
453### Run skills in a subagent
454
455Add `context: fork` to your frontmatter when you want a skill to run in isolation. The skill content becomes the prompt that drives the subagent. It won't have access to your conversation history.
456
457<Warning>
458 `context: fork` only makes sense for skills with explicit instructions. If your skill contains guidelines like "use these API conventions" without a task, the subagent receives the guidelines but no actionable prompt, and returns without meaningful output.
459</Warning>
460
461Skills and [subagents](/en/sub-agents) work together in two directions:
462
463| Approach | System prompt | Task | Also loads |
464| :--------------------------- | :----------------------- | :-------------------------- | :-------------------------------------------------- |
465| Skill with `context: fork` | From agent type | SKILL.md content | CLAUDE.md, except when the agent is Explore or Plan |
466| Subagent with `skills` field | Subagent's markdown body | Claude's delegation message | Preloaded skills + CLAUDE.md |
467
468With `context: fork`, you write the task in your skill and pick an agent type to execute it. The built-in Explore and Plan agents [skip CLAUDE.md and git status](/en/sub-agents#what-loads-at-startup) to keep their context small, so a forked skill using `agent: Explore` sees only the SKILL.md content and the agent's own system prompt. For the inverse, where you define a custom subagent that uses skills as reference material, see [Subagents](/en/sub-agents#preload-skills-into-subagents).
469
470#### Example: Research skill using Explore agent
471
472This skill runs research in a forked Explore agent. The skill content becomes the task, and the agent provides read-only tools optimized for codebase exploration:
473
474```yaml theme={null}
475name: deep-research
476description: Research a topic thoroughly
477context: fork
478agent: Explore
479
480Research $ARGUMENTS thoroughly:
481
4821. Find relevant files using Glob and Grep
4832. Read and analyze the code
4843. Summarize findings with specific file references
485```
486
487When this skill runs:
488
4891. A new isolated context is created
4902. The subagent receives the skill content as its prompt ("Research \$ARGUMENTS thoroughly...")
4913. The `agent` field determines the execution environment (model, tools, and permissions)
4924. Results are summarized and returned to your main conversation
493
494The `agent` field specifies which subagent configuration to use. Options include built-in agents (`Explore`, `Plan`, `general-purpose`) or any custom subagent from `.claude/agents/`. If omitted, uses `general-purpose`.
495
496### Restrict Claude's skill access
497
498By default, Claude can invoke any skill that doesn't have `disable-model-invocation: true` set. Skills that define `allowed-tools` grant Claude access to those tools without per-use approval when the skill is active. Your [permission settings](/en/permissions) still govern baseline approval behavior for all other tools. A few built-in commands are also available through the Skill tool, including `/init`, `/review`, and `/security-review`. Other built-in commands such as `/compact` are not.
499
500Three ways to control which skills Claude can invoke:
501
502**Disable all skills** by denying the Skill tool in `/permissions`:
503
504```text theme={null}
505# Add to deny rules:
506Skill
507```
508
509**Allow or deny specific skills** using [permission rules](/en/permissions):
510
511```text theme={null}
512# Allow only specific skills
513Skill(commit)
514Skill(review-pr *)
515
516# Deny specific skills
517Skill(deploy *)
518```
519
520Permission syntax: `Skill(name)` for exact match, `Skill(name *)` for prefix match with any arguments.
521
522**Hide individual skills** by adding `disable-model-invocation: true` to their frontmatter. This removes the skill from Claude's context entirely.
523
524<Note>
525 The `user-invocable` field only controls menu visibility, not Skill tool access. Use `disable-model-invocation: true` to block programmatic invocation.
526</Note>
527
528### Override skill visibility from settings
529
530The `skillOverrides` setting controls skill visibility from your [settings](/en/settings) instead of the skill's own frontmatter. Use it for skills whose SKILL.md you don't want to edit, such as ones checked into a shared project repo or provided by an MCP server. The `/skills` menu writes it for you: highlight a skill and press `Space` to cycle states, then `Enter` to save to `.claude/settings.local.json`.
531
532Each key is a skill name and each value is one of four states:
533
534| Value | Listed to Claude | In `/` menu |
535| :---------------------- | :------------------- | :---------- |
536| `"on"` | Name and description | Yes |
537| `"name-only"` | Name only | Yes |
538| `"user-invocable-only"` | Hidden | Yes |
539| `"off"` | Hidden | Hidden |
540
541A skill that is absent from `skillOverrides` is treated as `"on"`. The example below collapses one skill to its name and turns another off entirely:
542
543```json theme={null}
544{
545 "skillOverrides": {
546 "legacy-context": "name-only",
547 "deploy": "off"
548 }
549}
550```
551
552Plugin skills are not affected by `skillOverrides`. Manage those through `/plugin` instead.
553
554## Share skills
555
556Skills can be distributed at different scopes depending on your audience:
557
558* **Project skills**: Commit `.claude/skills/` to version control
559* **Plugins**: Create a `skills/` directory in your [plugin](/en/plugins)
560* **Managed**: Deploy organization-wide through [managed settings](/en/settings#settings-files)
561
562### Generate visual output
563
564Skills can bundle and run scripts in any language, giving Claude capabilities beyond what's possible in a single prompt. One powerful pattern is generating visual output: interactive HTML files that open in your browser for exploring data, debugging, or creating reports.
565
566This example creates a codebase explorer: an interactive tree view where you can expand and collapse directories, see file sizes at a glance, and identify file types by color.
567
568Create the Skill directory:
569
570```bash theme={null}
571mkdir -p ~/.claude/skills/codebase-visualizer/scripts
572```
573
574Save this to `~/.claude/skills/codebase-visualizer/SKILL.md`. The description tells Claude when to activate this Skill, and the instructions tell Claude to run the bundled script. The script path uses [`${CLAUDE_SKILL_DIR}`](#available-string-substitutions) so it resolves correctly whether the skill is installed at the personal, project, or plugin level:
575
576````yaml theme={null}
577name: codebase-visualizer
578description: Generate an interactive collapsible tree visualization of your codebase. Use when exploring a new repo, understanding project structure, or identifying large files.
579allowed-tools: Bash(python3 *)
580
581# Codebase Visualizer
582
583Generate an interactive HTML tree view that shows your project's file structure with collapsible directories.
584
585## Usage
586
587Run the visualization script from your project root:
588
589```bash
590python3 ${CLAUDE_SKILL_DIR}/scripts/visualize.py .
591```
592
593This creates `codebase-map.html` in the current directory and opens it in your default browser.
594
595## What the visualization shows
596
597- **Collapsible directories**: Click folders to expand/collapse
598- **File sizes**: Displayed next to each file
599- **Colors**: Different colors for different file types
600- **Directory totals**: Shows aggregate size of each folder
601````
602
603Save this to `~/.claude/skills/codebase-visualizer/scripts/visualize.py`. This script scans a directory tree and generates a self-contained HTML file with:
604
605* A **summary sidebar** showing file count, directory count, total size, and number of file types
606* A **bar chart** breaking down the codebase by file type (top 8 by size)
607* A **collapsible tree** where you can expand and collapse directories, with color-coded file type indicators
608
609The script requires Python 3 but uses only built-in libraries, so there are no packages to install:
610
611```python expandable theme={null}
612#!/usr/bin/env python3
613"""Generate an interactive collapsible tree visualization of a codebase."""
614
615import json
616import sys
617import webbrowser
618from html import escape
619from pathlib import Path
620from collections import Counter
621
622IGNORE = {'.git', 'node_modules', '__pycache__', '.venv', 'venv', 'dist', 'build'}
623
624def scan(path: Path, stats: dict) -> dict:
625 result = {"name": path.name, "children": [], "size": 0}
626 try:
627 for item in sorted(path.iterdir()):
628 if item.name in IGNORE or item.name.startswith('.'):
629 continue
630 if item.is_file():
631 size = item.stat().st_size
632 ext = item.suffix.lower() or '(no ext)'
633 result["children"].append({"name": item.name, "size": size, "ext": ext})
634 result["size"] += size
635 stats["files"] += 1
636 stats["extensions"][ext] += 1
637 stats["ext_sizes"][ext] += size
638 elif item.is_dir():
639 stats["dirs"] += 1
640 child = scan(item, stats)
641 if child["children"]:
642 result["children"].append(child)
643 result["size"] += child["size"]
644 except PermissionError:
645 pass
646 return result
647
648def generate_html(data: dict, stats: dict, output: Path) -> None:
649 ext_sizes = stats["ext_sizes"]
650 total_size = sum(ext_sizes.values()) or 1
651 sorted_exts = sorted(ext_sizes.items(), key=lambda x: -x[1])[:8]
652 colors = {
653 '.js': '#f7df1e', '.ts': '#3178c6', '.py': '#3776ab', '.go': '#00add8',
654 '.rs': '#dea584', '.rb': '#cc342d', '.css': '#264de4', '.html': '#e34c26',
655 '.json': '#6b7280', '.md': '#083fa1', '.yaml': '#cb171e', '.yml': '#cb171e',
656 '.mdx': '#083fa1', '.tsx': '#3178c6', '.jsx': '#61dafb', '.sh': '#4eaa25',
657 }
658 lang_bars = "".join(
659 f'<div class="bar-row"><span class="bar-label">{ext}</span>'
660 f'<div class="bar" style="width:{(size/total_size)*100}%;background:{colors.get(ext,"#6b7280")}"></div>'
661 f'<span class="bar-pct">{(size/total_size)*100:.1f}%</span></div>'
662 for ext, size in sorted_exts
663 )
664 def fmt(b):
665 if b < 1024: return f"{b} B"
666 if b < 1048576: return f"{b/1024:.1f} KB"
667 return f"{b/1048576:.1f} MB"
668
669 html = f'''<!DOCTYPE html>
670<html><head>
671 <meta charset="utf-8"><title>Codebase Explorer</title>
672 <style>
673 body {{ font: 14px/1.5 system-ui, sans-serif; margin: 0; background: #1a1a2e; color: #eee; }}
674 .container {{ display: flex; height: 100vh; }}
675 .sidebar {{ width: 280px; background: #252542; padding: 20px; border-right: 1px solid #3d3d5c; overflow-y: auto; flex-shrink: 0; }}
676 .main {{ flex: 1; padding: 20px; overflow-y: auto; }}
677 h1 {{ margin: 0 0 10px 0; font-size: 18px; }}
678 h2 {{ margin: 20px 0 10px 0; font-size: 14px; color: #888; text-transform: uppercase; }}
679 .stat {{ display: flex; justify-content: space-between; padding: 8px 0; border-bottom: 1px solid #3d3d5c; }}
680 .stat-value {{ font-weight: bold; }}
681 .bar-row {{ display: flex; align-items: center; margin: 6px 0; }}
682 .bar-label {{ width: 55px; font-size: 12px; color: #aaa; }}
683 .bar {{ height: 18px; border-radius: 3px; }}
684 .bar-pct {{ margin-left: 8px; font-size: 12px; color: #666; }}
685 .tree {{ list-style: none; padding-left: 20px; }}
686 details {{ cursor: pointer; }}
687 summary {{ padding: 4px 8px; border-radius: 4px; }}
688 summary:hover {{ background: #2d2d44; }}
689 .folder {{ color: #ffd700; }}
690 .file {{ display: flex; align-items: center; padding: 4px 8px; border-radius: 4px; }}
691 .file:hover {{ background: #2d2d44; }}
692 .size {{ color: #888; margin-left: auto; font-size: 12px; }}
693 .dot {{ width: 8px; height: 8px; border-radius: 50%; margin-right: 8px; }}
694 </style>
695</head><body>
696 <div class="container">
697 <div class="sidebar">
698 <h1>📊 Summary</h1>
699 <div class="stat"><span>Files</span><span class="stat-value">{stats["files"]:,}</span></div>
700 <div class="stat"><span>Directories</span><span class="stat-value">{stats["dirs"]:,}</span></div>
701 <div class="stat"><span>Total size</span><span class="stat-value">{fmt(data["size"])}</span></div>
702 <div class="stat"><span>File types</span><span class="stat-value">{len(stats["extensions"])}</span></div>
703 <h2>By file type</h2>
704 {lang_bars}
705 </div>
706 <div class="main">
707 <h1>📁 {escape(data["name"])}</h1>
708 <ul class="tree" id="root"></ul>
709 </div>
710 </div>
711 <script>
712 const data = {json.dumps(data)};
713 const colors = {json.dumps(colors)};
714 function fmt(b) {{ if (b < 1024) return b + ' B'; if (b < 1048576) return (b/1024).toFixed(1) + ' KB'; return (b/1048576).toFixed(1) + ' MB'; }}
715 function esc(s) {{ return s.replace(/[&<>"']/g, c => ({{"&":"&","<":"<",">":">",'"':""","'":"'"}}[c])); }}
716 function render(node, parent) {{
717 if (node.children) {{
718 const det = document.createElement('details');
719 det.open = parent === document.getElementById('root');
720 det.innerHTML = `<summary><span class="folder">📁 ${{esc(node.name)}}</span><span class="size">${{fmt(node.size)}}</span></summary>`;
721 const ul = document.createElement('ul'); ul.className = 'tree';
722 node.children.sort((a,b) => (b.children?1:0)-(a.children?1:0) || a.name.localeCompare(b.name));
723 node.children.forEach(c => render(c, ul));
724 det.appendChild(ul);
725 const li = document.createElement('li'); li.appendChild(det); parent.appendChild(li);
726 }} else {{
727 const li = document.createElement('li'); li.className = 'file';
728 li.innerHTML = `<span class="dot" style="background:${{colors[node.ext]||'#6b7280'}}"></span>${{esc(node.name)}}<span class="size">${{fmt(node.size)}}</span>`;
729 parent.appendChild(li);
730 }}
731 }}
732 data.children.forEach(c => render(c, document.getElementById('root')));
733 </script>
734</body></html>'''
735 output.write_text(html)
736
737if __name__ == '__main__':
738 target = Path(sys.argv[1] if len(sys.argv) > 1 else '.').resolve()
739 stats = {"files": 0, "dirs": 0, "extensions": Counter(), "ext_sizes": Counter()}
740 data = scan(target, stats)
741 out = Path('codebase-map.html')
742 generate_html(data, stats, out)
743 print(f'Generated {out.absolute()}')
744 webbrowser.open(f'file://{out.absolute()}')
745```
746
747To test, open Claude Code in any project and ask "Visualize this codebase." Claude runs the script, generates `codebase-map.html`, and opens it in your browser.
748
749This pattern works for any visual output: dependency graphs, test coverage reports, API documentation, or database schema visualizations. The bundled script does the work while Claude handles orchestration.
750
751## Troubleshooting
752
753### Skill not triggering
754
755If Claude doesn't use your skill when expected:
756
7571. Check the description includes keywords users would naturally say
7582. Verify the skill appears in `What skills are available?`
7593. Try rephrasing your request to match the description more closely
7604. Invoke it directly with `/skill-name` if the skill is user-invocable
761
762### Skill triggers too often
763
764If Claude uses your skill when you don't want it:
765
7661. Make the description more specific
7672. Add `disable-model-invocation: true` if you only want manual invocation
768
769### Skill descriptions are cut short
770
771Skill descriptions are loaded into context so Claude knows what's available. All skill names are always included, but if you have many skills, descriptions are shortened to fit the character budget, which can strip the keywords Claude needs to match your request. The budget scales at 1% of the model's context window. When it overflows, descriptions for the skills you invoke least are dropped first, so the skills you actually use keep their full text. Run `/doctor` to see whether the budget is overflowing and which skills are affected.
772
773To raise the budget, set the [`skillListingBudgetFraction`](/en/settings#available-settings) setting (e.g. `0.02` = 2%) or the `SLASH_COMMAND_TOOL_CHAR_BUDGET` environment variable to a fixed character count. To free budget for other skills, set low-priority entries to `"name-only"` in [`skillOverrides`](#override-skill-visibility-from-settings) so they list without a description. You can also trim the `description` and `when_to_use` text at the source: put the key use case first, since each entry's combined text is capped at 1,536 characters regardless of budget. The cap is configurable with [`maxSkillDescriptionChars`](/en/settings#available-settings).
774
775## Related resources
776
777* **[Debug your configuration](/en/debug-your-config)**: diagnose why a skill isn't appearing or triggering
778* **[Subagents](/en/sub-agents)**: delegate tasks to specialized agents
779* **[Plugins](/en/plugins)**: package and distribute skills with other extensions
780* **[Hooks](/en/hooks)**: automate workflows around tool events
781* **[Memory](/en/memory)**: manage CLAUDE.md files for persistent context
782* **[Commands](/en/commands)**: reference for built-in commands and bundled skills
783* **[Permissions](/en/permissions)**: control tool and skill access