# Architecture This document explains how CLEAR is built: the layers, how they fit together, how the shared context layer serves knowledge to the agent, and how state stays correct across every surface. It is the technical companion to [How CLEAR works](./guides/how-it-works.md), which covers the same system at a conceptual level. If you only want to *use* CLEAR, start with [Getting started](./guides/getting-started.md). Read on if you want to understand the machine, extend it, or port it to another coding harness. --- ## The layered stack CLEAR is built in layers. Each layer depends only on the ones beneath it, and the boundary near the top is deliberate: everything below the adapter is harness-agnostic. ```mermaid %%{init: {'theme':'base','themeVariables':{'primaryColor':'#1f2937','primaryTextColor':'#f9fafb','primaryBorderColor':'#6b7280','lineColor':'#9ca3af','secondaryColor':'#374151','tertiaryColor':'#374151','clusterBkg':'#111827','clusterBorder':'#4b5563'}}}%% flowchart TB subgraph ADAPTER["Adapter layer — Claude Code"] HOOKS["7 lifecycle hooks
(hooks.json to dispatchers)"] SKILLS["/cf-* commands
(skills)"] end subgraph CONTEXT["Context-serving layer"] CM["context assembly
(right knowledge, right time)"] end subgraph STATE["State and sync layer"] HUB["sync-state aggregator
(single writer per surface)"] end subgraph CORE["Core engine layer — portable CLIs"] K["knowledge"] PL["plan"] WP["workpackage"] SY["sync"] end subgraph STORE["Storage layer — .clear/"] FILES["markdown + YAML
(source of truth)"] IDX["SQLite index
(derived cache)"] end ADAPTER --> CONTEXT CONTEXT --> STATE STATE --> CORE CORE --> STORE CM -. "surfaces" .-> ADAPTER ``` | Layer | What it is | Portable? | |-------|-----------|:---------:| | **Storage** | `.clear/` — markdown knowledge, YAML plan/workpackage/session/state files, and a SQLite index. The files are the source of truth; the index is a derived cache. | ✅ | | **Core engine** | Harness-agnostic TypeScript CLIs for the four domains: knowledge, plan, workpackage, sync. Each has a registry, writer, and parser. | ✅ | | **State & sync** | Aggregates cross-domain state into one record and propagates changes through a single writer per surface, so nothing drifts. | ✅ | | **Context-serving** | Assembles the right knowledge and state and hands it to the agent at the right moment. | ✅ (mechanism) | | **Adapter** | The Claude Code integration: the seven lifecycle hooks, their dispatchers, the `/cf-*` skills, and session wiring. | Claude Code-specific | The top layer is thin on purpose. The engine, the knowledge format (CKS), the state model, and the CLIs are all portable; Claude Code is the **first adapter**, not a requirement. See [Portable core vs adapter](#portable-core-vs-adapter). --- ## The storage layer: `.clear/` When you run `/cf-init`, CLEAR provisions a `.clear/` directory in your project: ``` .clear/ ├── knowledge/ # knowledge entries (markdown) + the SQLite search index ├── plans/ # master-plan.yaml — phases, workpackages, progress ├── workpackages/ # workpackage records ├── sessions/ # session handoffs ├── state/ # sync-state.json — the aggregated cross-domain state └── config/ # CLEAR configuration ``` Two principles govern this layer: - **Files are the source of truth.** Every knowledge concept and every plan is a diffable file you can read, review, and commit. There is no hidden database of record. - **The index is a derived cache.** The SQLite index under `knowledge/` exists for fast full-text search. It is rebuildable from the files at any time and never holds state the files do not. --- ## The core engine: portable CLIs Four domains, each a self-contained TypeScript CLI surface: | Domain | Responsibility | |--------|----------------| | **knowledge** | Capture, index, search, surface, and run the lifecycle (supersede, deprecate, prune) of CKS concepts. | | **plan** | Create or import plans; track phases, active phase, and rolled-up progress. | | **workpackage** | Create and track units of work; lifecycle, progress, dependencies. | | **sync** | Aggregate cross-domain state, propagate changes, detect and repair drift. | Each domain follows the same internal shape — a **registry** (the in-memory model and its operations), a **writer** (the only thing that mutates the on-disk files), and a **parser** (reads files into the model). Routing every mutation through a single writer is what makes the next layer's correctness guarantees possible. These CLIs take no dependency on Claude Code. They read and write `.clear/` given a path, and they are what a port to another harness would reuse unchanged. --- ## The state & sync layer Naive "memory" systems fail by silent disagreement: the notes say one thing, the tracker another, and the agent is handed a contradiction. This is the layer built to prevent that, and to keep CLEAR *correct*. ### The aggregated state record A single aggregator maintains `.clear/state/sync-state.json` — a digest of every domain's current state: the active session, the active workpackage (and progress), the active plan and phase, and a summary of recent knowledge. It is the one place a surface can read "where things stand" without re-deriving it from four sources. ```mermaid %%{init: {'theme':'base','themeVariables':{'primaryColor':'#1f2937','primaryTextColor':'#f9fafb','primaryBorderColor':'#6b7280','lineColor':'#9ca3af','secondaryColor':'#374151','tertiaryColor':'#374151','clusterBkg':'#111827','clusterBorder':'#4b5563'}}}%% flowchart LR SESS["session"] --> HUB WP["workpackage"] --> HUB PLAN["plan"] --> HUB KN["knowledge"] --> HUB HUB["sync-state.json
(aggregated digest)"] --> SURF["every surface reads
one consistent view"] ``` ### Single-writer propagation State changes propagate through one writer per surface, triggered at well-defined moments rather than patched into several files that can fall out of step: - **Session ↔ workpackage** reconcile at session start, so resuming a session is a continuation rather than a new one. - **Workpackage → plan roll-up** runs when progress changes: a workpackage's progress flows up into its phase and the plan, on a single canonical 0–100 scale that every reader shares. - **Plan → workpackage propagation** handles scope changes (insert, defer, reorder) without breaking references (see [Stable identifiers](#stable-identifiers)). - **Knowledge ↔ work** links each captured concept to the active work, bidirectionally. Because there is exactly one writer for each piece of state, the dashboard, the plan file, the workpackage records, and the aggregated digest cannot disagree. ```mermaid %%{init: {'theme':'base','themeVariables':{'primaryColor':'#1f2937','primaryTextColor':'#f9fafb','primaryBorderColor':'#6b7280','lineColor':'#9ca3af','secondaryColor':'#374151','tertiaryColor':'#374151','clusterBkg':'#111827','clusterBorder':'#4b5563'}}}%% flowchart LR EV["workpackage progress changes"] --> RU["roll-up (single writer)"] RU --> P["plan file"] RU --> S["sync-state.json"] P --> VIEW["status · plan view · handoff
all agree"] S --> VIEW ``` ### Stable identifiers Every plan, phase, and workpackage carries two identifiers: a **stable identifier** that never changes once assigned, and a **display identifier** derived from position (for example, a phase's place in the plan). When work is reordered or a phase is inserted, only the display identifiers shift; the stable identifiers, and every reference, link, and piece of bound knowledge that uses them, stay intact. This is what lets the plan be reshaped without orphaning knowledge or breaking cross-links. ### Drift detection and repair State can still be disturbed from outside: a hand-edit, an interrupted operation, a restored backup. CLEAR can detect divergence between the files and the aggregated digest and repair it: the index rebuilds from the knowledge files, and the aggregated state reconciles from the domain files. The files remain the source of truth; repair means re-deriving the caches and the digest from them. --- ## The shared context layer This is the layer that delivers CLEAR's core promise — *the right context, to the right agent, at the right time.* It assembles knowledge and state and hands them to the agent at specific moments in the session, so an agent never has to go looking. - **At session start**, it loads the previous session's handoff, the knowledge relevant to where you left off, and the active plan and workpackage. - **As you work**, when a file you have a concept bound to comes into play, the related decisions, patterns, and lessons surface, including the lifecycle status, so a superseded or deprecated concept is presented *as such* rather than as current truth. - **On each turn**, recent state changes roll up so the picture stays current. The agent is handed assembled context. It does not query a knowledge base; the context layer serves the base to it. --- ## The adapter layer: Claude Code CLEAR integrates with Claude Code through two mechanisms. ### The seven lifecycle hooks `hooks.json` binds a script to each point in the Claude Code session lifecycle. Each fires the corresponding dispatcher: | Hook | Fires when | What CLEAR does | |------|-----------|------------------| | **SessionStart** | A session begins | Reconcile session ↔ workpackage state; load the prior handoff and relevant knowledge into context. | | **UserPromptSubmit** | You send a message | Roll up progress; keep the served context current. | | **PreToolUse** | Before a read/write/search/command | Surface knowledge bound to the files in play; guard protected writes. | | **PostToolUse** | After a write or edit | Capture knowledge; advance deliverable progress; run quality checks. | | **PreCompact** | Before context compaction | Preserve essential state so nothing is lost to compaction. | | **Stop** | The agent finishes a turn | Surface follow-up workflows when warranted. | | **SessionEnd** | A session ends | Finalize and record session state. | ```mermaid sequenceDiagram participant U as You participant CC as Claude Code participant CLEAR as CLEAR hooks CC->>CLEAR: SessionStart CLEAR-->>CC: prior handoff + relevant knowledge + active state U->>CC: prompt CC->>CLEAR: UserPromptSubmit CLEAR-->>CC: rolled-up state, fresh context CC->>CLEAR: PreToolUse (touch a file) CLEAR-->>CC: knowledge bound to that file CC->>CLEAR: PostToolUse (write/edit) CLEAR-->>CC: capture knowledge, advance progress U->>CC: /cf-handoff CC->>CLEAR: SessionEnd CLEAR-->>CC: session finalized ``` ### The `/cf-*` skills The commands — `/cf-init`, `/cf-plan`, `/cf-workpackage`, `/cf-knowledge`, `/cf-status`, `/cf-handoff`, `/cf-reload`, `/cf-help`, `/cf-debug` — are the explicit surface. Under the hood, each skill calls the same portable core CLIs. The skill is the Claude Code-shaped wrapper; the CLI is the portable engine. --- ## Portable core vs adapter The boundary between the portable core and the Claude Code adapter is real, not aspirational: ```mermaid %%{init: {'theme':'base','themeVariables':{'primaryColor':'#1f2937','primaryTextColor':'#f9fafb','primaryBorderColor':'#6b7280','lineColor':'#9ca3af','secondaryColor':'#374151','tertiaryColor':'#374151','clusterBkg':'#111827','clusterBorder':'#4b5563'}}}%% flowchart TB subgraph PORTABLE["Portable core (harness-agnostic)"] ENG["domain CLIs
knowledge · plan · workpackage · sync"] FMT["CKS knowledge format"] ST["state and sync model"] DATA[".clear/ storage"] end subgraph BOUND["Claude Code adapter (the thin shell)"] HK["lifecycle hooks + dispatchers"] SK["/cf-* skills"] SESS["session lifecycle wiring"] end BOUND --> PORTABLE ``` - **Portable:** the domain CLIs, the [CKS knowledge format](../CKS.md), the state and sync model, and the `.clear/` storage. None of it knows what Claude Code is. - **Claude Code-specific:** the hooks and their dispatchers, the `/cf-*` skills, and the session lifecycle wiring — the layer that translates Claude Code's lifecycle events into core-CLI calls. A port to another coding harness (Codex, Cursor, Aider, Gemini CLI) reimplements only the adapter: bind that harness's lifecycle events to the same core CLIs. The engine, the format, and the state model come along unchanged. This is the direction behind [*Built to be ported*](../README.md#built-to-be-ported). --- ## How it all comes together A single capture-to-serve cycle touches every layer: ```mermaid %%{init: {'theme':'base','themeVariables':{'primaryColor':'#1f2937','primaryTextColor':'#f9fafb','primaryBorderColor':'#6b7280','lineColor':'#9ca3af','secondaryColor':'#374151','tertiaryColor':'#374151','clusterBkg':'#111827','clusterBorder':'#4b5563'}}}%% flowchart LR W["you edit a file
(act)"] --> PT["PostToolUse hook
(adapter)"] PT --> CAP["knowledge CLI captures
a concept (core)"] CAP --> F["markdown file
(storage)"] CAP --> I["SQLite index
(storage)"] CAP --> L["link to active work +
roll up state (state and sync)"] L --> SS["sync-state.json"] F -. "later, you touch the bound file" .-> SV["context layer surfaces it"] I -. "search" .-> SV SV --> A["the right context,
right agent, right time"] ``` The decision you made while editing becomes a concept bound to that file, indexed, linked to the work you are doing, and rolled into the project's state. It then resurfaces, with its lifecycle intact, the next time that code is in play. --- ## Where to go next - [How CLEAR works](./guides/how-it-works.md) — the conceptual version of this document. - [The knowledge system](./guides/knowledge-system.md) — the CKS model in depth. - [Plan](./guides/plan-management.md) · [Workpackage](./guides/workpackage-management.md) · [Session](./guides/session-management.md) management — the workflow surfaces. - [`CKS.md`](../CKS.md) — the formal knowledge spec.