You already know that a is a folder with a SKILL.md file: a description in the and instructions in the body, plus $ARGUMENTS for whatever you typed after the name. Now, five patterns that make a skill stronger — and leaner.
Five patterns
| Pattern | How you write it | What it does |
|---|---|---|
| Live data | !`git diff HEAD` in the body | Claude Code runs the command before Claude reads the skill and inserts the output |
| Neighbouring files | files next to SKILL.md, linked from it | long reference material Claude reads only when needed |
| Its own context | context: fork in the frontmatter | the skill becomes a task for a background |
| Named arguments | arguments: [focus], and $focus in the body | each word after the name fills its own field |
| Allowed tools | allowed-tools: Read, Grep | these tools run without a prompt during the skill’s turn |
A skill for reviewing changes
Let’s put it all together. The file .claude/skills/changes-review/SKILL.md:
---
name: changes-review
description: Reviews uncommitted changes against the team checklist. Use when asked for a review before committing.
context: fork
arguments: [focus]
allowed-tools: Bash(git diff *)
---
## Changes
!`git diff HEAD`
## Task
Review the changes above against [checklist.md](checklist.md), paying most attention to $focus.
Name each problem with its file and line, and finish with one line: is it ready to commit.
And next to it, in the same folder, checklist.md:
- Every changed function has a test.
- Errors are reported, not swallowed.
- There are no secrets in the code or configs.
What happens when you type /changes-review tests:
- Claude Code runs
git diff HEADand inserts the diff into the skill’s text. - The word
testsgoes in place of$focus. - The skill becomes a task for a subagent. It works in the background, does not see your conversation, opens
checklist.mditself and sends a report when it is done.
Try /changes-review secrets — the same skill will look at secrets first.
Fine points
A failed command aborts the skill. If an injected command exits with an error, or your permission rules do not let it through, the skill does not run at all: you will see Shell command failed or Shell command permission check failed. Run the command by hand and look at the allowed-tools line. Outside Auto mode, a command your rules do not allow stops the skill — which is why allowed-tools: Bash(git diff *) is not redundant here.
allowed-tools forbids nothing. It only allows what it lists without a prompt, for the turn the skill runs in. Other tools stay available — just with the usual prompts.
Keep SKILL.md short. Once it runs, its whole text stays in the conversation. The documentation recommends no more than 500 lines, with the details in neighbouring files: Claude opens those only if it needs them.
Quick check
A skill with !`npm run lint` does not run and says Shell command failed. What do you do first?
Careful
An injected command runs before Claude even sees the skill, and Claude cannot review or cancel it. Only inject commands that read, not change: git diff, git log, git status. And remember the output lands in the context: a huge diff eats it just like a huge file.
Practice in the terminal