verify like anything else.
The copy layer
Underneath all four surfaces is one idea: every word on the site has an address. A page’s copy is a set of leaf fields —hero.headline, pricing.tiers.0.label, chrome.footer.copyright — and each one is stamped into the rendered HTML as a data-sk-copy="<page>:<field-path>" anchor. That anchor is a durable locator. No selector guessing, no fuzzy text matching.
Because the locator is exact, the commit can be exact too. Replacing a plain-text field is an inner-text swap with a field-grained containment proof — if an edit would reach beyond its own field, sitekit refuses it with E_EDIT_OVERREACH rather than writing something it can’t prove is contained.
Plain fields apply with no LLM. Markup fields are deferred to you. A field whose value is plain text is swapped deterministically. A field containing markup can’t be safely swapped by string replacement, so it’s reported as deferred and re-authored by your agent through the voice pack. Every surface below reports the same three outcomes: applied, deferred, failed.
sitekit run --copy-editing <tier> takes off, essential (Lite), or comprehensive (Full), defaulting to essential.
1. The copy dashboard
The newest surface, and the one to reach for most of the time. A local writing environment over the copy layer:127.0.0.1 only, and gates every request on a loopback host and origin — because unlike the read-only dashboards this pattern came from, this one writes.
Navigate to any page, edit its words, then run Import and Verify from the same screen. Deploy deliberately stays in your terminal.
--no-export opts out.
Embedding it
The same UI ships as a mountable component, so a platform can host it rather than the CLI:CopyDashboardClient adapter and the element renders whatever that adapter can answer. Capabilities are gated by probe (typeof client[m] === 'function', never invoked), so a read-only copy viewer falls out of the contract rather than needing a flag. A prebuilt IIFE build is available for a plain script tag.
2. The front-end editor
Point at the live site, click the words, type the new ones. The browser extension captures the click on any[data-sk-copy] element, live-updates the text on the page, and queues the edit. When you hit Change, it POSTs the queue to a receiver running on your machine:
GET /health, POST /apply, and POST /preview, binds loopback only, and applies edits through exactly the same deterministic core as everything else. “Point, type, approve, done.”
The extension itself is a separate connector — deliberately split out so it can later re-point from the localhost bridge to a hosted platform without the CLI changing at all.
3. The Markdown round-trip
The surface for a copywriter who doesn’t want a terminal or a browser extension — just a document.export writes one readable Markdown file per page plus a brand file. Someone edits prose under clear ## field-path headings. import swaps it back — deterministically for plain fields, deferring markup fields to your agent.
To see exactly where things stand across all three representations:
4. Single edits from the command line
When you know the address and the new text:Shared chrome — edit once, apply everywhere
Nav and footer copy lives on every page. The reservedbrand: address fans one edit out across every carrier page and updates the chrome subtree in content/messaging.yaml once:
brand is a reserved page slug — a real page can’t be named it (E_RESERVED_SLUG).
Inspecting the store
Which surface should I use?
| Situation | Use |
|---|---|
| You’re editing copy yourself, iteratively | sitekit dashboard |
| You want to click the real page and type | the front-end editor + edit-bridge |
| A copywriter needs to work in a document | content export → content import |
| You know the exact field and text | content set |
| A script or agent is applying many edits | content apply |
| The wording change is a brand change | not this layer — see Evolve |
What’s next
The four loops
Build, maintain, experiment, and evolve.
Voice packs
The rules every edit is still held to.