Skip to main content

Canon

CI PyPI Python Version License: MIT

Canon remembers the decisions your repo already made — and makes Claude Code and Cursor follow them automatically.

Governed project decision memory for AI coding agents.

Canon is a local-first CLI that sits between coding agents (Claude Code and Cursor first) and a project's institutional knowledge. It stops agents and new teammates from re-adopting rejected approaches, inventing conventions, or re-asking questions that were already settled.

It is not a chatbot, not another coding agent, not generic RAG, and not a website-first knowledge base. It is the living, agent-native layer for project decisions. It complements CLAUDE.md, AGENTS.md, and ADRs — it does not replace them.

start coding agent
        ↓
Canon automatically loads relevant active decisions
        ↓
agent receives them

Why it exists

Static files go stale. Agents forget last month's review thread. Asking people to stop mid-sprint and write an ADR does not survive week three.

Canon mines recent merged PRs (or Git history) and proposes candidate decisions. A human only approves or rejects. Confirmed decisions are injected automatically at the start of the next agent session. Old decisions are superseded, never silently deleted.

How it works

  1. canon init wires local storage and agent integrations.
  2. canon suggest reads recent merged PRs or commits and proposes conservative candidates.
  3. You approve or reject. That interaction should take seconds, not a writing session.
  4. On the next Claude Code session, a SessionStart hook injects relevant active decisions.
  5. Cursor reads an always-apply project rule that points at the generated snapshot.

Installation

Requires Python 3.11 or newer and Git.

pip install canon-memory

Isolated CLI install (recommended):

pipx install canon-memory
# or
uv tool install canon-memory

The product and CLI are Canon. The PyPI name is canon-memory because canon is taken by an unrelated package.

canon --help
canon --version

If canon is not recognized (common on Windows user installs):

python -m canon --version

Add your Python Scripts folder to PATH, or keep using python -m canon.

Quickstart

cd my-project
canon init
canon suggest
canon approve 1
canon inject-preview

Then start Claude Code, Grok Build, Codex, or a new Cursor Agent chat in the same repository. The agent should see the confirmed decision without you running canon query.

ChatGPT web still cannot auto-inject. Attach .canon/CANON.md.

Claude Code integration

canon init installs an official SessionStart command hook in .claude/settings.json (exec form, no shell):

{
  "type": "command",
  "command": "canon",
  "args": ["inject", "--for-hook"],
  "timeout": 15
}

Claude Code injects the hook's additionalContext at session start, resume, clear, compact, and fork. Output stays under the 10,000 character hook cap.

canon init also writes a small managed rule at .claude/rules/canon.md. It does not rewrite your CLAUDE.md.

Inspect: canon doctor
Disable: canon uninstall
Troubleshoot: confirm canon is on PATH inside the Claude Code environment.

Cursor integration

Cursor has no session-start hook. Canon uses the officially supported project rules mechanism:

  • .cursor/rules/canon.mdc with alwaysApply: true
  • @.canon/injection.md referenced from that rule
  • .canon/injection.md regenerated on init, approve, reject, and suggest

Limitation: Cursor will not re-read a changed snapshot until a new Agent session (or a rule reload). Approve a decision, then start a new chat. This is a Cursor platform limitation, not a missing Canon command.

Other agents (Grok, Codex, Copilot, Gemini, Windsurf, Cline, Continue)

Vendor memory is not Canon. Claude auto-memory, Grok memory, Codex memories, and Cursor notes are agent-written, usually machine-local, and have no rejected/superseded lifecycle. Official docs tell you to keep team rules in AGENTS.md / CLAUDE.md that a human maintains. That is the file that goes stale.

canon init writes a managed block into the files those tools actually load:

  • AGENTS.md (Codex, Copilot agent, Cursor, Grok, Gemini, Jules, Factory, Windsurf)
  • .grok/rules/canon.md plus a SessionStart refresh hook (Grok ignores hook stdout)
  • .github/copilot-instructions.md
  • GEMINI.md
  • .windsurf/rules/canon.md
  • .clinerules/canon.md
  • .continue/rules/canon.md
  • .mcp.jsoncanon mcp for on-demand lookup

Canon does not rewrite your CLAUDE.md. Commit .canon/CANON.md and .canon/decisions.json so teammates and CI see the same active decisions. A clone hydrates SQLite from decisions.json on canon init.

CLI commands

Command Purpose
canon init Create local storage, schema, and agent wiring. Idempotent.
canon status Project, database, GitHub, and integration status.
canon suggest Mine recent PRs/commits for conservative candidates.
canon approve [id] Candidate → active. May supersede an older decision.
canon reject <id> Candidate → rejected. Record is kept.
canon add "..." Record a decision from chat. --approve confirms it immediately.
canon query <text> Look up relevant active decisions.
canon check CI: fail if a change re-introduces a rejected decision. --strict also fails on warnings.
canon mcp Local stdio MCP server for on-demand lookup.
canon list List decisions. --active, --superseded, --rejected, --all, --tag.
canon show <id> Full body and provenance.
canon inject-preview Exactly what an agent would receive.
canon doctor Environment and integration checks.
canon config Show or set project configuration.
canon export Portable JSON of stored decisions.
canon import Validated import.
canon uninstall Remove managed integrations. History is kept unless --purge-data.
canon version Print the version.

Most commands accept --json. Debug with --debug or CANON_DEBUG=1.

Exit codes: 0 success, 1 application error, 2 invalid usage.

Decision lifecycle

candidate  →  active
candidate  →  rejected
active     →  superseded

Rejected and superseded records stay in SQLite. Injection uses active decisions only.

Decision #42
Status: SUPERSEDED
Superseded by: #57

Provenance

Every suggested and approved decision records what Canon actually knows:

  • source PR or commit
  • source repository
  • source date
  • confirmation date and confirmer

If a field is unavailable, Canon says so. It never invents PR numbers, hashes, authors, dates, or URLs.

Privacy

The default is local and private. No account is required.

  • SQLite, decision history, and injected context stay on disk.
  • Network is used only for optional GitHub PR metadata.
  • Telemetry is off unless you set CANON_TELEMETRY=1, and even then V1 only appends local events to .canon/telemetry.jsonl.

See PRIVACY.md.

Security

Canon treats commit messages, PR titles, PR bodies, filenames, and API responses as untrusted data. They are never executed and never treated as instructions. Git and gh run with argument lists, not a shell. SQL is parameterized.

See SECURITY.md.

Configuration

Precedence:

CLI arguments
    ↓
environment variables
    ↓
project config (.canon/config.toml)
    ↓
user config (~/.canon/config.toml)
    ↓
defaults

Defaults:

Setting Default Meaning
injection.max_decisions 12 Hard cap on injected decisions
injection.max_chars 4000 Hard cap on injection characters
injection.max_tokens 1000 Estimated token cap (chars / 4)
mining.lookback_prs 20 Merged PRs to inspect
mining.lookback_commits 80 Commits to inspect when GitHub is unavailable
mining.min_score 6 Conservative suggestion threshold
privacy.telemetry false Local event log only, off by default

Copy .env.example if you need environment overrides. Never commit .env.

Troubleshooting

Symptom What to do
not a Canon project Run canon init inside a Git repository.
GitHub CLI is installed, but you are not authenticated Run gh auth login, then canon suggest.
canon is not recognized Use python -m canon ... or add Python Scripts to PATH.
No candidates Expected on mechanical/UI-only history. Product/policy and stack choices should appear.
Claude session has no decisions Run canon doctor. Confirm canon is on PATH. Start a new session.
Cursor ignores a new decision Start a new Agent chat after canon approve.
Offline list, status, and inject-preview work without a network. suggest falls back to Git history.

Development

See CONTRIBUTING.md.

git clone https://github.com/Adarshk18/Canon.git
cd Canon
python -m pip install -e ".[dev]"
pytest
ruff check src tests
mypy
python -m build

Install unreleased main without a checkout:

pip install git+https://github.com/Adarshk18/Canon.git

Testing

pytest covers decision lifecycle, supersession, mining filters, injection budget, CLI commands, path traversal, SQL injection, command injection, and prompt-injection-style repository content.

Canon Cloud (optional)

Local use needs no account. Cloud is sync + team seats + billing.

export CANON_CLOUD_URL=https://your-canon-host
canon cloud login
canon cloud push
canon cloud pull
canon cloud upgrade pro

Billing is Polar.sh, not Stripe (Stripe India is invite-only). See docs/SAAS.md.

Roadmap / deferred features

Intentionally not in V1, matching the source product plan:

  • Slack or Notion connectors
  • Daily multi-project drift engine
  • Rich team dashboard
  • Enterprise self-host packaging
  • Organization management and SSO

Stdio MCP lookup, AGENTS.md/Copilot/Grok wiring, canon add / canon check, and a committed team snapshot shipped in 1.3.

The domain model is isolated from SQLite so those can be added later without rewriting the local core.

Historical name

An earlier plan used the working name DecisionVault. The product is Canon.

License

MIT. See LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

canon_memory-1.3.0.tar.gz (82.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

canon_memory-1.3.0-py3-none-any.whl (82.3 kB view details)

Uploaded Python 3

File details

Details for the file canon_memory-1.3.0.tar.gz.

File metadata

  • Download URL: canon_memory-1.3.0.tar.gz
  • Upload date:
  • Size: 82.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for canon_memory-1.3.0.tar.gz
Algorithm Hash digest
SHA256 09411d0fb8960fda144c3d662a36ca14c5bb12861bf18157be745dca1ffe9cef
MD5 5ea2f6591f0bfa52725c86a9c546e7ad
BLAKE2b-256 aa1d28989dfe1c3d66f87a994e6b31bfb1b4165c31c83557e9ee85197066ab77

See more details on using hashes here.

Provenance

The following attestation bundles were made for canon_memory-1.3.0.tar.gz:

Publisher: publish.yml on Adarshk18/Canon

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file canon_memory-1.3.0-py3-none-any.whl.

File metadata

  • Download URL: canon_memory-1.3.0-py3-none-any.whl
  • Upload date:
  • Size: 82.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for canon_memory-1.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 81695eb431bd65e7a8c3c7d682020bfd722b781acfd1bcae954e16dd9dc1b8a3
MD5 68907b827ac91cc73bd84bb76e2e2624
BLAKE2b-256 e97738e0946da4a55748a8853245efe7bc61e23d9d257503b4201e7e9d1a1c70

See more details on using hashes here.

Provenance

The following attestation bundles were made for canon_memory-1.3.0-py3-none-any.whl:

Publisher: publish.yml on Adarshk18/Canon

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

1.3.0 This release

2 files

1.1.0

2 files

1.0.1

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page