Skill Author
Helps you write new agent skills that follow the best-practices documented at
https://agentskills.io/skill-creation/ — without you having to re-read those pages
every time. Pairs with skill-creator (which handles eval/iterate/optimize loops
once a draft exists).
When to use this vs skill-creator
| Task |
Use |
| "I want to make a new skill for X" |
skill-author (scaffold + author) |
| "Scaffold the SKILL.md / a reference / a script" |
skill-author |
| "Lint this skill draft" |
skill-author |
| "My skill isn't triggering when I want it to" |
skill-creator (description optimization) |
| "Run test cases against my skill, benchmark it" |
skill-creator (eval loop) |
| "Compare two versions of my skill" |
skill-creator (blind comparison) |
If both apply, start here, then hand off to skill-creator once the draft is solid.
Workflow
1. Capture intent (1 minute)
Before scaffolding, get four answers — usually just by asking the user:
- What does it do? (one sentence)
- When should it trigger? (specific user phrases / contexts)
- What does it output? (file, command result, plan, prose)
- Is the output objectively verifiable? (decides whether
skill-creator evals are worth the effort later)
Write these four down before touching files. They become the seeds for the
description, the workflow body, and the future eval set.
2. Scaffold
Use scripts/new-skill.sh to produce the directory layout. The script
auto-detects scope (where to put the skill) and fans out discovery
symlinks for non-universal agents so the skill is loadable immediately.
bash skills/local/skill-author/scripts/new-skill.sh <skill-name>
Three scopes (auto-detected; override with --local / --project / --global):
| Scope |
Canonical dir |
Symlinks created |
| LOCAL (this publishing repo: vendor.yaml / skills/local/ found walking up) |
<repo>/skills/local/<name>/ (or skills/vendor/<name>/ with --vendor) |
.agents/skills/<name> + .claude/skills/<name> -> ../../skills/{local,vendor}/<name> |
| PROJECT (inside another git repo) |
<repo>/.agents/skills/<name>/ (universal agents — Cursor / Codex / OpenCode / Warp — pick this up directly) |
.claude/skills/<name> -> ../../.agents/skills/<name> (+ any already-present non-universal agent dir at the repo root) |
| GLOBAL (no git repo found) |
~/.agents/skills/<name>/ |
~/.claude/skills/<name> -> ../../.agents/skills/<name> (+ any detected non-universal agent dir under $HOME) |
The template's frontmatter has placeholders that lint will reject — this is on
purpose so the agent can't forget to fill them in.
Important: When the user's intent is ambiguous (they're inside a git repo
but haven't said whether the skill should live with the project or be
available everywhere), ask "system-wide (--global) or just this
project (--project)?" before running the script. The script is
non-interactive — once you've picked a scope, files land and symlinks fan
out without further prompting.
After running, the script emits a single JSON object on stdout with
{skill, mode, canonical, symlinks[], next_steps[]} so you can chain
follow-up actions deterministically.
3. Author the SKILL.md
Read references/authoring-patterns.md before writing the body. The patterns
that matter most:
- Description must be "pushy" and include concrete trigger contexts. Naive
descriptions cause undertriggering — the #1 failure mode of new skills. Keep
this within the cross-agent budget: 120-500 chars is the preferred range,
501-900 is valid but context-heavy, 901-1024 is valid but close to hard
loader limits, and >1024 is invalid for Codex/Cursor/spec-aligned skills.
- Gotchas section — environment-specific facts that defy reasonable
assumptions. The single highest-value section in most skills.
- Output templates — agents pattern-match against concrete structures more
reliably than they follow prose descriptions of formats.
- Calibrated specificity — be prescriptive only where the task is fragile;
give the agent freedom (and explain why) where multiple approaches are valid.
- Defaults, not menus — pick one tool/approach and mention alternatives as
escape hatches.
Keep SKILL.md under 500 lines. If you blow past that, move detail into
references/<topic>.md and tell the agent when to load it ("Read X if Y
happens"), not just that it exists.
4. Design any scripts
Before writing a script, read references/script-design.md. Skills script
design is meaningfully different from "regular" CLI script design because the
caller is an LLM reading your stderr to decide what to do next. The non-obvious
requirements:
- No interactive prompts, ever (agents run in non-interactive shells)
--help is the primary interface documentation — keep it concise but complete
- Errors must say what was expected and what to try, not just what failed
- Structured stdout (JSON/CSV/TSV), prose diagnostics to stderr — separate them
--dry-run for any destructive operation
- Pin versions for
uvx / npx / pipx invocations
For Python helpers, prefer PEP 723 inline dependencies + uv run over
requirements.txt — the script becomes self-contained and the agent doesn't
have to set up an environment first.
5. Lint
Run the linter before committing or handing off to skill-creator:
bash skills/local/skill-author/scripts/lint-skill.sh skills/local/<skill-name>
It checks three things:
- Frontmatter & length —
name and description exist; name is
hyphen-case and <=64 chars; description has a "use when" trigger phrase,
respects the 1024-char hard limit, and SKILL.md is under 500 lines.
- Script hygiene — every
scripts/*.sh has a shebang, is executable, and
responds to --help (presence of the flag handler, not necessarily a working
script).
- Reference reachability — every file in
references/ is mentioned at
least once from SKILL.md (no dead reference docs).
Fix every error. Warnings are advisory but usually worth addressing.
6. (Optional) Hand off to skill-creator
Once lint passes and the skill looks right, the next questions are
quantitative: does it trigger reliably? does it produce good output? That's
skill-creator territory. Tell the user: "skill-author got the structure
right. If you want to validate it works on real prompts, the skill-creator
skill runs test cases and benchmarks."
Available scripts
scripts/new-skill.sh <name> — Scaffold the canonical skill dir
(SKILL.md, references/, scripts/, assets/) and add discovery symlinks for
non-universal agents. Auto-detects scope (LOCAL / PROJECT / GLOBAL); see
table in step 2.
- Scope flags (mutually exclusive):
--local (force this repo's
skills/local/), --project (force <repo>/.agents/skills/),
--global (force ~/.agents/skills/).
- Other flags:
--vendor (LOCAL only — skills/vendor/<name>/ instead of
skills/local/; rare, vendored skills normally come via vendor.yaml);
--root DIR (override walk-up); --no-symlinks (skip the fan-out);
--dry-run; --force (overwrite existing canonical dir + replace
symlinks).
scripts/lint-skill.sh <skill-dir> — Run frontmatter, script hygiene,
and reference reachability checks. Exit non-zero on any error.
- Flags:
--strict (treat warnings as errors); --quiet (only print failures).
scripts/lint-frontmatter.sh [PATH...] — YAML-parse the frontmatter of
every SKILL.md under PATH (default .) with a real parser, and check that
the root is a mapping with string name + description. Catches the
breakage class lint-skill.sh's awk extractor cannot see — an unquoted
description: containing ": " makes npx skills (and Claude Code /
Cursor) silently skip the skill. lint-skill.sh calls this for the
single-skill case; run it directly to sweep a whole collection.
- Flags:
--parser auto|yq|python3|node (node = the js yaml package,
exactly what npx skills uses); --quiet.
Bundled assets
Templates that new-skill.sh copies and that you can reference manually:
assets/SKILL.md.template — Frontmatter + workflow skeleton with placeholders.
assets/reference.md.template — Reference doc skeleton (TOC + sections).
assets/script-bash.template — Bash 3.2 compatible script with set -euo pipefail,
--help / --dry-run flag handler, structured-output friendly logging
(data → stdout, prose → stderr).
assets/script-python.template — Python script with PEP 723 inline-deps
block, argparse with help/examples, dry-run support.
Reference files
references/authoring-patterns.md — The agentskills.io "best practices"
page condensed: gotchas, templates, validation loops, calibrated specificity,
defaults-not-menus, procedures-over-declarations, plan-validate-execute.
references/script-design.md — The agentskills.io "using scripts" page
condensed: agentic CLI design, structured output, error message style,
PEP 723, uvx/npx/pipx version pinning, dry-run patterns.
references/this-repo-conventions.md — Conventions specific to this
repository: where to put local vs vendor skills, how the 5-level skill
search works, AGENTS.md ↔ CLAUDE.md sync, where mirrored scripts live.
Gotchas
- AGENTS.md is a symlink to CLAUDE.md — edit either one; never replace the
symlink with a real file.
- Skill discovery is one level deep first, then recursive up to 5 levels.
skills/local/<name>/SKILL.md works because of the recursive fallback. Don't
nest skills more than 5 deep or they become invisible.
bash 3.2 compatibility is required for any script that might run on
stock macOS. No mapfile, no ${var,,} lowercasing, no [[ -v var ]].
See references/script-design.md for the safe subset.
description is always-on context and has agent-specific hard limits.
Put concrete trigger phrases in frontmatter, but keep local skills in the
120-500 char preferred range when possible. Treat >1024 chars as invalid:
Codex and Cursor/spec-aligned validators can skip the skill entirely.
- Quote any
description containing :, #, or leading punctuation. An
unquoted YAML plain scalar cannot contain ": " — npx skills fails with
"Nested mappings are not allowed in compact mappings" and drops the skill
from the picker without a non-zero exit. # is worse: it parses, but YAML
treats the rest as a comment and silently truncates your trigger string.
Single quotes need no escaping except ' itself. Run
scripts/lint-frontmatter.sh to catch both; see
pitfalls/skill-description-colon-breaks-yaml-frontmatter.md in this repo.
- Don't write a skill that wraps something the agent already does well.
If a stock Claude session handles the task in one turn without help, a skill
adds context-window cost for no gain. Test the no-skill baseline before
investing in authoring.
- Scope auto-detect can surprise you.
new-skill.sh walks up looking for
a publishing-repo anchor (vendor.yaml / skills/local/ /
skills/.claude-plugin/) first, then a .git. If you ran it from inside
a clone of this repo while meaning to add a skill to your other project,
it'll silently land in skills/local/. Pass --project or --global
explicitly when intent isn't obvious, and prefer asking the user
system-wide-vs-project-wide before running.
- Discovery symlinks must be
../../-relative, not repo-root-relative —
POSIX resolves symlink targets relative to the link's own directory. The
script enforces this and verifies each link with test -e <link>/SKILL.md;
if you ever hand-create one, see
pitfalls/symlink-target-relative-to-symlink-not-cwd.md.
When the user is updating an existing skill (not creating new)
Same workflow, but skip step 2 (scaffold). Read the existing SKILL.md first,
identify which patterns from references/authoring-patterns.md are missing or
weakly applied, and propose edits one section at a time so the user can sanity
check. After edits, run lint, then offer the skill-creator handoff for
quantitative validation.
1---2name: skill-author3description: Author a new agent skill or refactor an existing one to follow agentskills.io best practices — gotchas sections, output templates, validation loops, calibrated specificity (fragility-based), and agentic script design (--help, --dry-run, structured stdout, stderr diagnostics, PEP 723 inline deps, pinned uvx/npx versions). Use whenever the user wants to create a new skill from scratch, scaffold a SKILL.md, write a reference file, design a script meant to be invoked by an agent, lint a draft skill for quality, or convert an ad-hoc workflow into a reusable skill. For evaluating skill output quality with test cases, benchmarking, or optimizing the description trigger rate, defer to the `skill-creator` skill instead — this skill focuses on authoring, not evaluation.4---56# Skill Author78Helps you write **new agent skills** that follow the best-practices documented at9https://agentskills.io/skill-creation/ — without you having to re-read those pages10every time. Pairs with `skill-creator` (which handles eval/iterate/optimize loops11once a draft exists).1213## When to use this vs `skill-creator`1415| Task | Use |16|---|---|17| "I want to make a new skill for X" | **skill-author** (scaffold + author) |18| "Scaffold the SKILL.md / a reference / a script" | **skill-author** |19| "Lint this skill draft" | **skill-author** |20| "My skill isn't triggering when I want it to" | `skill-creator` (description optimization) |21| "Run test cases against my skill, benchmark it" | `skill-creator` (eval loop) |22| "Compare two versions of my skill" | `skill-creator` (blind comparison) |2324If both apply, start here, then hand off to `skill-creator` once the draft is solid.2526## Workflow2728### 1. Capture intent (1 minute)2930Before scaffolding, get four answers — usually just by asking the user:31321. **What does it do?** (one sentence)332. **When should it trigger?** (specific user phrases / contexts)343. **What does it output?** (file, command result, plan, prose)354. **Is the output objectively verifiable?** (decides whether `skill-creator` evals are worth the effort later)3637Write these four down before touching files. They become the seeds for the38description, the workflow body, and the future eval set.3940### 2. Scaffold4142Use `scripts/new-skill.sh` to produce the directory layout. The script43auto-detects **scope** (where to put the skill) and fans out discovery44symlinks for non-universal agents so the skill is loadable immediately.4546```bash47bash skills/local/skill-author/scripts/new-skill.sh <skill-name>48```4950Three scopes (auto-detected; override with `--local` / `--project` / `--global`):5152| Scope | Canonical dir | Symlinks created |53|---|---|---|54| **LOCAL** (this publishing repo: vendor.yaml / skills/local/ found walking up) | `<repo>/skills/local/<name>/` (or `skills/vendor/<name>/` with `--vendor`) | `.agents/skills/<name>` + `.claude/skills/<name>` -> `../../skills/{local,vendor}/<name>` |55| **PROJECT** (inside another git repo) | `<repo>/.agents/skills/<name>/` (universal agents — Cursor / Codex / OpenCode / Warp — pick this up directly) | `.claude/skills/<name>` -> `../../.agents/skills/<name>` (+ any already-present non-universal agent dir at the repo root) |56| **GLOBAL** (no git repo found) | `~/.agents/skills/<name>/` | `~/.claude/skills/<name>` -> `../../.agents/skills/<name>` (+ any detected non-universal agent dir under `$HOME`) |5758The template's frontmatter has placeholders that lint will reject — this is on59purpose so the agent can't forget to fill them in.6061> **Important**: When the user's intent is ambiguous (they're inside a git repo62> but haven't said whether the skill should live with the project or be63> available everywhere), **ask** "system-wide (`--global`) or just this64> project (`--project`)?" before running the script. The script is65> non-interactive — once you've picked a scope, files land and symlinks fan66> out without further prompting.6768After running, the script emits a single JSON object on stdout with69`{skill, mode, canonical, symlinks[], next_steps[]}` so you can chain70follow-up actions deterministically.7172### 3. Author the SKILL.md7374Read `references/authoring-patterns.md` before writing the body. The patterns75that matter most:7677- **Description must be "pushy"** and include concrete trigger contexts. Naive78 descriptions cause undertriggering — the #1 failure mode of new skills. Keep79 this within the cross-agent budget: 120-500 chars is the preferred range,80 501-900 is valid but context-heavy, 901-1024 is valid but close to hard81 loader limits, and >1024 is invalid for Codex/Cursor/spec-aligned skills.82- **Gotchas section** — environment-specific facts that defy reasonable83 assumptions. The single highest-value section in most skills.84- **Output templates** — agents pattern-match against concrete structures more85 reliably than they follow prose descriptions of formats.86- **Calibrated specificity** — be prescriptive only where the task is fragile;87 give the agent freedom (and explain *why*) where multiple approaches are valid.88- **Defaults, not menus** — pick one tool/approach and mention alternatives as89 escape hatches.9091Keep `SKILL.md` under 500 lines. If you blow past that, move detail into92`references/<topic>.md` and tell the agent **when** to load it ("Read X if Y93happens"), not just that it exists.9495### 4. Design any scripts9697Before writing a script, read `references/script-design.md`. Skills script98design is meaningfully different from "regular" CLI script design because the99caller is an LLM reading your stderr to decide what to do next. The non-obvious100requirements:101102- No interactive prompts, ever (agents run in non-interactive shells)103- `--help` is the primary interface documentation — keep it concise but complete104- Errors must say *what was expected* and *what to try*, not just *what failed*105- Structured stdout (JSON/CSV/TSV), prose diagnostics to stderr — separate them106- `--dry-run` for any destructive operation107- Pin versions for `uvx` / `npx` / `pipx` invocations108109For Python helpers, prefer **PEP 723 inline dependencies** + `uv run` over110`requirements.txt` — the script becomes self-contained and the agent doesn't111have to set up an environment first.112113### 5. Lint114115Run the linter before committing or handing off to `skill-creator`:116117```bash118bash skills/local/skill-author/scripts/lint-skill.sh skills/local/<skill-name>119```120121It checks three things:1221231. **Frontmatter & length** — `name` and `description` exist; name is124 hyphen-case and <=64 chars; description has a "use when" trigger phrase,125 respects the 1024-char hard limit, and SKILL.md is under 500 lines.1262. **Script hygiene** — every `scripts/*.sh` has a shebang, is executable, and127 responds to `--help` (presence of the flag handler, not necessarily a working128 script).1293. **Reference reachability** — every file in `references/` is mentioned at130 least once from `SKILL.md` (no dead reference docs).131132Fix every error. Warnings are advisory but usually worth addressing.133134### 6. (Optional) Hand off to skill-creator135136Once lint passes and the skill *looks* right, the next questions are137quantitative: does it trigger reliably? does it produce good output? That's138`skill-creator` territory. Tell the user: "skill-author got the structure139right. If you want to validate it works on real prompts, the `skill-creator`140skill runs test cases and benchmarks."141142## Available scripts143144- **`scripts/new-skill.sh <name>`** — Scaffold the canonical skill dir145 (SKILL.md, references/, scripts/, assets/) and add discovery symlinks for146 non-universal agents. Auto-detects scope (LOCAL / PROJECT / GLOBAL); see147 table in step 2.148 - Scope flags (mutually exclusive): `--local` (force this repo's149 `skills/local/`), `--project` (force `<repo>/.agents/skills/`),150 `--global` (force `~/.agents/skills/`).151 - Other flags: `--vendor` (LOCAL only — `skills/vendor/<name>/` instead of152 `skills/local/`; rare, vendored skills normally come via `vendor.yaml`);153 `--root DIR` (override walk-up); `--no-symlinks` (skip the fan-out);154 `--dry-run`; `--force` (overwrite existing canonical dir + replace155 symlinks).156- **`scripts/lint-skill.sh <skill-dir>`** — Run frontmatter, script hygiene,157 and reference reachability checks. Exit non-zero on any error.158 - Flags: `--strict` (treat warnings as errors); `--quiet` (only print failures).159- **`scripts/lint-frontmatter.sh [PATH...]`** — YAML-parse the frontmatter of160 every `SKILL.md` under PATH (default `.`) with a real parser, and check that161 the root is a mapping with string `name` + `description`. Catches the162 breakage class `lint-skill.sh`'s awk extractor cannot see — an unquoted163 `description:` containing `": "` makes `npx skills` (and Claude Code /164 Cursor) **silently skip the skill**. `lint-skill.sh` calls this for the165 single-skill case; run it directly to sweep a whole collection.166 - Flags: `--parser auto|yq|python3|node` (`node` = the js `yaml` package,167 exactly what `npx skills` uses); `--quiet`.168169## Bundled assets170171Templates that `new-skill.sh` copies and that you can reference manually:172173- `assets/SKILL.md.template` — Frontmatter + workflow skeleton with placeholders.174- `assets/reference.md.template` — Reference doc skeleton (TOC + sections).175- `assets/script-bash.template` — Bash 3.2 compatible script with `set -euo pipefail`,176 `--help` / `--dry-run` flag handler, structured-output friendly logging177 (data → stdout, prose → stderr).178- `assets/script-python.template` — Python script with PEP 723 inline-deps179 block, argparse with help/examples, dry-run support.180181## Reference files182183- `references/authoring-patterns.md` — The agentskills.io "best practices"184 page condensed: gotchas, templates, validation loops, calibrated specificity,185 defaults-not-menus, procedures-over-declarations, plan-validate-execute.186- `references/script-design.md` — The agentskills.io "using scripts" page187 condensed: agentic CLI design, structured output, error message style,188 PEP 723, uvx/npx/pipx version pinning, dry-run patterns.189- `references/this-repo-conventions.md` — Conventions specific to *this*190 repository: where to put local vs vendor skills, how the 5-level skill191 search works, AGENTS.md ↔ CLAUDE.md sync, where mirrored scripts live.192193## Gotchas194195- **AGENTS.md is a symlink to CLAUDE.md** — edit either one; never replace the196 symlink with a real file.197- **Skill discovery is one level deep first, then recursive up to 5 levels.**198 `skills/local/<name>/SKILL.md` works because of the recursive fallback. Don't199 nest skills more than 5 deep or they become invisible.200- **`bash 3.2` compatibility** is required for any script that might run on201 stock macOS. No `mapfile`, no `${var,,}` lowercasing, no `[[ -v var ]]`.202 See `references/script-design.md` for the safe subset.203- **`description` is always-on context and has agent-specific hard limits.**204 Put concrete trigger phrases in frontmatter, but keep local skills in the205 120-500 char preferred range when possible. Treat >1024 chars as invalid:206 Codex and Cursor/spec-aligned validators can skip the skill entirely.207- **Quote any `description` containing `:`, `#`, or leading punctuation.** An208 unquoted YAML plain scalar cannot contain `": "` — `npx skills` fails with209 "Nested mappings are not allowed in compact mappings" and drops the skill210 from the picker without a non-zero exit. ` #` is worse: it parses, but YAML211 treats the rest as a comment and silently truncates your trigger string.212 Single quotes need no escaping except `'` itself. Run213 `scripts/lint-frontmatter.sh` to catch both; see214 `pitfalls/skill-description-colon-breaks-yaml-frontmatter.md` in this repo.215- **Don't write a skill that wraps something the agent already does well.**216 If a stock Claude session handles the task in one turn without help, a skill217 adds context-window cost for no gain. Test the no-skill baseline before218 investing in authoring.219- **Scope auto-detect can surprise you.** `new-skill.sh` walks up looking for220 a publishing-repo anchor (`vendor.yaml` / `skills/local/` /221 `skills/.claude-plugin/`) *first*, then a `.git`. If you ran it from inside222 a clone of this repo while meaning to add a skill to your *other* project,223 it'll silently land in `skills/local/`. Pass `--project` or `--global`224 explicitly when intent isn't obvious, and prefer asking the user225 system-wide-vs-project-wide before running.226- **Discovery symlinks must be `../../`-relative**, not repo-root-relative —227 POSIX resolves symlink targets relative to the link's own directory. The228 script enforces this and verifies each link with `test -e <link>/SKILL.md`;229 if you ever hand-create one, see230 [`pitfalls/symlink-target-relative-to-symlink-not-cwd.md`](../../../pitfalls/symlink-target-relative-to-symlink-not-cwd.md).231232## When the user is updating an existing skill (not creating new)233234Same workflow, but skip step 2 (scaffold). Read the existing SKILL.md first,235identify which patterns from `references/authoring-patterns.md` are missing or236weakly applied, and propose edits one section at a time so the user can sanity237check. After edits, run lint, then offer the `skill-creator` handoff for238quantitative validation.