MUST be used when creating, writing, or designing new skills for Claude Code. Covers skill structure, naming conventions, description writing, and trigger optimization...
Use this skill when creating new skills to ensure they are discoverable and useful.
The name and description determine whether an agent will EVER use your skill. Get these wrong and the skill will sit unused while the agent struggles without it.
skills/
āāā skill-name/ # lowercase-with-hyphens, matches name in frontmatter
āāā SKILL.md # The skill definition (mandatory)
āāā skill.json # Optional: declares commands for the runner (see below)
āāā scripts/ # Executable scripts (one per skill command)
āāā my-script.ts # Convention: scripts/<command-name>.{js,ts,py,sh}
All skill scripts are invoked through the Anima runner, which resolves the
script, sets cwd, and injects env vars. Scripts no longer need a cd dance:
anima skill run <skill-id> <command> [args...] # synchronous
anima skill run <skill-id> <command> [...] --task # queue via scheduler
anima skill task <task-id> --watch # poll a queued task
anima skill list # discovery
anima skill help <skill-id> <command> # per-command help
The runner injects these env vars before exec:
SKILL_DIR ā Absolute path to the skill directory. Use this for any
skill-internal resource. Never use process.cwd().SKILL_ID ā Skill identifierSKILL_COMMAND ā Command nameANIMA_TASK_ID ā Only set in --task mode. Pass to
anima scheduler update_progress --taskId "$ANIMA_TASK_ID" --message "..."
for live progress reporting.ANIMA_EXECUTION_ID ā Only set in --task modeWhen absent, any executable file under scripts/ is callable by basename
(e.g., scripts/foo.js ā anima skill run myskill foo). Runtime is
auto-detected by extension or shebang.
For richer behavior ā argv help, longRunning auto-queue, required env
checks ā add a skill.json. Each command resolves to one of two execution
modes (mutually exclusive):
script ā A file inside the skill directoryFor logic that lives with the skill. Relative path. Runtime auto-detected.
{
"id": "writing-romance-novels",
"description": "Generate full-length romance novels ā chapter MP3s and AI cover art.",
"commands": {
"generate-cover": {
"script": "scripts/generate-cover.js",
"runtime": "node",
"longRunning": false,
"description": "Generate cover art using Gemini Imagen from cover.md inside a novel folder.",
"args": [{ "name": "novel-folder", "type": "absolute-folder", "required": true }],
"env": ["GEMINI_API_KEY"],
"timeoutMs": 180000
}
}
}
command ā A binary on PATHFor shared tooling. Avoids duplicating logic across multiple skills. The runner spawns the binary directly with full env injection (SKILL_DIR, ANIMA_TASK_ID, etc.) just like script mode.
{
"id": "writing-romance-novels",
"commands": {
"generate-audio": {
"command": "eleven-tts",
"longRunning": true,
"description": "Generate MP3 audio from chapter markdown using the shared eleven-tts binary.",
"args": [{ "name": "chapter-path", "type": "absolute-file", "required": true }],
"env": ["ELEVENLABS_API_KEY", "ELEVENLABS_VOICE_ID"],
"timeoutMs": 1800000
}
}
}
When to extract a command: If two or more skills would have an
identical (or near-identical) script, extract it once into
anima/scripts/<tool>.js, symlink to ~/.local/bin/<tool>, and point each
skill's command field at the binary name. Future skills get the tool for
free without copy-pasting code.
Effects of longRunning: true: The runner auto-enables --task mode
(returns task ID immediately, executes via the scheduler). Pass --sync to
override and run inline. Works the same in both script and command modes.
---
name: skill-name # lowercase-with-hyphens
description: "..." # What it does AND when to use it - MUST be quoted
---
The description MUST include:
developing-*, processing-*, managing-*, setting-up-*developing-skills, processing-images, managing-adsname: browsing-the-web
description: "MUST be used when you need to browse the web. Efficient browser automation designed for agents - enables intuitive web navigation, form filling, screenshots, and data scraping through accessibility-based workflows. Triggers on: browse website, visit URL, open webpage, fill form, click button, take screenshot, scrape data, web automation, interact with website."
Why it works:
name: transcribing-audio
description: "MUST be used when you need to transcribe audio files to text. Local speech-to-text (STT) transcription using Parakeet MLX on Apple Silicon - fast, private, offline. Triggers on: transcribe audio, convert audio to text, speech to text, STT, transcription, get text from audio, audio file transcription, voice to text, extract text from recording, transcribe podcast, transcribe meeting, transcribe voice memo."
If an agent doesn't invoke your skill, it's almost always because the description didn't match how the user phrased their request.
Test against multiple phrasings:
After the frontmatter, include:
anima skill run ⦠invocationsTake absolute paths in argv. Don't infer paths from CWD. The runner sets
cwd to SKILL_DIR for safety, but explicit absolute paths are clearer.
Use process.env.SKILL_DIR for any skill-internal resource (data files,
playlists, prompt templates) instead of relative paths or process.cwd().
Report progress for long tasks via anima scheduler update_progress
when ANIMA_TASK_ID is set (no-op when not):
const { spawnSync } = require("child_process");
function progress(message) {
if (!process.env.ANIMA_TASK_ID) return;
spawnSync(
"anima",
[
"scheduler",
"update_progress",
"--taskId",
process.env.ANIMA_TASK_ID,
"--message",
message,
],
{ stdio: "ignore", timeout: 5000 },
);
}
Validate required env vars early and exit with a clear error. The runner
also checks commands.*.env from skill.json before exec.
---
name: doing-something
description: "MUST be used when [trigger condition]. [What it does]. Triggers on: [phrase1], [phrase2], [phrase3], [phrase4], [phrase5]."
---
# Doing Something
Use this skill when the user wants to [goal].
## When to Use
- [Scenario 1]
- [Scenario 2]
- [Scenario 3]
## Available Commands
This skill is invoked through the **anima skill runner**.
- **`<command-name>`** ā description of what the command does
Inspect:
\`\`\`bash
anima skill help doing-something <command-name>
\`\`\`
## Instructions
1. [Step 1]
2. [Step 2]
3. [Step 3] ā `anima skill run doing-something <command> <absolute-path-arg>`
## Examples
\`\`\`bash
anima skill run doing-something <command> /absolute/path/to/input
\`\`\`
## Notes
- [Important note 1]
- [Important note 2]
{
"id": "doing-something",
"description": "Short description shown in `anima skill list`.",
"commands": {
"<command-name>": {
// Choose ONE: `script` for skill-local logic, `command` for a PATH binary
"script": "scripts/<command-name>.<ext>",
// OR
"command": "<binary-name>",
"runtime": "node | bun | python3 | bash",
"longRunning": false,
"description": "What the command does.",
"args": [
{
"name": "arg-name",
"type": "absolute-file | absolute-folder | string | number | boolean",
"required": true,
"description": "What this argument is for"
}
],
"env": ["REQUIRED_ENV_VAR_1", "REQUIRED_ENV_VAR_2"],
"timeoutMs": 600000
}
}
}