Skip to content

Storage and Memory Architecture โ€‹

TIP

One-liner: CodyMaster gives your AI a durable 5-tier brain that persists across sessions, avoids token overflow, and gets smarter over time.


The 5-Tier Memory Model โ€‹

Every CodyMaster project has five layers of memory, each with a different lifespan and purpose:

TierNameStorageLifespanPurpose
1SensoryChat contextThis turnActive files, terminals, current selection
2WorkingCONTINUITY.mdSession โ†’ next sessionGoal, phase, blockers, last actions
3Long-termcontext.db (SQLite)IndefiniteLearnings, decisions, BM25-ranked retrieval
4Semanticqmd indexUntil re-embedFull-text + vector search across docs/code
5StructuralSkeleton index + CodeGraphUntil re-indexAST, call graphs, 95% token compression

Tiers 1โ€“3 are always active. Tiers 4โ€“5 are opt-in and activated by skills automatically when the project grows large enough.


Global vs Project State โ€‹

Global user data (~/.codymaster/) โ€‹

Shared across all projects, managed by src/data.ts:

~/.codymaster/
โ””โ”€โ”€ kanban.json     โ† projects, tasks, activities, deployments, changelog, chain executions

Per-project memory (.cm/) โ€‹

Isolated per repo, never committed to git (add .cm/ to .gitignore):

.cm/
โ”œโ”€โ”€ CONTINUITY.md           โ† Working memory (Tier 2): goal, phase, blockers, last actions
โ”œโ”€โ”€ config.yaml             โ† Runtime configuration
โ”œโ”€โ”€ context.db              โ† SQLite: learnings + decisions with FTS5 index
โ”œโ”€โ”€ context-bus.json        โ† Real-time output sharing between skills in a chain
โ”œโ”€โ”€ skeleton.md             โ† L0 codebase index (auto-generated by cm-codeintell)
โ”œโ”€โ”€ token-budget.json       โ† Token allocation by category
โ””โ”€โ”€ memory/
    โ”œโ”€โ”€ learnings.json      โ† Legacy flat-file (migrated to SQLite on first run)
    โ””โ”€โ”€ decisions.json      โ† Legacy flat-file (migrated to SQLite on first run)

Storage Backend โ€‹

src/storage-backend.ts defines a StorageBackend interface with 11 methods covering learnings, decisions, skill outputs, and index caching. The backend is swapped via .cm/config.yaml:

yaml
# .cm/config.yaml โ€” default (no changes needed)
storage:
  backend: sqlite

The production backend. Implemented in src/context-db.ts using better-sqlite3:

  • WAL mode โ€” concurrent reads during writes
  • FTS5 virtual tables โ€” BM25-ranked full-text search on learnings and decisions
  • Auto-sync triggers โ€” FTS index stays in sync on every INSERT/DELETE
  • Zero external dependencies โ€” runs in-process, no server required
mermaid
flowchart LR
    A["CLI / MCP Tool"] --> B["StorageBackend\nsrc/storage-backend.ts"]
    B --> C["SqliteBackend\nsrc/context-db.ts"]
    C --> D["context.db\nFTS5 ยท BM25"]
    D --> E["cm_query\ncm_memory_query\nMCP tools"]

    style C fill:#2f3640,stroke:#fbc531,color:#fff
    style D fill:#353b48,stroke:#fbc531,color:#fff

Removed OpenViking backend โ€‹

Older CodyMaster revisions experimented with an OpenViking-backed implementation. That runtime path has been removed after proving too costly to install and too unreliable for the supported product path.

WARNING

Keep storage.backend: sqlite. If an older project config still says viking, CodyMaster warns and falls back to SQLite automatically.


Search and Retrieval โ€‹

Used by cm-continuity and MCP tools to recall relevant learnings and decisions:

Skill: "I need context about the auth module"
  โ†“
cm_query("auth module")
  โ†“
SQLite FTS5 BM25 search โ†’ top-k learnings + decisions sorted by relevance
  โ†“
Agent receives focused context slice (not the entire learnings file)

When to use: automatically. Skills call cm_query via MCP without user action.

For codebases >200 files or doc sets >50 pages, grep and file reads cause context overflow. qmd provides BM25 + vector search that returns precise snippets instead of full files.

Activated by: cm-deep-search โ€” triggers automatically when it detects a large project.

Setup: See Semantic Search Guide โ†’

For understanding codebases without reading every file:

LayerToolCostOutput
L0Skeleton index~4s, <500 tokensDirectory map, exports, imports
L1CodeGraph (AST)~30s, <2K tokensFunction signatures, class interfaces
L2Full contextOn-demandVector embeddings per file

Activated by: cm-codeintell when you ask "what does this codebase do?" or "how does X work?"


The Context Bus โ€‹

.cm/context-bus.json enables skills in a chain to share outputs without re-deriving state from chat history:

cm-planning writes: { "plan": "...", "phase": "design" }
       โ†“
cm-tdd reads: { "plan": "..." }  โ† no need to re-explain the plan
       โ†“
cm-code-review reads: { "plan": "...", "test_results": "..." }

MCP tools: cm_bus_read, cm_bus_write in src/mcp-context-server.ts.


Token Budget โ€‹

.cm/token-budget.json pre-allocates the 200k context window by category to prevent silent overflow:

engineering:    60k tokens
product:        30k tokens
operations:     20k tokens
growth:         20k tokens
orchestration:  30k tokens
reserved:       40k tokens

MCP tool: cm_budget_check โ€” skills call this before loading large context.


cm:// URI Scheme โ€‹

Skills reference context by URI, not file paths. The URI resolver (src/uri-resolver.ts) maps:

URIResolves to
cm://memory/learnings.cm/context.db learnings table
cm://memory/decisions.cm/context.db decisions table
cm://index/l0.cm/skeleton.md
cm://bus/current.cm/context-bus.json
cm://skill/cm-tddskills/cm-tdd/SKILL.md

MCP tool: cm_resolve โ€” loads the right context at the cheapest sufficient depth.


Configuration Reference โ€‹

Full .cm/config.yaml with all options:

yaml
storage:
  backend: sqlite        # supported default; legacy "viking" values fall back to sqlite

memory:
  max_learnings: 50      # Trigger Ebbinghaus TTL cleanup above this count
  archive_decisions: true

quality:
  velocity_tracking: true
  code_review_mode: strict  # "strict" | "normal"

rarv:
  max_retries: 3
  self_correction: true
  goal_alignment_check: true

See Also โ€‹

CodyMaster โ€” AI-assisted engineering toolkit