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: Create a new Claude Code skill following the conventions of existing skills.4---56Create a new Claude Code skill following the conventions of existing skills.78# Existing skills910```!11ls ~/.claude/skills .claude/skills skills 2>/dev/null || true12```1314Arguments: $ARGUMENTS1516# Workflow17181. Identify what the skill should do:19 - The description in the arguments20 - Otherwise, the skill most recently discussed in the conversation21 - If neither exists, ask the user what the skill should do and stop222. Decide where the skill lives (ask if unclear from the request):23 - `~/.claude/skills/<name>/SKILL.md` if useful across projects24 - `<repo>/.claude/skills/<name>/SKILL.md` if it encodes project-specific25 procedures, scripts, or conventions263. Decide the invocation model (see "Frontmatter")274. Read the one or two existing skills closest in shape to the new one and28 mirror their structure and tone. Mirror the body. Frontmatter follows the29 rules below305. Draft the skill (see "Frontmatter" and "Body")316. Derive `allowed-tools` (see "Permissions")327. Write the skill file and summarize the choices made (location, invocation33 model, permissions)348. Polish the draft (see "Polish")3536# Frontmatter3738Pick exactly one invocation model:3940- User-invoked action (e.g. `jj-split`): Description is a one-sentence summary41 of what the skill does, shown to the user in skill lists. Always add an42 `argument-hint` (see "Other fields") and interpolate the arguments in the body43 (see "Body"), since the user invokes it as a slash command and may pass44 arguments45- Auto-loaded guidance (e.g. `authoring-tests`): set `user-invocable: false`46 plus `paths` globs so the skill loads when matching files are touched.47 Description starts with "Use when..."48- Model-invoked task: no flags. The description is the only context Claude has49 when deciding whether to load the skill, so it must state the trigger: "Use50 when asked to..." with concrete phrasings5152Other fields:5354- `name`: kebab-case, matches the directory name55- `description`: always a `|` block scalar (`description: |`, then the indented56 lines), however short. A plain scalar breaks on a `: ` anywhere inside it,57 since a `: ` parses as a nested mapping and fails to load the frontmatter58- `argument-hint`: required for user-invoked skills. Text shown after the59 command name, describing the expected arguments (e.g.60 `'[file path or text to review]'`). Use `[...]` for optional arguments and61 `<...>` for required ones. Always quote it: an unquoted `[...]` parses as a62 list63- `arguments`: declare named arguments, referenced as `$<name>` in the body. Use64 named arguments only when the skill is always invoked with one specific value65 and has no conversation fallback. Otherwise omit them and use `$ARGUMENTS` for66 free-form input that can also fall back to the conversation6768# Body6970- Open with the description restated as an imperative instruction71- Inject dynamic context with `!`-fenced code blocks, which execute at72 invocation time (e.g. `jj show --git` in `jj-split`). Use them for context the73 skill always needs. If the workflow might stop before using the context,74 gather it in a workflow step instead75- A user-invoked skill interpolates its arguments in the body, either76 `$ARGUMENTS` for free-form input or the named `$<name>` placeholders, so input77 passed to the slash command isn't dropped. Place it after the dynamic context78 and before the workflow so user input can override the defaults. When later79 prose refers back to the input, label the line `Arguments: $ARGUMENTS` and80 write "the arguments" thereafter, so a long input isn't repeated. Otherwise a81 bare `$ARGUMENTS` is fine82- Structure: optional `# Goals` or `# Principles`, then a numbered `# Workflow`,83 then how-to and guideline sections the workflow references84- Cross-reference related skills instead of duplicating them: "Before starting,85 load `/authoring-tests`". Verify the referenced skill exists86- A project skill may only reference other project skills. A user skill is87 stored in one person's `~/.claude/skills`, so a project skill pointing at one88 sends every other contributor to a skill they lack. Either inline the skill's89 instructions, or drop the reference. A user skill may reference either, since90 whoever has it has both91- Don't instruct using interactive commands (e.g. `jj split -i`, `git add -p`).92 Claude cannot respond to interactive prompts, so use flag-driven alternatives93- In a workflow that mutates state, verify after each step, define when to stop94 early (e.g. "if the commit is already small, tell the user and stop"), and95 include a fixing-mistakes section when missteps are recoverable96- End open-ended lists of techniques with: "These aren't exhaustive. Reason from97 first principles when none fits cleanly."98- Keep SKILL.md to the procedure. Put large reference material, data, and99 scripts in supporting files in the skill directory and link them from the body100 for on-demand reading101- Wrap prose at 80 columns. No em dashes. No terminal period on a list item,102 even a multi-sentence one, whose internal sentences keep theirs103104## Target resolution105106A skill that transforms code or prose usually works on either an explicit target107or the current commit's changes. Standardize this with a `# Target` section that108interpolates `jj show --git`, then an `Arguments: $ARGUMENTS` line, then the109precedence: operate on the target named in the arguments if given. Otherwise110operate on the changes in the current commit shown above. If there are no111arguments and the commit has no changes, ask the user what to target and stop.112See `../reuse/SKILL.md` and `../stratify/SKILL.md`.113114# Permissions1151161. List every tool use the body requires: Bash commands (including those in117 `!`-fenced context blocks), `WebFetch` domains, and MCP tools1182. Drop the ones already allowed by `~/.claude/settings.json` (for project119 skills, also check the project's `.claude/settings.json`)1203. Add the rest as `allowed-tools` entries, scoped as narrowly as possible:121 `Bash(jj split *)`, not `Bash(jj *)`1224. If a needed tool matches a settings `deny` rule, flag the conflict to the123 user: deny rules are evaluated before skill `allowed-tools` and block the124 tool even while the skill is active125126# Polish127128Run these passes over the skill file, in order, waiting for each to finish129before starting the next:1301311. `/refine-context`1322. `/humanize`133134Run each pass in its own subagent, and give that subagent nothing but the path135to the skill file and the instruction to run the one skill on it. Withhold the136request that prompted the skill, the reasoning behind the draft, and the137findings of earlier passes: each pass must read the file cold and judge it as a138reader who has never seen it would, so gaps that seem filled by conversation139context surface as gaps. Tell the subagent to be adversarial: assume the draft140is unclear until the text proves otherwise.141142Report what each pass changed.