What a voice pack ships
voice.json declares constraints in machine form (bannedPhrases, imagery rules, version). voice.md is written guidance for the agent — sentence shapes, register, how to handle a CTA.
There is deliberately no cross-validation between the two. The prose is interpretive; the JSON is literal. That split is the point.
A voice pack ships no CSS. A style pack ships a canonical
style.css that gets inlined verbatim into every page. A voice pack is rules and prose only, because applying voice depends on the specific copy being written. The brand’s visual atoms live in the style pack; its verbal atoms live here.The core writing guide sits underneath
Every voice pack is an overlay on a universal prose foundation atwriting/core.md.
The core guide holds the rules that are true for every brand — directness, specificity, no invented numbers, no marketing filler. The voice pack adds what makes this brand distinct: its audience, cadence, vocabulary, and CTA register.
Resolution is two-level and site-local first:
| Location | Wins when |
|---|---|
<site>/writing/core.md | present — copied into every new workspace |
the bundled writing/core.md | no site-local file — used for new scaffolds and ephemeral work |
run inlines the core guide into each emitted scaffold ahead of the voice block, serve and section re-authoring prepend it before voice.md, and verify --fragment and align return it as a judgment input so the reviewing agent grades against the same base the author wrote from.
The bundled voices
Two voice packs ship in the binary:editorial
Considered, specific, unhurried. Full sentences, concrete nouns, no exclamation. The default pairing for most style packs.
brutalist
Blunt and declarative. Short sentences, plain words, no hedging. Pairs with the harder-edged visual packs.
Two enforcement modes
The split betweenvoice.json and voice.md produces two genuinely different kinds of enforcement, and it is worth understanding which is which.
Literal — banned phrases
Literal — banned phrases
bannedPhrases in voice.json is a deterministic string check. If a banned phrase appears in emitted copy, sitekit verify fails the page. No model judgment, no ambiguity, no negotiation. This is how you make “we never say unlock the power of” a structural property of the site rather than a hope.Banned phrases also come from content/messaging.yaml, so a brand can add its own without forking the pack.Interpretive — the prose guide
Interpretive — the prose guide
voice.md cannot be reduced to a string scan, and sitekit does not pretend otherwise. Register, cadence, and CTA discipline are applied by the agent at authoring time and judged by an agent at review time via verify --fragment or align.This is a prompt-level contract, not a linter. It is enforced by being placed in front of the model every single time copy is written — never by hoping the model remembers.Capture a voice from a site you already have
If the brand already exists in writing somewhere, infer the pack instead of authoring it:capturing-a-voice-pack skill into your harness. Your agent then reads the source copy and extracts the register, the recurring sentence shapes, the vocabulary, and — importantly — the phrases this brand demonstrably never uses, which become bannedPhrases.
You can capture from a local copy file instead of a URL when the writing lives in a document rather than on a site.
Author one from scratch
authoring-a-voice-pack skill, which drives a clarify-intent → draft → preview → iterate → verify loop with your agent.
Working with voices
inspect is the one to reach for when a voice isn’t resolving the way you expect — it prints the full three-tier chain (site-local → workshop → bundled) and shows which tier won.
Where voices live
Same three tiers as every other pack:| Tier | Path | Scope |
|---|---|---|
| Site-local | <site>/voices/<name>/ | this site only, committed with it |
| Workshop | ~/.sitekit/voices/<name>/ | every site on your machine, private |
| Bundled | next to the binary | ships with sitekit |
E_WORKSHOP_NAME_COLLISION. Fork a bundled pack under a scoped name (@me/editorial) instead; scoped names are exempt by design.
What’s next
Capture a brand
Rip a voice or a full visual identity from a site, screenshot, or screen recording.
Style packs
The visual half of the brand.