agents/skills/write-skill/SKILL.md
Create or improve a Claude Code skill/slash command with best practices for structure, dynamic context, and safety. Use for creating new skills, improving existing ones, or learning skill authoring.
npx skillsauth add drn/dots write-skillInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Create or improve Claude Code skills (slash commands) following established patterns and avoiding known pitfalls.
$ARGUMENTS - What the skill should do, or the name of an existing skill to improvefind ~/.claude/commands -maxdepth 1 -name "*.md" -exec basename {} .md \; 2>/dev/null | sort | head -20find . -maxdepth 3 -path "*/skills/*/SKILL.md" 2>/dev/null | head -20find . -path "./claude/commands/*.md" 2>/dev/null | head -20find . -maxdepth 1 \( -name go.mod -o -name Gemfile -o -name package.json -o -name Cargo.toml -o -name pyproject.toml \) 2>/dev/null | head -3Determine whether the user wants to:
If creating, ask the user what the skill should do if $ARGUMENTS is vague.
Plan the skill structure:
--- fences)Detect the project skill convention from the context above:
*/skills/*/SKILL.md (Agent Skills standard), create <skills-dir>/<name>/SKILL.mdclaude/commands/<name>.md (Claude Code standard)Follow all rules below carefully.
All fields are optional. Only description is strongly recommended.
---
description: One-line summary of what this skill does and when to use it
allowed-tools: Bash(git *), Bash(npm test)
---
| Field | Purpose |
|---|---|
| description | Drives auto-activation and / menu. Write in third person. Max 1024 chars. Include trigger keywords. |
| allowed-tools | Tools Claude can use without asking permission. Glob patterns supported. |
| context | Set to fork to run in an isolated subagent (no conversation history). |
| agent | Subagent type when context: fork (e.g., Explore, Plan). |
| model | Override model (e.g., sonnet for cheaper tasks). |
| disable-model-invocation | true to prevent auto-loading (manual /name only). Use for destructive skills. |
| user-invocable | false to hide from / menu (background knowledge only). |
Inject live data by writing an exclamation mark followed by a command wrapped in backticks. The command runs locally and its output replaces the placeholder before Claude sees the prompt.
In the examples below, !{command} represents the actual syntax (exclamation mark + backtick + command + backtick). Curly braces are used here to prevent this skill file from executing its own examples.
## Context
- Current branch: !{git branch --show-current}
- Git status: !{git status --short}
- Project type: !{ls -1 go.mod package.json Cargo.toml 2>/dev/null | head -3}
$() Command SubstitutionClaude Code blocks $() inside dynamic context expressions for security reasons. This is the single most common authoring mistake.
# BROKEN — $() is blocked
- Branch commits: !{DEFAULT=$(git symbolic-ref ...) && git log origin/$DEFAULT..HEAD}
- Changes: !{git diff --stat HEAD...$(git symbolic-ref ...)}
# FIXED — detect base branch portably, provide both branches
- Base ref: !{git branch -r 2>/dev/null | grep -oE 'origin/(main|master)' | head -1}
- Commits vs main: !{git log origin/main..HEAD --oneline 2>/dev/null | head -20}
- Commits vs master: !{git log origin/master..HEAD --oneline 2>/dev/null | head -20}
- Changes vs main: !{git diff --stat HEAD...origin/main 2>/dev/null | head -50}
- Changes vs master: !{git diff --stat HEAD...origin/master 2>/dev/null | head -50}
Alternatives to $():
command1 | command2 | command3command 2>/dev/null (empty output on failure is fine)git branch -r | grep -oE 'origin/(main|master)' | head -1 — portable, no custom tools neededorigin/main and origin/master variants — one will be empty, the agent uses whichever has outputAlways bound output to avoid blowing up the context window:
# GOOD — bounded output
- Files: !{find . -maxdepth 3 -name "*.go" 2>/dev/null | head -20}
- Commits: !{git log --oneline -10}
# BAD — unbounded, could be massive
- Files: !{find . -name "*.go"}
- Log: !{git log}
Never use || or && — Claude Code's permission system treats these as multiple operations and blocks them.
Use 2>/dev/null to suppress stderr, but it does not fix exit codes. When a command fails, the skill loader sees the non-zero exit code and treats it as an error, even though stderr is suppressed. This breaks skill loading entirely.
Fix: always pipe through | head -N after 2>/dev/null. In a pipeline, the exit code is that of the last command (head), which exits 0 even when the upstream command fails and produces no output.
# BAD — 2>/dev/null suppresses stderr but exit code is still non-zero
- Tag: !{git describe --tags --abbrev=0 2>/dev/null}
- Commits: !{git log origin/master..HEAD --oneline 2>/dev/null}
# BAD — || treated as multiple operations by permission system
- Tag: !{git describe --tags --abbrev=0 2>/dev/null || echo "No tags"}
# GOOD — pipe neutralizes exit code, empty output on failure is fine
- Tag: !{git describe --tags --abbrev=0 2>/dev/null | head -1}
- Commits: !{git log origin/master..HEAD --oneline 2>/dev/null | head -50}
| Variable | Description |
|---|---|
| $ARGUMENTS | All arguments the user passed after /skill-name |
| $ARGUMENTS[0], $1 | First argument (0-indexed) |
disable-model-invocation: true for skills with side effects (deploy, merge, send).Skills follow this general structure (path varies by convention -- see Step 3):
---
description: ...
allowed-tools: ... (optional)
---
## Context
- Key info: !{command}
## Your task / Instructions
Step-by-step instructions for Claude.
### Step 1: ...
### Step 2: ...
Multi-agent skills (like /dev, /debug, /explore) use the Task tool to spawn subagents with specific roles.
After writing, run two validation passes. Fix issues silently — only flag if the fix would change the skill's intent.
$() in any dynamic context line|| or && operators in any dynamic context line2>/dev/null | head -N (suppresses stderr AND neutralizes exit code)2>/dev/null without a trailing pipe (exit code breaks skill loading)disable-model-invocation: trueScan the skill for these failure patterns. Fix any you find — these are the patterns that cause skills to waste tokens, loop endlessly, or produce wrong results.
Task clarity
Scope control
Stop conditions
Context efficiency
Report the validation results and the file path of the new/updated skill.
development
Walk every unresolved review thread on a PR, triage each one, reply with a rationale of whether or not the comment will be acted upon, make the code change if warranted, and mark the thread resolved. Use when the user asks to address only the open PR comments without re-running CI, respond to review feedback, resolve review threads, or clear bot comments on a PR.
tools
Iteratively run /rereview, fix the findings, and loop until reviewers approve clean. Use for iterative automated review, when you want /rereview to loop until clean, or for a paranoid pre-merge review that auto-addresses every blocker.
development
Generate self-contained HTML visualizations with Plannotator theming. Use for implementation plans, PR explainers, architecture diagrams, data tables, slide decks, and any visual explanation of technical concepts. Plans and PR explainers follow Plannotator's prescriptive approach; all other visual content delegates to nicobailon/visual-explainer.
development
Create reviewed Codex goal setup packages for long-running /goal work. Use when the user wants to turn an idea, backlog, project mission, or vague objective into durable goal files under a project goals slug folder, with Plannotator review gates for brief, narrative plan with acceptance criteria, verification, blockers, and the final /goal prompt.