| name | create-skill |
| description | Guide for creating a new Battle Skill from scratch. Use when adding a new skill, capturing a workflow, or turning a technique into a reusable skill. Triggers on "create a skill", "new skill", "add a skill". |
Create Skill
A guide for creating high-quality Battle Skills that AI agents can reliably use.
Claude Code skills follow the Agent Skills open standard, which works across multiple AI tools (Claude Code, Cursor, Gemini CLI, Codex CLI, Kiro, Antigravity). Claude Code extends the standard with invocation control, subagent execution, and dynamic context injection.
TL;DR — Quick Checklist
skills/
└── your-skill-name/
├── SKILL.md ← required
├── references/ ← optional: large docs, cheat sheets
├── scripts/ ← optional: executable helpers
└── assets/ ← optional: templates, icons, files
Run before committing:
python3 scripts/validate_skills.py skills/your-skill-name
python3 scripts/gen_catalog.py
Where Skills Live
Where you store a skill determines who can use it. Higher-priority locations win when names conflict:
| Location | Path | Applies to |
|---|
| Enterprise | Managed settings (org-wide) | All users in organization |
| Personal | ~/.claude/skills/<name>/SKILL.md | All your projects |
| Project | .claude/skills/<name>/SKILL.md | This project only |
| Plugin | <plugin>/skills/<name>/SKILL.md | Where plugin is enabled (namespaced as plugin:skill) |
Note: Claude also auto-discovers skills from nested .claude/skills/ directories (e.g., packages/frontend/.claude/skills/), supporting monorepo setups.
Step 1 — Pick a Name
- Use lowercase kebab-case:
react-patterns, api-design, deploy-vercel
- Name describes what the skill does, not what domain it's in
- No generic names:
frontend, misc, helpers
Step 2 — Create the Folder & SKILL.md
mkdir skills/your-skill-name
touch skills/your-skill-name/SKILL.md
SKILL.md Frontmatter
All fields are optional, but description is strongly recommended.
---
name: your-skill-name
description: >-
What the skill does and when
to use it. Be specific.
argument-hint: [environment]
allowed-tools: Read Grep Bash
model: claude-sonnet-4-6
effort: high
context: fork
agent: general-purpose
disable-model-invocation: false
user-invocable: true
paths: "src/**/*.ts"
hooks:
PreToolUse:
- matcher: Bash
hooks:
- command: echo "tool use detected"
shell: bash
---
Field Reference
| Field | Type | Description |
|---|
name | string | Lowercase kebab-case, max 64 chars. Becomes the /slash-command. If omitted, uses directory name. |
description | string | What the skill does & when to use it. Truncated after 250 chars — front-load key use cases. |
argument-hint | string | Hint for expected arguments, e.g. [issue-number] |
allowed-tools | string/list | Tools Claude can use without permission when skill is active, e.g. Read Grep Bash(npm *) |
model | string | Override session model, e.g. claude-opus-4-6 |
effort | string | low | medium | high | max |
context | string | fork to run in an isolated subagent context |
agent | string | Subagent type when context: fork — Explore, Plan, general-purpose, or custom agent name |
disable-model-invocation | boolean | true = Claude won't auto-trigger, invoke manually with /name |
user-invocable | boolean | false = hidden from / menu, used for background knowledge |
paths | string/list | Glob patterns limiting when skill auto-activates |
hooks | object | Hooks scoped to skill lifecycle |
shell | string | bash (default) or powershell |
Invocation Control
How disable-model-invocation and user-invocable affect who can trigger a skill and when it loads into context:
| Frontmatter | You can invoke | Claude can invoke | When loaded into context |
|---|
| (default) | Yes | Yes | Description always in context; full skill loads on invocation |
disable-model-invocation: true | Yes | No | Description not in context; full skill loads when you invoke |
user-invocable: false | No | Yes | Description always in context; full skill loads on invocation |
String Substitutions
Use these variables in skill content for dynamic behavior:
| Variable | Description |
|---|
$ARGUMENTS | All arguments passed when invoking the skill |
$ARGUMENTS[N] or $N | Access argument by 0-based index |
${CLAUDE_SESSION_ID} | Current session ID |
${CLAUDE_SKILL_DIR} | Directory containing this SKILL.md |
Dynamic Context Injection
The !`<command>` syntax runs shell commands before skill content is sent to Claude. The output replaces the placeholder — Claude only sees the final result.
---
name: pr-summary
description: Summarize changes in a pull request
context: fork
agent: Explore
---
- PR diff: !`gh pr diff`
- PR comments: !`gh pr view --comments`
- Changed files: !`gh pr diff --name-only`
Summarize this pull request...
How it works:
- Each
!`<command>` executes immediately (preprocessing)
- Command output replaces the placeholder in skill content
- Claude receives the fully-rendered prompt with actual data
Use ${CLAUDE_SKILL_DIR} to reference bundled scripts: !`python ${CLAUDE_SKILL_DIR}/scripts/gather.py`
Description Writing Guide
The description field is the primary trigger mechanism — Claude reads it to decide if a skill is relevant. Write it to match how users naturally phrase requests. Minimum 10 words (the validator will warn if fewer).
Bad description:
How to write React components.
Good description:
Best practices for building React components, hooks, and state management.
Use this skill when writing any React code, creating components, managing state,
or when the user mentions React, JSX, hooks, or component architecture.
The good version: explains what it does, says when to use it, and lists trigger phrases.
Tip: Skill descriptions share a context budget (default: 1% of context window, min 8,000 chars). Set SLASH_COMMAND_TOOL_CHAR_BUDGET env var to increase. Each description is capped at 250 chars regardless — front-load the key use case.
Step 3 — Write the Body
Anatomy of a Good Skill Body
# Skill Name
One sentence explaining what this skill enables.
---
## When to Use This Skill
- Situation A
- Situation B
## When NOT to Use This Skill
- Situation C (use X instead)
## Core Rules
1. Rule one — with brief explanation
2. Rule two — with brief explanation
3. ...
## Examples
### Good Example
\`\`\`language
// correct pattern
\`\`\`
### Bad Example
\`\`\`language
// anti-pattern — explain why
\`\`\`
## Anti-Patterns (Avoid)
- What not to do and why
Principles
Keep SKILL.md under 500 lines. If you're going over, move large sections to references/ and add a pointer in SKILL.md:
> For full API reference, see [references/api.md](references/api.md)
Be concrete, not abstract. Show code examples. Show the diff between right and wrong.
Enable extended thinking. Include the word ultrathink anywhere in skill content to activate Claude's extended thinking mode for deeper reasoning.
Principle of No Surprise. The skill should do exactly what its name and description say — nothing more, nothing less.
Progressive disclosure: keep SKILL.md under 500 lines and link to supporting files (references/, scripts/, assets/) that Claude reads only when needed.
| Layer | What lives here | When it's loaded |
|---|
| Metadata (name + description) | Frontmatter in SKILL.md | Always in context — used for skill matching |
| SKILL.md body | Core rules, examples, anti-patterns | When the skill triggers |
references/ | Large docs, API refs, cheat sheets | On demand — Claude reads only when the task needs them |
scripts/ | Executable helpers, scaffolders | On demand — Claude runs when the workflow requires it |
assets/ | Templates, config files, icons | On demand — Claude copies/uses when generating output |
Why this matters: AI agents have limited context windows. If you inline a 2000-line API reference into SKILL.md, it wastes tokens every time the skill triggers — even when only 10% of that content is relevant. Instead, keep SKILL.md focused on decision-making (rules, when/when-not, key examples) and offload reference material:
## Cloud Deploy
Follow the rules below for all cloud deployments.
> For provider-specific configuration, see:
> - [references/aws.md](references/aws.md)
> - [references/gcp.md](references/gcp.md)
> - [references/azure.md](references/azure.md)
Claude will read the relevant references/ file only when the user's task requires that specific provider.
Step 4 — Add Bundled Resources (Optional)
references/ — Large Docs
For cheat sheets, API references, framework docs that would bloat the main SKILL.md:
references/
├── aws.md
├── gcp.md
└── azure.md
Reference them from SKILL.md: See [references/aws.md](references/aws.md) for AWS-specific config.
scripts/ — Executable Helpers
For deterministic, repetitive tasks the AI should run rather than reason about:
assets/ — Files & Templates
For starter files, config templates, icons used in skill output.
Step 5 — Validate & Publish
python3 scripts/validate_skills.py skills/your-skill-name
python3 scripts/gen_catalog.py
git add skills/your-skill-name CATALOG.md skills_index.json
git commit -m "feat(skill): add your-skill-name"
Commit Convention
feat(skill): add <name> # new skill
fix(skill): fix <name> # bug fix in skill
improve(skill): update <name> # improvement
deprecate(skill): remove <name> # removal
Step 6 — Update CHANGELOG.md
Add an entry under [Unreleased]:
### Added
- `your-skill-name` — One-line description of what it does
Restrict Skill Access
Control which skills Claude can invoke using permission rules:
# Allow specific skills
Skill(commit)
Skill(review-pr *)
# Deny specific skills
Skill(deploy *)
Skill(name) — exact match
Skill(name *) — prefix match (matches name-anything)
- Deny
Skill entirely to block all skill invocations by Claude
Note: disable-model-invocation: true removes the skill from Claude's context entirely. user-invocable: false only hides from the / menu.
Quality Bar
Before submitting, ask yourself:
A skill that hasn't been used in a real project yet is a hypothesis, not a battle skill.
Example: Minimal Valid Skill
skills/
└── git-commit-message/
└── SKILL.md
---
name: git-commit-message
description: Write clear, conventional git commit messages following Conventional Commits. Use when the user asks to write a commit message, summarize changes for git, or says "commit this".
---
# Git Commit Message
Write structured commit messages that make history readable.
## Format
\`\`\`
<type>(<scope>): <subject>
[optional body]
[optional footer]
\`\`\`
## Types
- `feat` — new feature
- `fix` — bug fix
- `docs` — documentation only
- `refactor` — no feature/fix change
- `test` — adding tests
- `chore` — tooling, deps
## Rules
1. Subject line max 72 chars, imperative mood ("add" not "added")
2. Scope is optional but helpful: `feat(auth): add OAuth`
3. Body explains *why*, not *what* (the diff shows what)
## Example
Good: `feat(auth): add Google OAuth login`
Bad: `updated auth stuff`