Architecture

OpenCanon is a daemon plus clients. The daemon owns state. The CLI, hooks, and UI present the same results.

Layout

skill layout
tree
.agents/skills/opencanon/
.gitignore
generated/ gitignored
project.ts
aliases.d.ts
scripts/
opencanon.ts
runtime/ gitignored
cli.js
core/
validators/
daemon/
ui/
engine/
index.ts
docs/opencanon/
decisions.json
canon/
*.md
.gitignore
.opencanon/
cache/ gitignored
~/.opencanon/
daemons.json

Boundaries

  • Workspace packages are the development source for @opencanon/cli, @opencanon/core, @opencanon/daemon, @opencanon/engine, @opencanon/ui, and @opencanon/validators.
  • The skill is self-contained. It ships the bundled runtime so consumers do not need workspace packages or npm install at install time. The bundled runtime is built for Bun.
  • Repository validators import through .agents/skills/opencanon/index.ts, never workspace package names. That keeps validator code portable across host repositories.

Discovery

Inside a Git repository, discovery is Git-backed. .gitignore is honored, then OpenCanon applies projectFilePatterns, ignore, maxFiles, and maxFileSizeKb. Filesystem discovery is available as an explicit override for tests and benchmarks; OpenCanon never silently falls back from Git to filesystem.

Graph Index

The engine extracts TS/JS symbols, references, calls, imports, literals, diagnostics, duplicates, and Python facts into local SQLite state. CLI graph commands and validators read the same index, so scoped searches, caller/callee inspection, and graph-backed validators share one source of repository facts. Rust crates, Cargo dependencies, and Python dependency metadata are also discovered for generated authoring constants.

Generated authoring types

The daemon keeps gitignored authoring files fresh under .agents/skills/opencanon/generated/. project.ts exposes typed constants for workspace packages, import specifiers, npm dependencies, Rust crates, Cargo dependencies, and Python dependencies. aliases.d.ts declares ambient modules for fixture source imports so invalid and valid virtual projects can still type-check in an editor.

These generated types are deliberately small. OpenCanon does not generate per-file symbol, literal, caller, or callee maps by default because those make TypeScript language servers slow in large repositories. Validators still read precise facts at runtime from ctx.facts and ctx.graph.

Strict prerequisites

Daemon-backed commands are strict about prerequisites: Bun runtime version, the bundled engine binary, the configured cache directory, decisions, and referenced Markdown headings. Invalid configuration is a hard failure for normal context and validate commands; doctor reports the same diagnostics and offers safe fixes.