Create a new Claude Code skill following the conventions of existing skills.
Existing skills
ls ~/.claude/skills .claude/skills skills 2>/dev/null || true
Arguments: $ARGUMENTS
Workflow
- Identify what the skill should do:
- The description in the arguments
- Otherwise, the skill most recently discussed in the conversation
- If neither exists, ask the user what the skill should do and stop
- Decide where the skill lives (ask if unclear from the request):
~/.claude/skills/<name>/SKILL.md if useful across projects
<repo>/.claude/skills/<name>/SKILL.md if it encodes project-specific
procedures, scripts, or conventions
- Decide the invocation model (see "Frontmatter")
- Read the one or two existing skills closest in shape to the new one and
mirror their structure and tone. Mirror the body. Frontmatter follows the
rules below
- Draft the skill (see "Frontmatter" and "Body")
- Derive
allowed-tools (see "Permissions")
- Write the skill file and summarize the choices made (location, invocation
model, permissions)
- Polish the draft (see "Polish")
Frontmatter
Pick exactly one invocation model:
- User-invoked action (e.g.
jj-split): Description is a one-sentence summary
of what the skill does, shown to the user in skill lists. Always add an
argument-hint (see "Other fields") and interpolate the arguments in the body
(see "Body"), since the user invokes it as a slash command and may pass
arguments
- Auto-loaded guidance (e.g.
authoring-tests): set user-invocable: false
plus paths globs so the skill loads when matching files are touched.
Description starts with "Use when..."
- Model-invoked task: no flags. The description is the only context Claude has
when deciding whether to load the skill, so it must state the trigger: "Use
when asked to..." with concrete phrasings
Other fields:
name: kebab-case, matches the directory name
description: always a | block scalar (description: |, then the indented
lines), however short. A plain scalar breaks on a : anywhere inside it,
since a : parses as a nested mapping and fails to load the frontmatter
argument-hint: required for user-invoked skills. Text shown after the
command name, describing the expected arguments (e.g.
'[file path or text to review]'). Use [...] for optional arguments and
<...> for required ones. Always quote it: an unquoted [...] parses as a
list
arguments: declare named arguments, referenced as $<name> in the body. Use
named arguments only when the skill is always invoked with one specific value
and has no conversation fallback. Otherwise omit them and use $ARGUMENTS for
free-form input that can also fall back to the conversation
Body
- Open with the description restated as an imperative instruction
- Inject dynamic context with
!-fenced code blocks, which execute at
invocation time (e.g. jj show --git in jj-split). Use them for context the
skill always needs. If the workflow might stop before using the context,
gather it in a workflow step instead
- A user-invoked skill interpolates its arguments in the body, either
$ARGUMENTS for free-form input or the named $<name> placeholders, so input
passed to the slash command isn't dropped. Place it after the dynamic context
and before the workflow so user input can override the defaults. When later
prose refers back to the input, label the line Arguments: $ARGUMENTS and
write "the arguments" thereafter, so a long input isn't repeated. Otherwise a
bare $ARGUMENTS is fine
- Structure: optional
# Goals or # Principles, then a numbered # Workflow,
then how-to and guideline sections the workflow references
- Cross-reference related skills instead of duplicating them: "Before starting,
load
/authoring-tests". Verify the referenced skill exists
- A project skill may only reference other project skills. A user skill is
stored in one person's
~/.claude/skills, so a project skill pointing at one
sends every other contributor to a skill they lack. Either inline the skill's
instructions, or drop the reference. A user skill may reference either, since
whoever has it has both
- Don't instruct using interactive commands (e.g.
jj split -i, git add -p).
Claude cannot respond to interactive prompts, so use flag-driven alternatives
- In a workflow that mutates state, verify after each step, define when to stop
early (e.g. "if the commit is already small, tell the user and stop"), and
include a fixing-mistakes section when missteps are recoverable
- End open-ended lists of techniques with: "These aren't exhaustive. Reason from
first principles when none fits cleanly."
- Keep SKILL.md to the procedure. Put large reference material, data, and
scripts in supporting files in the skill directory and link them from the body
for on-demand reading
- Wrap prose at 80 columns. No em dashes. No terminal period on a list item,
even a multi-sentence one, whose internal sentences keep theirs
Target resolution
A skill that transforms code or prose usually works on either an explicit target
or the current commit's changes. Standardize this with a # Target section that
interpolates jj show --git, then an Arguments: $ARGUMENTS line, then the
precedence: operate on the target named in the arguments if given. Otherwise
operate on the changes in the current commit shown above. If there are no
arguments and the commit has no changes, ask the user what to target and stop.
See ../reuse/SKILL.md and ../stratify/SKILL.md.
Permissions
- List every tool use the body requires: Bash commands (including those in
!-fenced context blocks), WebFetch domains, and MCP tools
- Drop the ones already allowed by
~/.claude/settings.json (for project
skills, also check the project's .claude/settings.json)
- Add the rest as
allowed-tools entries, scoped as narrowly as possible:
Bash(jj split *), not Bash(jj *)
- If a needed tool matches a settings
deny rule, flag the conflict to the
user: deny rules are evaluated before skill allowed-tools and block the
tool even while the skill is active
Polish
Run these passes over the skill file, in order, waiting for each to finish
before starting the next:
/refine-context
/humanize
Run each pass in its own subagent, and give that subagent nothing but the path
to the skill file and the instruction to run the one skill on it. Withhold the
request that prompted the skill, the reasoning behind the draft, and the
findings of earlier passes: each pass must read the file cold and judge it as a
reader who has never seen it would, so gaps that seem filled by conversation
context surface as gaps. Tell the subagent to be adversarial: assume the draft
is unclear until the text proves otherwise.
Report what each pass changed.
1---2name: create-skill3description: |4 Create a new Claude Code skill following the conventions of existing skills.5argument-hint: '[what the skill should do]'6---78Create a new Claude Code skill following the conventions of existing skills.910# Existing skills1112```!13ls ~/.claude/skills .claude/skills skills 2>/dev/null || true14```1516Arguments: $ARGUMENTS1718# Workflow19201. Identify what the skill should do:21 - The description in the arguments22 - Otherwise, the skill most recently discussed in the conversation23 - If neither exists, ask the user what the skill should do and stop242. Decide where the skill lives (ask if unclear from the request):25 - `~/.claude/skills/<name>/SKILL.md` if useful across projects26 - `<repo>/.claude/skills/<name>/SKILL.md` if it encodes project-specific27 procedures, scripts, or conventions283. Decide the invocation model (see "Frontmatter")294. Read the one or two existing skills closest in shape to the new one and30 mirror their structure and tone. Mirror the body. Frontmatter follows the31 rules below325. Draft the skill (see "Frontmatter" and "Body")336. Derive `allowed-tools` (see "Permissions")347. Write the skill file and summarize the choices made (location, invocation35 model, permissions)368. Polish the draft (see "Polish")3738# Frontmatter3940Pick exactly one invocation model:4142- User-invoked action (e.g. `jj-split`): Description is a one-sentence summary43 of what the skill does, shown to the user in skill lists. Always add an44 `argument-hint` (see "Other fields") and interpolate the arguments in the body45 (see "Body"), since the user invokes it as a slash command and may pass46 arguments47- Auto-loaded guidance (e.g. `authoring-tests`): set `user-invocable: false`48 plus `paths` globs so the skill loads when matching files are touched.49 Description starts with "Use when..."50- Model-invoked task: no flags. The description is the only context Claude has51 when deciding whether to load the skill, so it must state the trigger: "Use52 when asked to..." with concrete phrasings5354Other fields:5556- `name`: kebab-case, matches the directory name57- `description`: always a `|` block scalar (`description: |`, then the indented58 lines), however short. A plain scalar breaks on a `: ` anywhere inside it,59 since a `: ` parses as a nested mapping and fails to load the frontmatter60- `argument-hint`: required for user-invoked skills. Text shown after the61 command name, describing the expected arguments (e.g.62 `'[file path or text to review]'`). Use `[...]` for optional arguments and63 `<...>` for required ones. Always quote it: an unquoted `[...]` parses as a64 list65- `arguments`: declare named arguments, referenced as `$<name>` in the body. Use66 named arguments only when the skill is always invoked with one specific value67 and has no conversation fallback. Otherwise omit them and use `$ARGUMENTS` for68 free-form input that can also fall back to the conversation6970# Body7172- Open with the description restated as an imperative instruction73- Inject dynamic context with `!`-fenced code blocks, which execute at74 invocation time (e.g. `jj show --git` in `jj-split`). Use them for context the75 skill always needs. If the workflow might stop before using the context,76 gather it in a workflow step instead77- A user-invoked skill interpolates its arguments in the body, either78 `$ARGUMENTS` for free-form input or the named `$<name>` placeholders, so input79 passed to the slash command isn't dropped. Place it after the dynamic context80 and before the workflow so user input can override the defaults. When later81 prose refers back to the input, label the line `Arguments: $ARGUMENTS` and82 write "the arguments" thereafter, so a long input isn't repeated. Otherwise a83 bare `$ARGUMENTS` is fine84- Structure: optional `# Goals` or `# Principles`, then a numbered `# Workflow`,85 then how-to and guideline sections the workflow references86- Cross-reference related skills instead of duplicating them: "Before starting,87 load `/authoring-tests`". Verify the referenced skill exists88- A project skill may only reference other project skills. A user skill is89 stored in one person's `~/.claude/skills`, so a project skill pointing at one90 sends every other contributor to a skill they lack. Either inline the skill's91 instructions, or drop the reference. A user skill may reference either, since92 whoever has it has both93- Don't instruct using interactive commands (e.g. `jj split -i`, `git add -p`).94 Claude cannot respond to interactive prompts, so use flag-driven alternatives95- In a workflow that mutates state, verify after each step, define when to stop96 early (e.g. "if the commit is already small, tell the user and stop"), and97 include a fixing-mistakes section when missteps are recoverable98- End open-ended lists of techniques with: "These aren't exhaustive. Reason from99 first principles when none fits cleanly."100- Keep SKILL.md to the procedure. Put large reference material, data, and101 scripts in supporting files in the skill directory and link them from the body102 for on-demand reading103- Wrap prose at 80 columns. No em dashes. No terminal period on a list item,104 even a multi-sentence one, whose internal sentences keep theirs105106## Target resolution107108A skill that transforms code or prose usually works on either an explicit target109or the current commit's changes. Standardize this with a `# Target` section that110interpolates `jj show --git`, then an `Arguments: $ARGUMENTS` line, then the111precedence: operate on the target named in the arguments if given. Otherwise112operate on the changes in the current commit shown above. If there are no113arguments and the commit has no changes, ask the user what to target and stop.114See `../reuse/SKILL.md` and `../stratify/SKILL.md`.115116# Permissions1171181. List every tool use the body requires: Bash commands (including those in119 `!`-fenced context blocks), `WebFetch` domains, and MCP tools1202. Drop the ones already allowed by `~/.claude/settings.json` (for project121 skills, also check the project's `.claude/settings.json`)1223. Add the rest as `allowed-tools` entries, scoped as narrowly as possible:123 `Bash(jj split *)`, not `Bash(jj *)`1244. If a needed tool matches a settings `deny` rule, flag the conflict to the125 user: deny rules are evaluated before skill `allowed-tools` and block the126 tool even while the skill is active127128# Polish129130Run these passes over the skill file, in order, waiting for each to finish131before starting the next:1321331. `/refine-context`1342. `/humanize`135136Run each pass in its own subagent, and give that subagent nothing but the path137to the skill file and the instruction to run the one skill on it. Withhold the138request that prompted the skill, the reasoning behind the draft, and the139findings of earlier passes: each pass must read the file cold and judge it as a140reader who has never seen it would, so gaps that seem filled by conversation141context surface as gaps. Tell the subagent to be adversarial: assume the draft142is unclear until the text proves otherwise.143144Report what each pass changed.