Architecture and security boundaries
CLI and MCP delegate to shared deterministic services; optional AI remains outside that path.
flowchart TB
subgraph hosts["Agent hosts"]
H1["Codex"]
H2["Claude Code"]
H3["Cursor"]
H4["Gemini CLI / Claude Desktop"]
end
subgraph adapters["Protocol adapters"]
CLI["CLI · knowl …"]
MCP["MCP · knowl serve"]
HOOK["Short-lived lifecycle hooks"]
VIEW["GET-only local viewer"]
end
subgraph core["Deterministic core services"]
GOV["Validation · reconciliation · history"]
RET["Vector-primary retrieval · BM25 fallback · context"]
LIFE["Tasks · sessions · handoffs"]
EVID["Evidence · drift · code index"]
WS["Workspace federation"]
SYN["Skills · tag synthesis"]
end
subgraph local["Local project state"]
DB[(" .knowl/knowl.db ")]
SK[".knowl/skills/"]
MAN["Machine-local workspace manifest"]
PEER[("Promoted peer atoms · read-only")]
end
AI["Optional configured AI<br/>ask · raw ingest · assisted comparison/derivation"]
hosts --> CLI
hosts --> MCP
hosts --> HOOK
CLI --> GOV
CLI --> RET
CLI --> LIFE
CLI --> EVID
CLI --> WS
CLI --> SYN
MCP --> GOV
MCP --> RET
MCP --> LIFE
MCP --> EVID
MCP --> WS
MCP --> SYN
HOOK --> LIFE
VIEW --> DB
GOV --> DB
RET --> DB
LIFE --> DB
EVID --> DB
WS --> DB
SYN --> DB
SYN --> SK
WS --> MAN
WS --> PEER
CLI -. configured only .-> AI
MCP -. configured ingest/derivation .-> AI
AI --> GOV
| Layer | Source | Responsibility |
|---|---|---|
| Protocol and commands | src/mcp, src/cli |
MCP registration, CLI parsing, host setup, lifecycle envelopes |
| Core contracts | src/core |
Types, validation boundaries, formatting, configuration, token budgets |
| Store and retrieval | src/store |
SQLite schema, assertions, evidence, ranking, sessions, portability, maintenance |
| Workspace federation | src/workspace |
External manifests, membership, ownership, promotion, peer resolution |
| Code intelligence | src/code |
Tree-sitter indexing and symbol:// resolution |
| Learned skills | src/skills |
File-backed package validation, registry, entrypoint execution |
| Viewer | src/viewer |
Loopback-only graph and inspection APIs |
| Optional AI | src/pipeline, src/ai |
Filter → extract → verify → merge pipeline, question answering, assisted derivation |
Storage, retrieval, governance, lifecycle, skills, and synthesis need no provider. Writes always pass size validation and, by default, secret and sensitive-path checks. The database and skills are local; workspace manifests hold external machine paths; the unauthenticated viewer is loopback-only.
Write durability
All three SQLite databases — the knowledge store, the transcript index, and the resume store —
run in WAL with synchronous = NORMAL.
NORMAL does not fsync on every commit. An application crash, a killed knowl serve, Ctrl-C, or
a closed laptop lid still lose nothing: SQLite's documentation is explicit that "transactions are
durable across application crashes regardless of the synchronous setting or journal mode", and
that "WAL mode is safe from corruption with synchronous=NORMAL". Only a power cut or an OS
crash can drop the last seconds of writes, and the file still opens cleanly afterwards. Measured
against FULL on this schema, NORMAL is 4.19× on un-batched writes — the common shape here, since
one knowl_store or one hook capture is a single write — and better under contention.
| Variable | Default | Meaning |
|---|---|---|
KNOWL_SQLITE_SYNCHRONOUS |
NORMAL |
NORMAL or FULL. Set FULL to fsync every commit, buying durability across power loss at roughly 4× the per-write cost. OFF is refused: it can corrupt the database on power loss and measured no faster than NORMAL. An unrecognised value stops the command rather than silently falling back. |