write
write checks a draft for AI writing tells and quotes each line that has one, with the pattern it breaks. New drafts follow your project's style guide.
canon adds one spec-driven workflow to Claude Code. You write the spec; Claude builds it behind a draft pull request and checks it against your project's rules. The same pull request updates docs/canon/, the record of how the project works. Hooks refuse edits, pushes, and merges that break your git rules.
/plugin marketplace add arhaty/claude-plugins/plugin install canon@arhaty/canon:setupRun each command in Claude Code, in order. If Claude Code asks you to, run /reload-plugins before setting up.
canon keeps two kinds of document. A spec in docs/specs/ argues for one change while it's in flight and moves to an archive when it ships. docs/canon/ is the record of how the project works today, written from the code and changed in the same pull request as the code it describes.
A change ships through review, a merge into your integration branch, and a release pull request that you merge in GitHub.
/canon:define <idea>Cuts a branch, researches, and writes docs/specs/NNN-slug.md. Asks questions until none are open.
/canon:approveChecks the spec on the current branch, marks it approved, commits, and pushes it.
/canon:build NNNBuilds the approved spec behind a draft pull request into the integration branch.
/canon:reviewChecks the branch against the canon, the rule files, and the spec. Read-only.
/canon:canonWrites what the branch settled into docs/canon/, or says in one line that nothing did.
/canon:stagingArchives the spec, waits for CI, and merges the branch into the integration branch.
/canon:productionOpens the release pull request with a manifest of what ships, then stops. The owner merges it.
The hooks run only in a project set up with canon. Each refusal says why and names its bypass.
| Hook | Refuses | Bypass |
|---|---|---|
protect-branch | Any change while the integration or production branch is checked out | ALLOW_PROTECTED_BRANCH_EDIT=1 |
protect-push | A push to either protected branch, and any force push | ALLOW_PROTECTED_PUSH=1, ALLOW_FORCE_PUSH=1 |
protect-merge | Any merge into the production branch | None |
require-canon | A pull request into the integration branch that touches a governed path and no file in docs/canon/ | ALLOW_UNDECIDED_MERGE=1 |
| File | What it is |
|---|---|
.claude/canon.json | Your setup answers. Every hook and skill reads it. |
docs/canon/ | The canon index and the template each canon file follows. |
docs/specs/ | The spec lifecycle, the template, and the archive for shipped specs. |
CLAUDE.md | A workflow section between canon markers. The rest of the file is untouched. |
.claude/canon-domains.json | Maps repository paths to the canon file that governs them. |
.claude/rules/principles.md | Starter engineering principles. |
Setup reads the repository first and offers what it finds as defaults. It lists every file it would change and writes nothing until you approve each one by name. It doesn't commit.
claude plugin marketplace update arhatyclaude plugin update canon@arhatyclaude plugin uninstall canon@arhatyRun these in a terminal, then run /reload-plugins in any open Claude Code session or restart it. Uninstalling stops the skills and hooks. docs/canon/ and docs/specs/ stay, and they read fine without the plugin.
A way of working where a written spec, agreed before the code, says what a change does and how to check it. The AI coding agent builds to the spec, and the spec is what reviewers check the change against.
Spec Kit takes a feature through constitution, specify, plan, tasks, and implement. canon follows each change past the code, through review, staging, and a release pull request. It also keeps docs/canon/ current and enforces the git rules with hooks.
No. Small fixes and tweaks go straight to a branch. Feature work starts with /canon:define.
No. protect-merge refuses every merge into the production branch and has no bypass. The owner merges the release pull request in GitHub.
Yes, optionally. With a tracker set in .claude/canon.json, each command reads the issue's status and moves it, and Linear's GitHub integration moves it on the staging and production merges.
write checks a draft for AI writing tells and quotes each line that has one, with the pattern it breaks. New drafts follow your project's style guide.