Skill writer
Author or refactor `.md` skills and rules for AI coding agents — enforces YAML frontmatter schema, trigger-phrase quality, length budgets, and the references/assets progressive-disclosure layout.From its SKILL.md
npx -y skills add infohata/mind-vault --skill skill-writerAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
16.0 KB, as published. Nobody here has run it
skill-writer
Meta-skill that governs how AI agents author and refactor skills (and rules) inside mind-vault or any sibling repository that follows the same convention. Fully IDE-agnostic: the same rules apply whether the invoking host is Claude Code, Cursor, Antigravity, OpenCode, Copilot, or any other skill-aware agent.
When to use
TRIGGER when: user asks to "create/add/write a new skill", "extract a pattern into mind-vault", "formalize an AI codebase rule", "refactor a skill"; or when reviewing/rewriting any file matching skills/*/SKILL.md or rules/RULE_*.md.
SKIP for: one-off prose docs, changelogs, READMEs, ADRs, or in-project configuration files — these are not agent-invoked skills and do not need the SKILL.md contract.
File layout
A skill lives in its own folder whose name is the skill slug:
skills/
└── <skill-slug>/
├── SKILL.md # Pattern body (required, target <500 lines)
├── references/ # Long examples, configs, deep-dive docs (loaded on demand)
│ └── *.md
├── assets/ # Templates/snippets the agent emits verbatim
│ └── *.{py,sh,yml,…}
└── scripts/ # Executable helpers the agent runs
└── *.sh
- Filename must be
SKILL.md(uppercase). Lowercaseskill.mdis not discovered by most hosts. - Folder name =
name:frontmatter field, kebab-case, noskill-prefix (the folder is already underskills/).
Frontmatter contract
Required minimum:
---
name: <kebab-case-slug> # matches folder name
description: <one-line trigger> # <200 chars, noun-dense
---
Optional on larger skills (use when the skill is versioned, replaces older skills, or needs provenance):
license: Apache-2.0
metadata:
author: mind-vault
version: "1.0"
replaces:
- <older-skill-name>
Writing the description
The description is the probabilistic trigger — the only text the host agent inspects when deciding whether to load the skill. Bad descriptions = skill never fires, or fires on the wrong turns.
✅ DO — noun-dense, names the concrete stack, specific verbs:
Apply global cross-project Django backend dev conventions for models, views, signals, Channels, DRF, and all backend architecture before hitting templates or JS.Debug failing tests quickly across any massive Python monolith by surgically specifying and running targeted test paths instead of running full, slow test suites locally.Search outside the project (in IDE plans, AI agent workspaces, or temporary storage) and retrieve standalone artefacts, research, or validation logs to bring them inside the project repository.
❌ DON'T — generic, verb-only, hand-wavy, or buzzword soup:
A skill for helping write frontend code.Helps with Django stuff.Enforce robust anchor store bounding box triggers for elite deployment excellence.
TRIGGER / SKIP expansion
For skills that fire frequently and misfire often (language-specific, stack-specific, or tool-specific skills), add an explicit TRIGGER when / SKIP block at the top of ## When to use. Example from claude-api:
TRIGGER when: code imports `anthropic`/`@anthropic-ai/sdk`; user asks for the
Claude API, Anthropic SDK, or Managed Agents; user adds/modifies/tunes a Claude
feature (caching, thinking, compaction, tool use, batch, files, citations,
memory) or model (Opus/Sonnet/Haiku) in a file.
SKIP: file imports `openai`/other-provider SDK; filename like `*-openai.py`/
`*-generic.py`; provider-neutral code; general programming/ML.
This is load-bearing: it gives the host agent a crisp decision rule instead of vibes, and it's the single biggest lever against false-positive skill activation.
Body structure
Canonical SKILL.md body, in order:
# <title>+ one-paragraph Overview (what this skill covers; what it does not).## When to use— scoping rules, with TRIGGER/SKIP block if applicable.## Pattern— the actual conventions, numbered or named subsections.## When NOT to use these patterns— counter-cases that prevent over-application.## References— the single canonical list of links to./references/*.md, external docs, and related skills. Maintain only one such block per skill. Do not duplicate it under aliases like**Optional extensions**,**Further reading**, or a front-loaded mirror near the top of the file — every line ofSKILL.mdis loaded into context on every activation, so duplicated lists double the bill for the same information. If a reference must be foreshadowed early in the body (e.g. inside## Critical hazards), link to it inline at the point of mention rather than re-listing it. (Several feature-dense skills —django,django-frontend,deployment— historically carried both a top "Optional extensions" block and a bottom## Referencesblock; consolidate on## Referenceswhen touching them.)- No trailing
**Last Updated**: YYYY-MM-DDfooter. File mtime +git logcarry the date for free; a literal trailer costs ~10 tokens on every activation for information the host can derive from the filesystem. History lives inCHANGELOG.md.
The additive-only rule
Skills document deviations from default LLM knowledge, not generic programming advice.
- ❌ Don't explain "what Django is" or "how to write a for-loop".
- ❌ Don't re-document framework basics (
pip install,git commit,npm run build). - ✅ Do document: project-specific conventions, non-obvious ordering constraints, workarounds for known bugs, mixin/base-class contracts, required Makefile targets, opinionated stack choices, negative patterns learned from incidents.
The host agent already knows pip install -r requirements.txt. It does not know that this repo forbids manual .po edits and uses a map-based fill workflow. Write the latter.
The ✅ DO / ❌ DON'T matrix
Every non-trivial convention must include an explicit counter-example. This bounds the agent's guessing space — without the negative side, agents "revert to mean" and produce idiomatic-but-wrong output.
✅ DO: Use `filter(None, [...])` + `"\n".join(...)` to build optional-prefix strings.
❌ DON'T: Use ternaries or `if/else` append-vs-replace logic.
✅ DO: `prefetch_related("content_object")` when iterating models with GenericForeignKey.
❌ DON'T: Access `.content_object` in a loop without prefetch — N+1 storm.
Length budget & progressive disclosure
Target: SKILL.md under 500 lines. Hard stop: ~800 lines.
When a skill outgrows the budget:
- Move long code examples into
references/<TOPIC>.mdand link to them. - Move large templates/snippets into
assets/<name>.<ext>and instruct the agent to read them via tool. - Keep the
SKILL.mdbody focused on decisions, contracts, and pointers. Details load on demand.
<!-- ✅ SKILL.md stays lean -->
### WebSocket support
See [references/ASYNC_WEBSOCKET.md](references/ASYNC_WEBSOCKET.md) for Channels
routing, consumers, and tenant-aware auth middleware.
<!-- ❌ SKILL.md bloating -->
### WebSocket support
<100 lines of consumer code, routing setup, middleware config…>
Why this matters: every line of SKILL.md is loaded into context on every activation. A 1000-line skill spends context budget the downstream task could have used.
Prose density — payload over framing
Skills (and references) are token-priced on every activation. Cut explanatory prose to minimum without dropping payload. First drafts naturally accrete framing prose because the author is mid-context and over-explaining feels safer; a tighten-pass before commit collapses it.
After authoring a new skill/reference, do a tighten-pass targeting ≥30% line reduction. Payload-intact: every code snippet, every numbered trap, every decision rule, every cross-link survives. Only framing prose collapses.
✅ Keep: code blocks; trap-name + one-sentence mechanism; "don't do X — do Y" lines; cross-references; concrete numbers (file counts, wall-time, version pins).
❌ Cut: paragraph framing ("The pieces below are…", "none of this was obvious from…"); re-statements of a bullet's content in surrounding prose; triple-framed "why this matters" expansions where the rule already implies the why; parallel-clause cascades in References-list pointer lines (one topic clause + one payload clause is enough).
Apply identically to references/<TOPIC>.md files — references aren't free, they cost on demand and the user reads them. A 200-line reference that says the same thing in 100 lines is strictly better.
Density has a floor: concrete-first. The v5.5.0 batch harvest compressed ~650 reference lines into pure abstraction and the maintainer's verdict was "this was a hard read" — the tighten-pass must never cut the concrete incident or worked example that anchors a pattern. Open each pattern with the incident, then the general claim, one claim per sentence; a general sentence with no concrete example beside it is unverifiable, not tight. See ../compound/references/mind-vault-promotion.md § Write for the two readers.
Cross-project portability
A skill in mind-vault is consumed by multiple projects. Therefore:
- Concrete project names in the pattern body are leaks. If the pattern says "Project X uses Y" as a universal rule, the rule is wrong for every other project. Either generalize ("Projects with constraint Y should Z") or clearly fence as an example.
- Examples may name real projects, but must be visually fenced:
Example (project-foo): the translation map lives at
tools/translation_maps/*.py. - Never hard-code paths from a consuming project in
References.docs/artefacts/by-agent/researcher/…paths do not exist from the agent's perspective when invoked from a sibling project. - Never hard-code relative paths in templates the skill emits when the skill supports multiple source locations. A template that writes
[docs/ideas/](../ideas/)only works when the source file lives atdocs/execution/...; it breaks fordocs/IDEAS.mdor root-levelIDEAS.md. Parameterise with placeholders (<IDEAS_REL>), derive the path from the actual source location at emit time, and include a worked-examples table for the common cases. See references/emitted-templates.md for the full rule + DO/DON'T.
Skills vs commands — no thin wrappers
A skill with name: X in its frontmatter is already invocable as /X — hosts that support slash menus surface the skill directly. Creating a commands/X.md that just says "Invoke the X skill" duplicates the slash entry (both appear side-by-side in the menu) without adding any behavior.
Write a commands/*.md file only when:
- No same-named skill exists and the command carries its own behavioral spec, OR
- The command is a deliberate alias for another skill (e.g.
/brainstorm→/plan), where the distinct name communicates intent the skill's own slug can't.
Don't:
- Write a
commands/X.mdwhose body is "Invoke theXskill. Seeskills/X/SKILL.md." — it's a redundant registration surface; delete it and trust the skill's own slash-menu entry. - Duplicate the skill's
descriptionin the command frontmatter with slight rewording — drift becomes a maintenance burden and users see both entries with near-identical descriptions, which reads as noise.
✅ DO: skill at `skills/plan/SKILL.md` with `name: plan` → `/plan` appears once in slash menu.
✅ DO: standalone command `commands/brainstorm.md` aliasing `/plan` — different intent framing, no skill equivalent.
❌ DON'T: `commands/plan.md` that says "Invoke the `plan` skill" → `/plan` now appears twice.
The failure mode surfaced as double slash-menu entries across 8 mind-vault names (compound, idea, ideate, ingest-backlog, plan, sprint-auto, work, wrap) where a thin command wrapper existed alongside the skill; dedup in PR #51.
Maintaining skills
- Don't add a trailing
**Last Updated**footer. File mtime +git logare the system of record; an inline date costs ~10 tokens per activation for info the host can derive for free. Narrative belongs inCHANGELOG.md, keyed by the merging PR, where it costs zero context budget. - If an example drifts out of sync with real code, fix it or delete it — stale examples are worse than none.
- When merging two skills, keep
metadata.replacesso agents recognize old names. - When deprecating a skill, leave a tombstone
SKILL.mdthat points to the successor rather than deleting silently.
Versioning (optional, sidecar file)
Anthropic's official Agent Skills spec defines no version field, and Anthropic's published skills (github.com/anthropics/skills) carry no version metadata. Most skills therefore don't need a version at all — CHANGELOG.md + git log is the system of record.
For feature-dense skills where a version handle is genuinely useful (a quick "are we on the same edition?" reading at a glance), use a sidecar VERSION file in the skill's directory:
skills/django/
├── SKILL.md
├── VERSION ← single line, e.g. "5.5\n"
├── references/
└── …
Why a sidecar:
- Zero SKILL.md context cost. The host loads
SKILL.md(and references on demand), not arbitrary sibling files. AVERSIONfile is invisible to the host agent and free at activation time. - Easy to grep, easy to bump.
cat skills/*/VERSIONshows the matrix; a pre-commit hook can read it. - Spec-neutral. Adding a frontmatter
version:field would conflict with the official spec the day Anthropic standardises one; a sidecar is plain ad-hoc tooling.
Bumping discipline: monotonic, project-defined (SemVer-ish or just MAJOR.MINOR). Bump on substantive pattern additions, not docs polish — the version handle should mean something.
Don't add a VERSION file to every skill. Add it only where the question "what edition am I reading?" actually arises — that's the threshold.
Minimal skeleton
Copy this as the starting point for any new skill:
---
name: my-skill
description: <one-line trigger under 200 chars, noun-dense, names the concrete stack>
---
# my-skill
Overview: what this pattern does, what stack it assumes, what it does not cover.
## When to use
TRIGGER when: <conditions>
SKIP: <conditions>
## Pattern
### 1. <First convention>
<short explanation>
✅ DO: <example>
❌ DON'T: <counter-example>
### 2. <Second convention>
…
## When NOT to use these patterns
- <case 1>
- <case 2>
## References
- [details](references/DETAILS.md)
- [Related skill](../other-skill/SKILL.md)
References
- Adjacent examples in this repo:
skills/artefact-retrieval/SKILL.md,skills/surgical-tdd/SKILL.md(lean),skills/django/SKILL.md(feature-dense) - references/MARKDOWN_FORMATTER_GOTCHAS.md — constructs auto-formatters (mdformat / markdownlint) silently rewrite in a meaning-changing way (e.g. a literal
+/-/*at the start of a wrapped prose line becoming a list item); author defensively + read the diff after formatting - references/LANGUAGE_CONVENTIONS.md — the house register for everything authored in mind-vault: US-English spelling (matching the US-spelled API identifiers every stack already uses) but metric/SI units and Celsius; scope limits (never impose it on a consuming project, never rewrite released CHANGELOG or archived docs), sweep false positives, and the ISO-date/24h conventions already in force
- Git Safety Rule — applies to commits produced while authoring skills
- Anthropic's Claude Code Agent Skills documentation (
docs.claude.com) — the officialSKILL.mdspec this skill aligns with