whetstone
AGENTS.md36 starsChanged 4 months agoMITView on GitHub
Claude Code plugin for PHP/React/Python/JavaScript/TypeScript workflows. Includes the plugin (agents, commands, skills, hooks), a skill distillery, and a CLI for cross-tool conversion.
- Installs packages
Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.
Of the AGENTS.md files we read, the 31,439 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
In this repository13 other files it gives its agents.
- analyze-misfiresSkill
- announceSkill
- audit-pluginSkill
- diagnose-negativesSkill
- eval-skillsSkill
- evolve-skillSkill
- prune-sync-logSkill
- releaseSkill
- skilloptSkill
- sync-from-reposSkill
- triage-prsSkill
- write-skillSkill
- skill-distillerSkill
The file
Show its rules and text
We split this AGENTS.md into the rules it gives an agent
31 rules. About 0 are common, 6 are distinctive, and 25 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈6
Distinctive · estimate
This author's own choices. Worth a look.
25
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 47
Do not delete or overwrite user data.
- Distinctive: line 51
Read before claiming "new": Before presenting sync/improvement findings, read the target's body, not its description or frontmatter, to …
- Very specific: line 65
When /release runs, it:
- Very specific: line 89
Do not touch release versions, CHANGELOG.md, or README component counts on regular edits.
- Very specific: line 90
If a session-end summary says "bumped to vX.Y.Z" without the user invoking /release, that is a regression — back out the bump before …
- Very specific: line 95
All skills, agents, and commands in the plugin carry an ia- prefix.
- Very specific: line 102
Every directory under plugins/whetstone/skills/ starts with ia-.
- Very specific: line 103
Every agent file under plugins/whetstone/agents/ starts with ia- (flat layout, no category subdirectories).
- Very specific: line 104
Every command file under plugins/whetstone/commands/ starts with ia-.
- Very specific: line 111
Every shipped skill declares a class: field in frontmatter.
- Very specific: line 122
If the skill content reads like a stack reference (install, config, idioms, migrations), it's language.
- Very specific: line 123
If the content is "how to do X well" without naming a stack, it's discipline.
- Very specific: line 124
If the content is a phased process producing artifacts, it's workflow.
- Very specific: line 125
If the subject of the skill is agents, prompts, or skills themselves, it's meta.
- Very specific: line 126
Default to tool only if none of the above fit and the scope is genuinely narrow.
- Distinctive: line 134
When adding or modifying skills, verify:
- Very specific: line 173
Avoid ${CLAUDE_SKILL_DIR}: it is empty outside Claude Code, and every skill here ships cross-harness.
- Very specific: line 196
Keep component edits separate from release bookkeeping.
- Very specific: line 200
Create plugins/whetstone/agents/ia-new-agent.md (flat layout)
- Very specific: line 210
Create plugins/whetstone/skills/ia-skill-name/SKILL.md with the required frontmatter.
- Very specific: line 211
Add its trigger pattern to plugins/whetstone/hooks/skill-patterns.sh.
- Very specific: line 212
Add trigger regression fixtures to distillery/tests/fixtures/triggers/ia-skill-name.jsonl.
- Very specific: line 218
Add hook entry to plugins/whetstone/hooks/hooks.json
- Very specific: line 219
Create hook script in plugins/whetstone/hooks/
- Distinctive: line 220
Test the hook's emitted protocol and intended caller behavior.
- Distinctive: line 312
All commands can also be run standalone for targeted analysis.
- Very specific: line 316
Every trigger pattern fix should add a regression test case to distillery/tests/fixtures/triggers/<skill>.jsonl to prevent regressions.
- Distinctive: line 337
Only include fields from the official Claude Code spec:
- Very specific: line 343
Do not add custom fields (downloads, stars, rating, categories, etc.).
- Very specific: line 345
Keep renames as append-only history from former plugin names to current names or null.
- Very specific: line 388
Never --set-labels (it erases other labels).
≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Whetstone
Claude Code plugin for PHP/React/Python/JavaScript/TypeScript workflows. Includes the plugin (agents, commands, skills, hooks), a skill distillery, and a CLI for cross-tool conversion.
Repository structure
whetstone/
├── .claude-plugin/
│ └── marketplace.json # Marketplace catalog
├── distillery/ # Skill distillery (generate skills from skills.sh)
│ ├── scripts/
│ │ ├── distiller.py # Search, fetch, validate, eval, harvest, test
│ │ └── test_distiller.py # pytest tests for distiller
│ └── generated-skills/ # Generated skill output directory
├── scripts/
│ ├── update-metadata.sh # Update component counts in plugin.json + marketplace.json
│ ├── generate-skill-hooks.sh # Generate hook patterns from SKILL.md frontmatter
│ ├── mirror-to-ai-skills.sh # Mirror plugin skills to ai-skills public repo
│ ├── configure-codex-skill-sources.py # Disable duplicate direct sources in Codex
│ ├── install-codex-plugin.sh # Install/enable plugin, then retire duplicate sources
│ ├── refresh-codex-plugin.sh # Cachebust/reinstall Codex without dirtying release version
│ ├── sync-to-tools.sh # Symlink skills to .agents/.kilocode; retire legacy Codex links
│ └── update-plugin.sh # Update locally installed plugin to latest version
├── CHANGELOG.md # Version history
└── plugins/
└── whetstone/ # The plugin
├── .codex-plugin/
│ └── plugin.json # Codex skills-plugin metadata
├── .claude-plugin/
│ └── plugin.json # Plugin metadata
├── agents/ # Agents (all `ia-<name>.md`, flat layout)
├── shared-references/ # Reference content shared by agents and commands, loaded via Read
├── commands/ # Slash commands (all `ia-<name>.md`); only command files here
│ └── scripts/ # Helper scripts commands run
├── skills/ # Skills (all `ia-<name>/`)
│ └── ia-<skill-name>/
│ ├── SKILL.md # Skill content
│ ├── references/ # Optional supplementary docs
│ └── scripts/ # Optional bundled scripts
├── hooks/ # Record tasks, then add skills to subagent starting context
└── README.md # Plugin documentationWorking agreement
- Do not delete or overwrite user data. Avoid destructive commands.
- Hyphens for all file naming (agents, skills, commands).
- Agents omit
model:unless overriding (e.g.,model: haiku). - Agents reference skills (one-directional); skills stay generic and portable.
- Read before claiming "new": Before presenting sync/improvement findings, read the target's body, not its description or frontmatter, to verify the pattern isn't already covered. A description that disagrees with its body is itself a finding.
- Check the consumer's contract, not a proxy. Before calling a reference, identifier, or absence verified, check it against what reads it: the Agent tool resolves plugin agents as
whetstone:ia-<name>, not theagents/*.mdfilename stem; a link must cover the routed topic, not just resolve; an absence claim needs a case-insensitive grep for two or three spellings (the citation-artifact rule is spelled[OAICITE]). Existing working callsites are the ground truth; a lone divergent form is an error.validate-plugin,test-triggers, and cross-ref validation do not checksubagent_typevalues. - Present changes one at a time for review decisions. Batch presentation only when explicitly asked.
- No off-stack content: Skip or replace code examples, references, and patterns for languages/frameworks the team doesn't use (Ruby/Rails, Java, Swift, etc.). Use PHP, Python, or TypeScript equivalents. Generic SQL or framework-agnostic examples are fine when no specific stack fits.
- Discipline sections duplicate on purpose. The
## Disciplinesections in language skills (ia-php-laravel,ia-python-services,ia-nodejs-backend,ia-react-frontend,ia-rust-systems,ia-cpp-systems) repeat shared rules because each skill ships standalone to users without this file. Do not flag them as cross-skill duplication. - Code-quality and writing principles belong in the language-specific coding skills, not in planning or meta skills. Planning skills govern workflow; coding skills govern how code gets written.
- No personal-machine paths in plugin files. The plugin is published externally (mirrored to ai-skills, shipped to ClawHub, synced to
.agents/.codex/.kilocode). Anything underplugins/whetstone/must be self-contained and runnable by a stranger — no references to~/...or/home/<user>/...paths into personal notes,~/ai/repos/,/home/ilia/, private Linear/Slack/Grafana URLs, or any other path specific to one machine or org. If a pattern's deep reference lives in personal notes, embed enough actionable content inline that the skill works without them; do not leave pointer lines like "see the wiki at ..." in published files. Usegit grep -n '~/ai/\|/home/' -- plugins/before shipping to catch stragglers. Search tracked files only: a plaingrep -rnalso walks gitignored build artifacts (evals/results/,__pycache__/) that never ship, so it reports stragglers that do not exist. The tracked hits that remain are theSPEC.mdlines documenting this rule.
Versioning
Version bumps, CHANGELOG entries, and README count updates happen during /release, not per-change. Editing a skill, agent, or command does not trigger any version ceremony. Make the change, commit it with a descriptive message, move on. Let work accumulate across multiple commits until a release is cut.
One CHANGELOG entry per release keeps what shipped reconstructable; per-change entries fragment it.
When /release runs, it:
- Bumps the version in
plugins/whetstone/.claude-plugin/plugin.json,plugins/whetstone/.codex-plugin/plugin.json, and.claude-plugin/marketplace.json - Appends a CHANGELOG.md entry summarizing the commits since the last release
- Updates README.md component counts and tables
- Runs
bash scripts/update-metadata.shto sync descriptions and counts - Validates JSON, then runs the pre-commit gates in order with these blocking statuses:
update-metadata.sh --check— BLOCKING (metadata/count drift)validate-plugin— BLOCKING on HIGH findings (machine-path leaks, dead cross-refs, phantom agents, orphan references)validate-cross-refs.sh— BLOCKING (broken reference links; also rejects path-style links to a sibling skill, which resolve locally but break in the ai-skills mirror)- native Codex plugin regression (
test-codex-plugin.sh) — BLOCKING - trigger regression tests (
test-triggers) — BLOCKING - Tier-1 prompt-injection corpus scan — BLOCKING on HIGH findings
- Tier-2 prompt-injection attestation verify — BLOCKING; skipped with a WARNING when no previous
v*tag exists - skill-injection hook tests (
test-semantic) — NON-BLOCKING (WARNING only; these are hook-firing tests, not the prompt-injection scan) - skill manifest regeneration (baseline reset to the last-released manifest first)
- Commits, refreshes the native Codex plugin before push, mirrors to ai-skills, publishes to ClawHub, and syncs shared skill directories
Semver rules applied by /release:
- MAJOR (1.0.0 → 2.0.0): breaking changes, major reorganization
- MINOR (1.0.0 → 1.1.0): new agents, commands, or skills since last release
- PATCH (1.0.0 → 1.0.1): bug fixes, doc updates, improvements to existing components
Enforcement:
- Do not touch release versions,
CHANGELOG.md, or README component counts on regular edits. Commit the actual change and stop. - If a session-end summary says "bumped to vX.Y.Z" without the user invoking
/release, that is a regression — back out the bump before handing off. - Exception: if the user explicitly asks for a version bump outside
/release, do it. Otherwise/releaseis the sole authority for version state.
Naming convention
All skills, agents, and commands in the plugin carry an ia- prefix. The prefix:
- Prevents collisions with Claude Code built-ins (
/plan,/review) and with sibling plugins (EveryInc'sce-family). - Groups plugin artifacts visibly in shared tool directories (
~/.codex/skills/,~/.agents/skills/). - Keeps command invocations short and consistent:
/ia-plan,/ia-review,/ia-brainstorm,/ia-work.
Rules:
- Every directory under
plugins/whetstone/skills/starts withia-. - Every agent file under
plugins/whetstone/agents/starts withia-(flat layout, no category subdirectories). - Every command file under
plugins/whetstone/commands/starts withia-. - The
name:frontmatter field matches the directory/file stem exactly. - Trigger regex patterns in
hooks/skill-patterns.shdo NOT change — they match user speech, not skill names. Only the array keys (SKILL_PATTERNS[ia-debugging]) carry the prefix. - Reference files (
*/references/*.md) are NOT prefixed — they're content, not invocable components.
Skill class taxonomy
Every shipped skill declares a class: field in frontmatter. Five values, chosen by the dominant lookup need a user has when they reach for the skill:
| Class | What lives here | Examples |
language | Stack-specific patterns: a language, framework, or service the skill wraps. | ia-php-laravel, ia-react-frontend, ia-postgresql, ia-terraform |
discipline | Engineering practices not tied to one stack: how to do X well in any project. | ia-debugging, ia-code-review, ia-writing-tests, ia-simplifying-code |
workflow | Multi-step processes with phases and outputs. | ia-planning, ia-brainstorming, ia-md-docs, ia-orchestrating-swarms |
meta | About prompts, agents, design itself. The skill's subject is AI-native work. | ia-meta-prompting, ia-agent-native-architecture, ia-frontend-design |
tool | Niche utilities — narrow, scoped to a single capability. | ia-git-worktree, ia-reflect |
Picking a class:
- If the skill content reads like a stack reference (install, config, idioms, migrations), it's
language. - If the content is "how to do X well" without naming a stack, it's
discipline. - If the content is a phased process producing artifacts, it's
workflow. - If the subject of the skill is agents, prompts, or skills themselves, it's
meta. - Default to
toolonly if none of the above fit and the scope is genuinely narrow.
The validator (validate-plugin) requires the field and rejects unknown values. /write-skill asks for the class up front when scaffolding a new skill.
Skill compliance checklist
The master reference for what can/cannot/should/should not be used in skills is https://code.claude.com/docs/en/skills -- consult it when uncertain about frontmatter fields, supported features, or behavioral constraints.
When adding or modifying skills, verify:
YAML Frontmatter (Required)
name:present and matches directory name (lowercase-with-hyphens)description:describes what it does and when to use it (e.g., "Explains code with diagrams. Use when exploring how code works.")description:describes when to invoke the skill (trigger conditions); never how the skill proceeds step-by-step. Restating the body's procedure in the description causes Claude to follow the description and skip the skill content.description:sentence 1 names the distinctive mechanism (what a sibling skill would not produce), not a category label ("code review", "optimization loops"). Route neighbors with "Use<sibling>for<that job>" rather than restating their scope. Quoted-utterance or slash-name catalogs belong only in descriptions of user-invoked skills.- No
disable-model-invocation: trueon a skill that another skill or command invokes through an explicitSkill()call; the flag makes that call fail (cannot be used with Skill tool). Tighten the description's trigger instead. description:stays at or under 80 tokens;validate-pluginflags skills and agents over it as HIGH. Two or three appended trigger phrases are enough to cross it, so re-runpython3 distillery/scripts/distiller.py validate-pluginafter any description edit.
Description-as-shortcut failure mode: a description that summarizes the procedure gets followed instead of the body being read. Observed case: a skill with a two-stage flowchart (spec-compliance review, then quality review) described as "code review between tasks" ran one review, not two. A description of the form "does X, then Y, then Z" is a procedure shortcut; keep process in the body.
Reference Links (Required if references/ exists)
- All files in
references/linked as[filename.md](./references/filename.md) - All files in
assets/linked as[filename](./assets/filename) - All files in
scripts/linked as[filename](./scripts/filename) - No bare backtick references like
`references/file.md`— use proper markdown links
Writing Style
- Imperative/infinitive form (verb-first instructions)
- No second person ("you should") — use objective language ("To accomplish X, do Y")
- When a skill must block on a user question, name the harness tool —
AskUserQuestionin Claude Code (callToolSearchwithselect:AskUserQuestionfirst if its schema isn't loaded),request_user_inputin Codex — and fall back to numbered options in chat only when no blocking tool exists. For a blocking chat fallback, name the pending decision on the first line and place the question in the final block. The plugin ships cross-harness (Codex/.agents/.kilocode), so a bare "ask the user" silently degrades to chat off-Claude - No bare
/ia-xslash commands in skill bodies. Onlyskills/ships to Codex/.agents/.kilocode (.codex-plugin/plugin.jsondeclares"skills"and no commands key), so a slash command printed there resolves to nothing on three of four distribution targets. Reference a sibling component by skill name (ia-planning); where a user is genuinely told to invoke something, scope it — "planning (/ia-planin Claude Code)". Descriptive mentions inside a conditional ("when invoked via/ia-lfg") are fine - No model-specific workarounds. A step that cannot be justified without naming a model, a model version, or one agent's private tool name is an issue to file, not skill content. The plugin ships to four harnesses across model families, so a step written to route around one model's failure is a tax on every other reader. Describe the capability the step needs, not the mechanism one model happens to require
- No literal
$0-$9or$ARGUMENTSin a SKILL.md body. Substitution applies to the skill's markdown content and to bash rules inallowed-toolsfrontmatter; it does not apply toreferences/*.md. A Postgres placeholder or shell positional written in the body is rewritten before the model sees it — put such examples in a reference file, or use?-style placeholders in the body
Bundled scripts
A skill referencing its own bundled files picks one of three tiers:
- Read-time relative path —
[init-plan.sh](./scripts/init-plan.sh). No variable, no shell. Default choice. - Prose pointer — "read
scripts/init-plan.shfrom this skill's directory". Use when the reader resolves the path, not a tool. - Executed shell — a model-filled
SKILL_DIRvariable. Two non-obvious constraints apply:- The assignment line needs a trailing
;. Some hosts flatten the newline into a space, and without the separator$SKILL_DIRexpands before the assignment runs. - Claude Code's permission checker evaluates every subcommand of a compound command, so wrapping a pinned
bash ".../foo.sh"call inif [ -f ... ]; then ...; fidefeats a narrowBash(bash *foo.sh)allow-rule. A model-filled path is dynamic anyway and will not match a static pin.
- The assignment line needs a trailing
Avoid ${CLAUDE_SKILL_DIR}: it is empty outside Claude Code, and every skill here ships cross-harness.
Quality Dimensions (SkillsBench arXiv:2602.12670)
- Output format — skill defines what it produces (report template, file path, code pattern)
- Success criteria — how the agent knows the skill completed correctly
- Constraints — what the skill must NOT do, stop conditions, boundaries
- Procedural content — numbered steps with action verbs, not just declarative rules
- Optimal length — SKILL.md body 2K-8K chars ideal. >15K hurts (-2.9pp). Overflow →
references/, chosen by when content is read, not by size: move cold-path material (handoff steps, theory, reference-implementation guidance) behind a link and keep decision gates and checklists inline, because a gate behind a Read does not fire. Landing slightly over 15K beats moving a gate out.
Quick Validation
# Check for unlinked references in a skill
grep -E '`(references|assets|scripts)/[^`]+`' plugins/whetstone/skills/*/SKILL.md
# Should return nothing if all refs are properly linked
# Check description format - should describe what + when
grep -E '^description:' plugins/whetstone/skills/*/SKILL.mdCommon tasks
Keep component edits separate from release bookkeeping. Defer version changes, metadata/count regeneration, README component tables, mirroring, and publishing to /release.
Adding a new agent
- Create
plugins/whetstone/agents/ia-new-agent.md(flat layout) - Validate the agent's references and exercise it through the installed Claude Code delegation interface.
Adding a new command
- Create
plugins/whetstone/commands/ia-new-command.md. - Validate references and invoke
/ia-new-commandin an installed Claude Code session.
Adding a new skill
- Create
plugins/whetstone/skills/ia-skill-name/SKILL.mdwith the required frontmatter. - Add its trigger pattern to
plugins/whetstone/hooks/skill-patterns.sh. - Add trigger regression fixtures to
distillery/tests/fixtures/triggers/ia-skill-name.jsonl. - Run
python3 distillery/scripts/distiller.py test-triggers --skill ia-skill-name. - Exercise the skill through a matching task in the intended installed harness.
Adding a new hook
- Add hook entry to
plugins/whetstone/hooks/hooks.json - Create hook script in
plugins/whetstone/hooks/ - Test the hook's emitted protocol and intended caller behavior.
Skill distillery
The distillery/ directory generates skills from top-rated skills on skills.sh. Use the skill-distiller project-level skill (.claude/skills/skill-distiller/SKILL.md) for the full workflow.
# Generate a new skill
python3 distillery/scripts/distiller.py search "react"
python3 distillery/scripts/distiller.py fetch --skills '<json>'
# ... analyze, synthesize, validate → distillery/generated-skills/<name>/
# Promote to plugin
cp -r distillery/generated-skills/<name> plugins/whetstone/skills/<name>
# Metadata and distribution run during /release.
# Mirror to ai-skills (read-only public distribution)
bash scripts/mirror-to-ai-skills.shSkillOpt optimizer (offline)
distillery/skillopt/ is a vendored microsoft/SkillOpt (MIT, see its VENDORED.md) plus a whetstone env that optimizes a process SKILL.md by running the target model agentically (Claude Code via claude_code_exec) against curated fixtures, with a hybrid reward: deterministic hard (fixture test red→green) + a per-skill process rubric soft. It is the Tier 3 rung of the skill-optimization ladder (eval-skills → evolve → SkillOpt) — the higher-fidelity, higher-cost path for process skills whose value is agentic, reached when the single-turn DSPy evolve plateaus.
Validated recipe (full procedure in SKILLOPT-RUNBOOK.md): optimize for the weaker model that actually runs the skill (capable models saturate hard; the process gap is in the weak model), and blend soft into the gate via SKILLOPT_SOFT_WEIGHT (keep λ < 1/n_val to preserve the deterministic floor) — a process skill cannot be optimized by the hard-only gate.
Safety: the rollout drives a bypassPermissions agent with its bash sandbox off, so it can reach the host filesystem. Run it from a bare terminal, never nested in a Claude Code session, git-checkpoint first, keep fixtures tracked, and OS-sandbox anything beyond your own curated fixtures.
Offline only: not mirrored, not in the release pipeline; best_skill.md promotion stays manual and gated by test-triggers. See distillery/skillopt/README.md and the runbook.
Session harvesting and eval
The distillery mines Claude Code session logs to build skill evaluation and golden datasets and to score skill effectiveness.
# Harvest per-skill eval datasets from ~/.claude/projects/
# Excludes stale examples (from before skill was last changed) by default
python3 distillery/scripts/distiller.py harvest-sessions [--project <name>] [--skill <name>] [--include-stale]
# Discover new negative signal patterns not yet in _NEGATIVE_SIGNAL_PATTERNS
python3 distillery/scripts/distiller.py discover-signals [--top 30]
# Score a skill via LLM-as-judge. Direct backend (default: claude -p, billed) OR
# in-session sub-agents (no API cost): --emit-tasks (save the manifest) -> dispatch judge sub-agents
# -> --score-from-verdicts @<file> --manifest @<manifest>. Verdicts carry only {index, response};
# signal/session_id/skill_version come from the manifest, never from the judge's self-report.
python3 distillery/scripts/distiller.py dspy-eval <skill> [--max-examples 20] [--backend claude-cli|openrouter] [--emit-tasks | --score-from-verdicts @<file> --manifest @<manifest>]
# Find skills whose trigger regex may be too narrow (sessions that matched a skill's
# keywords but never fired it). Keyword overlap, so rows are candidates for review, not a miss rate.
python3 distillery/scripts/distiller.py analyze-undertriggers [--skill <name>] [--min-examples 5] [--overlap 6] [--include-stale]
# Build golden eval dataset from harvested sessions
python3 distillery/scripts/distiller.py build-golden <skill> [--top 20] [--auto]
# Review candidates.jsonl, set labels to positive/negative/skip, then:
python3 distillery/scripts/distiller.py approve-golden <skill>
# Evolve a skill via DSPy GEPA/MIPROv2 (outputs diff for review, requires: pip install dspy)
python3 distillery/scripts/distiller.py evolve <skill> [--optimizer gepa|mipro|bootstrap] [--iterations 5] [--save]
# Identify skills injected into tasks where they're not needed (misfire detection)
python3 distillery/scripts/distiller.py analyze-misfires [--min-examples 30] [--include-stale]
# Analyze skill injection outcomes by project context (surface anomalies)
python3 distillery/scripts/distiller.py analyze-outcomes [--min-examples 5] [--include-stale]
# Analyze negative-signal sessions to find failure patterns and suggest skill fixes.
# Direct (claude -p, billed) OR sub-agent: --emit-prompt -> dispatch 1 sub-agent -> --format-result --response @<file>
python3 distillery/scripts/distiller.py diagnose-negatives <skill> [--max-examples 10] [--include-stale] [--emit-prompt | --format-result --response @<file>]
# Record or check per-skill resource budget (assistant turns + tool variety per agent type; catches silent skill bloat; exit 1 regression, 3 stale baseline)
python3 distillery/scripts/distiller.py budget <skill> --record # baseline current aggregates
python3 distillery/scripts/distiller.py budget <skill> # check vs baseline (default)
python3 distillery/scripts/distiller.py budget --check-all # scan every skill with a baseline
# Run regex trigger regression tests (release gate)
python3 distillery/scripts/distiller.py test-triggers [--skill <name>]
# Run skill-injection hook tests (deterministic; drives inject-skills.sh directly, no API cost)
python3 distillery/scripts/distiller.py test-semantic [--max-tests 5]
# Generate/update skill change manifest (tracks when skills and patterns last changed)
python3 scripts/generate-manifest.pyThese commands are integrated into the release pipeline (/sync-from-repos > /audit-plugin > /release > /announce):
harvest-sessionsruns in/sync-from-reposPhase 1 (background, parallel with inventory)analyze-outcomesruns in/sync-from-reposPhase 6 (surfaces project-context anomalies before audit);discover-signalsis manual-only and not in the pipelineanalyze-misfires,analyze-outcomes, anddiagnose-negativesrun in/audit-pluginPhase 2 (trigger coverage checks)test-triggersandtest-semanticrun in/audit-pluginPhase 7 and/releasepre-commit gates
All commands can also be run standalone for targeted analysis.
Staleness filtering: harvest-sessions, analyze-misfires, analyze-outcomes, and diagnose-negatives exclude examples that predate the skill/pattern or ran on a retired runtime model. The manifest at distillery/.skill-versions.json tracks content/pattern hashes per skill plus a top-level model_baseline_prefixes list (current: Opus 5.5 main + Sonnet 5.5 / Haiku 5.5 subagents, plus Fable 5 and Mythos 5). Update MODEL_BASELINE_PREFIXES in scripts/generate-manifest.py when the runtime model family changes, or override per-run with SKILL_MODEL_BASELINE=prefix1,prefix2. Use --include-stale to override when you need historical analysis.
Every trigger pattern fix should add a regression test case to distillery/tests/fixtures/triggers/<skill>.jsonl to prevent regressions.
Scripts
| Script | Purpose | When to run |
scripts/update-metadata.sh | Count components, update plugin.json + marketplace.json descriptions; --check fails on metadata/version drift (a /release gate) | During /release |
scripts/check-trigger-overlap.py | Advisory Jaccard report on trigger-regex vocabulary; surfaces skill pairs competing for the same phrases ([same-tier] = expected stack family) | During /audit-plugin, or after adding/editing skill triggers |
scripts/generate-spec.py | Generate starter SPEC.md per skill from SKILL.md + fixture; skips skills that already have one | When adding a new skill, or after class: taxonomy refresh |
scripts/generate-manifest.py | Update distillery/.skill-versions.json with current skill/pattern hashes | Automatically during release |
scripts/mirror-to-ai-skills.sh | Mirror plugin skills to ~/ai/ai-skills (read-only distribution) | During /release, or when explicitly requested |
scripts/generate-skill-hooks.sh | Generate draft hooks/skill-patterns.sh from SKILL.md frontmatter | After adding/removing skills (hand-tune regex after) |
scripts/publish-clawhub.sh | Publish skills to clawhub.ai registry (handles rate limits, skips existing versions) | During release (automatic) or manually |
scripts/sync-to-tools.sh | Symlink skills to shared directories; remove legacy Codex links and configure duplicate-source exclusions | After editing or adding skills |
scripts/install-codex-plugin.sh | Install and verify the native Codex plugin before retiring duplicate direct sources | Initial install and release refresh |
scripts/refresh-codex-plugin.sh | Reinstall local Codex source edits with a temporary, trap-restored cachebuster | During between-release Codex plugin development |
scripts/update-plugin.sh | Update locally installed plugin to latest pushed version | After pushing a new version to GitHub |
scripts/post-thread.py | Post tweet threads to X via Playwright CDP to Edge | After /announce drafts are approved |
Marketplace.json spec
Only include fields from the official Claude Code spec:
- Required:
name,owner,plugins - Optional:
metadata(with description and version),renames,forceRemoveDeletedPlugins - Plugin entries:
name,description,version,author,homepage,tags,source
Do not add custom fields (downloads, stars, rating, categories, etc.).
Keep renames as append-only history from former plugin names to current names or null. Validate changes with claude plugin validate .; see the official rename and removal documentation.
Resources
- Skills Reference -- master reference for skill frontmatter, features, and constraints
- Plugin Documentation
- Plugin Marketplace Documentation
- Plugin Reference
<!-- BEGIN beads-managed -->Beads ledger (br)
This repo is onboarded to the central br ledger. A PATH wrapper routes every
br call from here into a private review ledger stored outside the repository;
this work tree carries no .beads artifacts (do not create any). The full
protocol is documented separately.
Allowed commands (the wrapper denies everything else): create update comments
close reopen list show count stats search where info, doctor health,
doctor migrate-schema plan|apply|undo, sync --import-only|--status,
config get|list. Never pass --db, --no-auto-flush, --no-auto-import,
--no-db, --allow-stale, or --prefix.
JSON envelopes: br list --json → {issues, total}; br show ID --json →
a one-element array with comments under .[0].comments. Pipe br JSON to jq
only as rtk proxy br … | rtk proxy jq … (raw, unfiltered output).
Finding schema (review-cycle records):
- Native status
open/closedonly —in_progressis banned (it silently disappears from--status open). Priority is severity: P0 critical, P1 important, P2 minor. - Exactly one
type:{security|correctness|memory|perf|build|test|style}label and onecycle:<id>label. Open findings carry exactly onestate:{proposed|disputed|fixed|needs-human}; closed findings carry nostate:*and aclose_reasonoffixed|false-positive|wont-fix|duplicate. - Description first line is
file: <path>:<line>, repo-relative. - Attribution:
br create --actor <id>,br comments add --author <id>. - Closing is two steps (
brrefuses a terminal status inupdate): firstbr update IDclearingstate:*and the assignee, thenbr close ID --reason <r>. updaterefuses to clear a non-emptynotes,description,design,acceptance-criteria,prerequisites, oragent-contextbody, or to replace it with content shorter than half its current length. Extendnoteswith--append-notesrather than forcing a shorter rewrite with--force.- Never
--set-labels(it erases other labels); use--add-label/--remove-label.
Human gate — create as state:needs-human and get pre-change approval for: P0,
type:security, type:memory, destructive operations, schema/data migrations, or
public API changes.
<!-- END beads-managed -->Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

