The Keystone reference.
Keystone is the agent charter framework. A charter is the authored standards that constrain a coding agent; keystone is the model layer over host primitives that authors, validates, and projects that charter to every host. This is the complete reference: the concepts, the 13 primitive kinds, signals, and every surface. For an introduction see the home page; for a task-oriented walkthrough see the guide.
v4.0.0 — the charter rebrand. Keystone is the agent charter framework, not a harness. The artifact moved from .harness/ to .charter/ and was renamed throughout; CHARTER.md is the single canonical agent entrypoint. Framework events became extensible signals, and the hook primitive kind was retired — reactions self-subscribe via on:. There are now 13 primitive kinds (was 14). keystone migrate up carries a 3.0 install to 4.0.
What keystone is. keystone is the model layer over host primitives: each kind adds validations, associations, and cross-host projection the bare host file lacks. Canonical source lives at .charter/; on keystone project it is rendered into host-native paths (.claude/rules/, .claude/skills/, .claude/agents/, .claude/commands/, .cursor/rules/, AGENTS.md, …).
The tools are optional at runtime. The charter is markdown on disk. An agent that reads .charter/INDEX.json plus the primitive bodies it points at can operate the charter without keystone installed. The CLI helps you author and maintain; the MCP server gives the agent structured access; the dashboard gives you a local operator view. None are runtime dependencies.
Charter vs. harness
The distinction that names the tool. A harness is the engine that runs the model; a charter is the authored standards that constrain it. Keystone manages the charter.
The authored standards
The rules, reasoning, checks, workflows, and postures an author writes to constrain a coding agent. Lives at .charter/. Your CLAUDE.md, a pre-commit hook you authored, a review SOP — all charter.
The engine that runs it
The machinery that executes the model — Claude Code, the orchestrator, the runner, the process that fires a hook. Mechanism, not policy.
Authorship, not executability. A pre-commit hook executes and is still charter, because you authored it to state a standard. The runner that fires that hook is the harness.
You author the charter; the harness you run consumes and applies it.
Say it that sharply or "charter" collapses back into "harness." The orchestrator resolves cleanly: it runs, so it's harness (machinery); the process it enforces is authored, so that's charter. Mechanism vs. policy — the same split that puts Claude Code in the harness but your CLAUDE.md in the charter.
The resolution contract: rules → corpus → ask
The runtime resolution flow — encoded in the MCP server's instructions block and in guides/process/runtime-resolution.md. When a scenario arises, the agent works the charter in stages, escalating only when the previous stage doesn't carry enough information.
- Rules.
Find applicable guides via
INDEX.json, filtered by touched-files globs and phase. Project wins by default; policies refine via nesting inkeystone.json;strictitems lock absolutely. - Corpus.
When a guide's body isn't enough to act, follow its
corpus:field to the linked reasoning — the why. Corpus is opt-in; it is never auto-loaded. - Contradictions → ask.
Any contradiction between rules and corpus triggers the agent to ask the user to resolve it. The server returns data; the agent reasons about conflicts.
External-system access is a tool, not a resolution stage. Reaching an outside system is done through a kind: tool primitive (transport cli | http | mcp | plugin) — it is not one of the three resolution stages.
The three-stage resolution contract
guides via INDEX.json] R -->|body enough?| DONE[Act] R -->|body too terse| C[2 · Corpus
follow corpus:] C -->|no conflict| DONE C -->|rules ⚔ corpus| A[3 · Ask
user resolves] A --> DONE
Projection
Rendering the charter into a host agent's native paths via keystone project.
Canonical source is .charter/; projected files are generated — do not hand-edit them. Projection lowers each keystone primitive to the host-native surface: .claude/rules/, .claude/skills/, .claude/agents/, .claude/commands/, .cursor/rules/, AGENTS.md, and the like. One canonical primitive can map to many host mechanisms — that one-to-many mapping is the framework's value.
Thin pointers. In 4.0, CHARTER.md is the single canonical agent entrypoint (full orientation). Every host file — CLAUDE.md, AGENTS.md, CONVENTIONS.md, Cursor/Continue rules — is a thin pointer to it: Claude Code via a native @CHARTER.md import, others via an imperative "read CHARTER.md" plus a per-host capability delta (subagents / slash commands / skills / hooks).
One canonical source, many host projections
The cascade
How a primitive resolves when the project and vendored policies both define one at the same canonical path. The resolver is pure: exactly one file loads per (kind, id).
- Project wins by default.
The project's
.charter/<kind>/<id>always wins. The repo's authors have final say over their own charter. - Nested policies refine outer ones.
Among vendored policies, a policy nested deeper in
keystone.jsonrefines the outer policy it is nested in. - Strict locks absolutely.
A
strict.<kind>: [<id>]declaration on any tree node makes that item absolute — nothing else can override it, not the project, not any other policy.keystone verifyreports a violation if any layer attempts to shadow a strict item.
The framework never composes overlapping primitives. Exactly one file wins; its frontmatter is what's read. For guides specifically: an override does not inherit the base's globs: — if a project guide overrides a policy guide and only the policy had globs, the override loads under its own (possibly absent) globs.
Project always wins by default; deeper-nested policies refine outer; strict locks
Provenance
Every primitive carries a provenance the walker derives from its path — where it came from, and who ratified it.
Path-derived provenance. project for the repo's own charter; policy/<name> for a vendored policy layer. keystone charter show --effective renders the resolved cascade and annotates what each winner overrides.
keystone verify.strict: declarations. The ratification boundary between org/team policy and a project.Amendment records provide human-readable provenance. type: amendment documents (or ADRs for architectural changes) name who proposed and ratified a change and why — alongside the path-derived provenance for tools. Policies are the ratification boundary: pinned by version and content hash, drift-reset by keystone verify; strict: declarations lock items absolutely.
The 13 primitive kinds
.charter/ holds 13 primitive kinds. Every primitive declares kind, id, and description in frontmatter, plus per-kind fields (globs, phase, triggers, tier, mode, on, run, agent, returns, tools, corpus, includes, …). The walker emits one .charter/INDEX.json; agents read the index first and open bodies only when their activation conditions match.
The hook kind is retired. In 4.0 there are 13 kinds, not 14. What was a hook is now a sensor (or a tool) that self-subscribes to a signal or host phase via on:. See Signals.
guide
The rules the agent must follow — the what and what not. Reasoning lives in the paired corpus file.
Ambient by default — every guide in the resolved cascade is loaded into the agent's context at session start. Activation has two gates, topic first, then globs:
globs: is an optional frontmatter list that narrows a guide's activation. It can only remove a guide from activation; it never expands it. The invariant:
activates ⇔ (topic default fires) ∧ (globs match, or no globs declared)
Globs reference real code regions. The bootstrap command seeds initial globs from the region map in corpus/state/CODEBASE_STATE.md. Globs that match no files are a learning signal, not a feature. On guides/computational/ entries, globs: is documentation, not enforcement — the actual tool reads its own config; divergence is flagged by the stack-drift sensor.
---
globs: # optional; narrows only
- "src/billing/**"
- "!src/billing/legacy/**"
---
# <Name> — rules
<one-sentence framing of what this guide governs>
## IRON LAW(S)
<non-negotiable rules; omit when nothing qualifies>
## GOLDEN RULE
<strong, explicit standards; omit when nothing qualifies>
## RULES
<regular rules — the default tier; most directives live here>
For reasoning, see [`corpus/<topic>/<name>.md`](corpus/<topic>/<name>.md).
Key frontmatter: globs: (optional, narrows), kind: on computational guides. Unrecognized keys are ignored; bare-content guides are valid. Forward-link to corpus is required when a paired corpus file exists (charter-root-relative path). Length: short — a guide is rules; long-form belongs in corpus.
Project wins by default; deeper-nested policies refine; strict.guides: [<name>] locks. Exactly one file loads per <topic>/<name> — the winner's globs: is the only one consulted. Projects to: an inferential guide → a .claude/rules/ shim; a computational guide → a host hook (LSP-style check).
sensor
A check that reacts to a signal or host phase via on:. Sensors gate. In 4.0 the sensor kind folds in the retired hook kind — reactions self-subscribe.
A check → verdict
A run: shell invocation whose exit / HTTP status is the verdict. Exit 0 = pass; non-zero = fail (capture stderr).
An agent review → schema
Dispatched as an agent review that emits a structured returns: verdict. Keystone cannot invoke an LLM itself, so it emits a dispatch manifest the host spawns.
A sensor subscribes to a signal or host phase via on: (host phases like PreToolUse, Stop are a closed set bridged into the host; any other on: value is a signal). Fire manually with keystone signal fire <name>. See Signals.
---
kind: <computational | drift | coverage | ...>
# plus on: to self-subscribe to a signal / host phase
---
# Sensor: <name>
<one-sentence description>
## Command
<the shell invocation; may be templated with project variables>
## Interpretation
<how to parse output; what constitutes pass / fail / warning>
## Remediation
<what the agent should do on failure>
Key frontmatter: kind: (required — open set, documented values in docs/conventions.md), on: (signal or host phase), plus run: (computational) or agent: + returns: (inferential). H1 title # Sensor: <name>; Command / Interpretation / Remediation required.
Project wins by default; deeper-nested policies refine; strict.sensors: [<id>] locks. Projects to: a host bridge entry per host phase (the host calls keystone signal fire <phase> and keystone dispatches + owns blocking), or an agent dispatch manifest the host spawns for inferential sensors.
agent
A role spawned as a subagent. The body is the subagent's system prompt.
Spawned via the host's Task tool by id. An inferential sensor dispatches an agent as its reviewer; an agent can also be invoked directly as a role.
kind: agent, id, description; optional tools: (the tool allowlist the subagent runs with) and returns: (a structured verdict schema when the agent is used as a review). The body is the system prompt.
Project wins by default; deeper-nested policies refine; strict.agents: [<id>] locks. Projects to: the host's native agents directory (e.g. .claude/agents/<id>.md).
command
A unit of work / lifecycle step. The atomic building block a playbook composes.
The user's intent matches the command's description + phase. Projected as a host slash command (e.g. /keystone-<id>).
kind: command, id, description; optional phase: to bind the command to a lifecycle phase. The body is the work the agent performs when the command runs.
Project wins by default; deeper-nested policies refine; strict.commands: [<id>] locks. Exactly one file loads per id. Projects to: the host's native commands directory (e.g. .claude/commands/<id>.md → /keystone-<id>).
skill
A single composed capability, surfaced as a host-native skill. skill is the agent-native primitive; framework authors usually reach for playbook (which wraps it).
Host-native auto-activation. The host substring-matches the user's input against the skill's triggers: and loads its body — no slash command required.
---
kind: skill
id: <stable id, conventionally `<namespace>:<name>`>
description: 'One sentence — what this skill does.'
triggers:
- <phrase the user might type>
- <slash command form>
---
# <Skill Name>
<body — what the agent should do when this skill activates>
Key frontmatter: kind: skill, id (conventionally namespaced, e.g. keystone:audit), triggers: (required, non-empty list). Projects to: the host's native skills directory (e.g. .claude/skills/<slug>/SKILL.md). Cascade: strict.skills: [<id>] locks.
playbook
A composed sequence of commands with human gates:. References commands by name.
# Playbook: <name>
<one-sentence description>
## Sequence
1. **<command-name>** — <why this step>
2. **<command-name>** — <why this step>
## Halt conditions
<when the playbook stops early — e.g., a sensor in a step returns fail>
Shape: H1 title # Playbook: <name> (required); Sequence (each step names an existing command); Halt conditions (what stops the playbook between steps). No frontmatter required. If a referenced command is missing from the cascade, keystone verify reports a broken reference at install time.
Project wins by default; deeper-nested policies refine; strict.playbooks: [<name>] locks. Exactly one file per <name>. Projects to: the host via a skill wrapper.
corpus
The reasoning / why, loaded on demand. Corpus carries the depth a guide cannot.
A guide's corpus: field (or a prose forward-link) points at it. Corpus is opt-in — never auto-loaded. It is the second stage of the resolution contract.
# <Name> — reasoning
<long-form explanation of why the rule exists>
## Anti-patterns
<failure modes the rule guards against>
## References
<links to source material — papers, books, posts>
Back to the rules: [`guides/<topic>/<name>.md`](../../guides/<topic>/<name>.md).
Shape: H1 # <Name> — reasoning; no frontmatter required; back-link to the guide is required when a paired guide file exists; long-form welcomed. Cascade: strict.corpus: [<name>] locks; exactly one file per <topic>/<name>. Not projected — corpus is agent-read on demand.
document
A governed output — plan / review / adr / retro / feature / amendment. Instances are tracked, not indexed.
Document instances live under .charter/work/ and are driven by the keystone document subcommand, which lists work documents and promotes them through gate-validated transitions. The walker skips work/, so instances are not indexed as primitives. Amendment records use type: amendment (see Governance).
kind: document, id, description, plus a type: (plan / review / adr / retro / feature / amendment) and the gate schema the transitions validate against. Projects to: instances written under .charter/work/.
concern
A composition mixin — shared frontmatter or body fragments other primitives include.
Pulled in by another primitive's includes:. A concern is not activated on its own; it composes into its includers at project time.
kind: concern, id, description. The body is the reusable fragment. Projects to: inlined into each including primitive's projection (not a standalone host file).
posture
Tool/permission posture — the allow / ask / deny stance projected into the host's settings.
Ambient — a posture is part of the resolved cascade and shapes the host's permission surface at project time.
kind: posture, id, description, plus the allow / ask / deny permission declarations. Projects to: the host's settings.json (e.g. .claude/settings.json).
tool
An author-defined external callable. On-demand by default, or a signal-fired side-effect when it declares on:. In 4.0 the tool kind gained an http transport and an on: field.
On-demand by default — reached as the external-system access path of the resolution contract (a tool, not a resolution stage). When it declares on:, it becomes a signal-fired side-effect — self-subscribing to a signal or host phase exactly like a sensor.
kind: tool, id, description, transport: (cli | http | mcp | plugin), and optional on: (signal / host phase for a side-effect). Projects to: mcp tools auto-register on keystone's MCP server; others project into host config as appropriate.
eval
The eval harness — declared checks the charter runs against itself, with baseline regression diffs.
Run with keystone eval run (static + sensor levels). --baseline <git-ref> materializes the ref in a git worktree, runs both sides, and diffs results into a regression report.
kind: eval, id, description, plus the eval definition (expected.json and an optional fixture/ alongside the EVAL.md). Not projected — evals run through the CLI / MCP eval surface.
pattern
A reusable documentation pattern (Diátaxis), in prose — applied when writing docs.
Applied by the author when writing documentation — a pattern is guidance for shaping prose (tutorial / how-to / reference / explanation), not a runtime-activated primitive.
kind: pattern, id, description. The body is the documentation pattern itself. Not projected — patterns are author-facing.
The signal model
A signal is a keystone framework event the host can't see — the extensible, higher-level counterpart to a host hook phase. It is the 4.0 anchor that let the hook primitive kind retire.
Host phases are a closed set; signals are open. Host phases (PreToolUse, Stop, …) are bridged into the host and cannot be extended. Any other on: value is a signal — so projects define their own. Declare custom signals in keystone.json under signals:, and fire them with keystone signal fire <name> (keystone signal list to discover). The hook fire verb is kept as a back-compat alias.
on:A primitive subscribes to a signal via on:, the same way a skill declares triggers:. When the signal fires, the subscriber reacts. Three kinds react:
check → verdict
Runs a check; its exit / HTTP status is the verdict. Gates.
side-effect
Fires an external callable (transport cli | http | mcp | plugin). On-demand, or a side-effect when it declares on:.
review → returns
Runs an inferential review that emits a structured returns: verdict.
Signal fires → subscribers self-selected by their on: value react
PreToolUse · Stop · …"] --> BR[Host bridge] CS["Custom signal (open)
keystone.json signals:"] -->|keystone signal fire| DISP{Dispatch by on:} BR --> DISP DISP --> SE["sensor · check → verdict"] DISP --> TL["tool · side-effect"] DISP --> AG["agent · review → returns"]
Built-in signals are the framework lifecycle events (the counterparts to the earlier framework hook events — around commands, playbooks, gates, and verification). Custom signals are project-defined: add a name under signals: in keystone.json, then fire it.
$ keystone signal list # discover available signals $ keystone signal fire pre-verify # fire a built-in or custom signal $ keystone hook fire pre-verify # back-compat alias for signal fire
CLI
One Go binary. Every command has --help; keystone completion bash|zsh|fish for shell autocomplete.
--agent..charter/, emit INDEX.json..claude/ / .cursor/ host projections from canonical sources.--effective resolves the post-cascade winning set.hook fire is a back-compat alias..charter/ for safe experiments.--baseline <ref> for regression diffs.MCP server
Same binary, separate verb. keystone mcp install --agent claude-code writes .mcp.json; the host launches the server on session start. For opencode it writes the server into opencode.json's mcp key as a local (stdio) server.
Inspect the charter
keystone_list_primitives, keystone_get_primitive, keystone_get_corpus.
Find
keystone_search.
Run & report
keystone_eval_list, keystone_eval_run, keystone_eval_report, keystone_eval_baseline.
Author
keystone_new_<kind> for every kind, plus keystone_charter_bootstrap, keystone_target_add, keystone_index_refresh, keystone_project_refresh.
Signals & charter
keystone_signal_list, keystone_charter_coverage, keystone_charter_conformance, keystone_explain.
keystone://index # full INDEX.json
keystone://primitive/{kind}/{id} # one body
keystone://charter/status # install audit
skill://list · skill://{name}/SKILL.md # auto-discovery
keystone_bootstrap, keystone_task, keystone_audit, keystone_learn.
Dashboard
keystone web serve --port 4773 (the default — KEYS on a phone keypad). Localhost-only; same binary; reuses the same data model as the CLI and MCP server. SSE push at /events swaps fragments when files in .charter/ change; the REST API under /api/ is read-only.
home
Counts by kind.
metrics
Primitive counts, lint stats, freshness, index health.
insights
Suggested actions to improve charter performance.
primitives
Table with kind + glob filter; detail page with cross-references.
coverage
Uncharted territory — files no guide governs. (4.0)
signals
Declared signals and their subscribers. (4.0)
policies
List + add / remove.
investigator
Primitives grouped by cascade layer, with search.
verify
One-click keystone verify + result pane.
prune
Lint findings + heuristics (orphan corpus, empty bodies, duplicate descriptions) with per-row prune.
inbox
Walk learning candidates, accept / reject.
flywheels
Copy-paste invocations for learn / synthesize / audit.
evals
Declared evals + run button + report fragment.
search
HTMX-live full-text across the charter.
graph
Mermaid-rendered dependency graph.
Governance
Project + charter-amendment governance. A charter is authored standards; changing it is an amendment, and amendments follow a defined pipeline rather than ad-hoc edits.
- Propose.
A surprise, incident, or review finding is captured as a learning candidate under
.charter/learning/inbox/(keystone learn). - Synthesize.
Accepted candidates are promoted into the right layer — a guide, corpus entry, sensor, or tool (
keystone synthesize). - Ratify.
A maintainer accepts the promotion in review. The change lands in
.charter/and is indexed. - Record.
Material amendments are recorded as a governed document with
type: amendment(or an ADR for architectural ones), so the charter's evolution is human-readable, not just reconstructable from git.
This is the same flywheel the tool ships (learn → synthesize); governance names it as the charter's amendment process. ADR 0009 records the 4.0 amendments.
Every primitive carries a provenance the walker derives from its path: project for the repo's own charter, policy/<name> for a vendored policy layer. keystone charter show --effective renders the resolved cascade and annotates what each winner overrides.
- Project layer wins by default — the repo's authors have final say over their own charter.
- Policies are vendored, pinned by version and content hash, and drift-reset by
keystone verify. A policy'sstrict:declarations lock items absolutely — the ratification boundary between an org/team policy and a project. - Amendment records (
type: amendmentdocuments / ADRs) name who proposed and ratified a change and why.
Maintainers merge changes, cut releases, and ratify charter amendments. Contributors — anyone who opens an issue or PR. Users — feedback is a first-class input to amendments. Decision-making runs on lazy consensus (silence is assent), maintainer approval + a green Code Health gate to merge, and maintainer escalation on unresolved disagreement (recorded as an ADR). Breaking changes to the charter contract (on-disk layout or frontmatter schema) ship in a major release with a migration and an ADR.
Migration: 3.0 → 4.0
4.0 is the charter rebrand. Run keystone migrate up once — it carries a 3.0 install to 4.0. Idempotent; safe to re-run. Back up first via keystone snapshot save --label pre-4.0.
.harness/ → .charter/ and HARNESS.md → CHARTER.md. Rewrites keystone.json references.hooks/ into sensors/: kind: hook → sensor, event: → on: (frontmatter only). The hook primitive kind is retired.context.json.event: still parses as an alias for on:; keystone hook fire is kept as an alias for keystone signal fire.$ keystone snapshot save --label pre-4.0 # back up .charter/ (.harness/) first $ keystone migrate up # carry the install to 4.0 — idempotent $ go install ./cmd/keystone # refresh the binary the host hooks call