moo-authoring · git:20260803.c25becd · 2026-08-03 · sha256 4b170ee621ef4cb3
moo-authoring git:20260803.c25becdA
Immutable. This exact content is served forever at /api/v1/blob/4b170ee621ef4cb3.
--- name: moo-authoring description: Use when adding or changing a skill, fragment, hook, or runtime file in this repo — including deciding which unit a new capability should be. --- Doctrine for authoring moo's own surfaces. ## Frontmatter A skill's frontmatter carries `name` and `description`; read any shipped `SKILL.md` for the current key set. The description is one line, and Claude Code caps it at 1024 characters. Version lives in `plugin.json` only (DRY). The official Claude Code spec does not allow `version` in SKILL.md frontmatter. ## Sizing - Size a skill by a deletion pass, never a numeric cap — the same bar `hope/_fragments/card.md` sets for cards. - Put branch-specific content in files the skill opens when the branch is taken, and name them where they are needed. - Decision tables > prose explanations. ## Token Efficiency - Challenge every sentence: "Does Claude need this?" - Bullets for enumerable items; a paragraph when the point is one connected argument. - No vague terminology; pick one term per concept. ## Skill Design Phrase design decisions as "X over Y: reason". **Unit choice** — behavior inlines at build, data references at runtime; a skill's firing is probabilistic, so behavior that must run every time is a hook: | The new thing is... | Unit | |---|---| | A contract that must read identically in ≥2 skills | Fragment (`<plugin>/_fragments/<name>.md`) | | Data selected per use (catalog, profile, corpus) | Runtime file | | A trigger + procedure that stands alone | Skill | | A trigger only the human perceives | Skill with `disable-model-invocation: true` | | Behavior that must run every time, deterministically | Hook | | An unproven idea | hunch skill + `HYPOTHESIS.md`; graduates or dies | **Composition — artifacts and priming over imports:** - Skills compose through emitted artifacts (the card) and natural-language triggers, never cross-references. - New pipeline stage when the cognitive mode changes (clarify WHAT ≠ decide HOW ≠ judge unsupervised work; find ≠ fix). One skill = one mode + one gate. - Chain mechanics: each stage ends in a gate the user locks; the card carries only what the next stage can't re-derive; the shared contract is a fragment inlined into every stage. - Two skills over one when triggers differ; a shared explanation the pair needs lives in CHANGELOG, not in either skill. ## Fragments A fragment is `<plugin>/_fragments/<name>.md`, and a skill of that plugin inlines it by name alone: ``` <!-- f card --> …generated bytes — edit the fragment, never this block… <!-- /f --> ``` - Scope is the plugin: a skill can name only its own plugin's fragments. `bun run sync` discovers both sides, so a new fragment or a new include site needs no list edited anywhere. - Never hand-edit between the markers, and never resolve a drift by editing a consumer — the fragment is the source, the block is output. - An unknown name leaves the block stale rather than throwing, so `scripts/sync.js` reads markdown-magic's `errors` array and exits non-zero. Any check that swallows that exit code re-opens the hole. ## Hook Design Hooks run beside the thread, never in front of it — they never gate. Mode = two questions: does the foreground need the result, and now? | Mode | When | |---|---| | Sync inject | Few lines of framing, computed instantly | | `async` — fire-and-forget | Side effect only; surfaces as a file change, never re-engages the thread | | `asyncRewake` — fire-and-maybe-wake | Off-thread check; exit 2 wakes Claude on a finding, exit 0 stays silent | A hook that spawns headless `claude -p` copies its flag set from the two shipped hooks, where each flag is commented at the point of use (`hope/hooks/judge.sh`, `hope/hooks/memory-write.sh`), and keeps its verdict logic in one file shared with its eval harness.