# Architecture
How the Basic Memory plugin works, flow by flow. For the design rationale and
decision history, see [DESIGN.md](../DESIGN.md).
## The bridge
Claude Code has its own **working memory** (auto-memory: short, in-context notes
Claude keeps per project). Basic Memory is a **durable graph** (Markdown files,
semantic + structured search, portable across tools). They do different jobs. The
plugin is the connective tissue that keeps each informed by the other.
```mermaid
flowchart LR
subgraph CC["Claude Code session"]
WM["Working memory
(auto-memory)
fast · in-context · per-project"]
end
subgraph BM["Basic Memory"]
G["Durable graph
(Markdown + SQLite)
searchable · typed · portable"]
end
WM -- "PreCompact: checkpoint
before forgetting" --> G
G -- "SessionStart: brief
tasks + decisions" --> WM
classDef mem fill:#1f2430,stroke:#6A9BCC,color:#e8eaed;
class WM,G mem;
```
The plugin ships **four surfaces**, in three layers:
```mermaid
flowchart TB
subgraph Ambient["Ambient (lifecycle hooks)"]
SS["SessionStart hook
→ brief from the graph"]
PC["PreCompact hook
→ checkpoint to the graph"]
end
subgraph Background["Background (system prompt)"]
OS["output-style
→ search-first / capture / cite reflexes"]
end
subgraph Deliberate["Deliberate (slash commands)"]
SK["/basic-memory:bm-setup · bm-remember · bm-share · bm-status"]
end
Ambient --> MCP["Basic Memory MCP server"]
Background --> MCP
Deliberate --> MCP
MCP --> Files["Markdown files
(local and/or cloud)"]
```
Everything routes through the Basic Memory MCP server (and the `bm` CLI for the
hooks). The plugin itself holds no state — configuration lives in
`.claude/settings.json`, content lives in your Basic Memory projects.
## SessionStart — the brief
When a session begins, the hook puts the most relevant slice of the graph in front
of Claude *before the first prompt*, so the session starts oriented instead of cold.
```mermaid
sequenceDiagram
participant CC as Claude Code
participant H as session-start.sh
participant BM as Basic Memory (bm CLI)
participant C as Claude
CC->>H: SessionStart (cwd, source)
H->>H: read .claude/settings.json
(primaryProject, secondaryProjects, teamProjects)
par primary
H->>BM: search type=task status=active
H->>BM: search type=decision status=open
and each shared project (parallel)
H->>BM: search type=decision status=open
end
BM-->>H: results (or timeout → skip)
H-->>CC: brief (plain stdout, <10k chars)
CC->>C: brief injected into context
Note over C: starts on active tasks,
open decisions, team context
```
Key properties:
- **Structured, not fuzzy.** Queries filter on `type`/`status` frontmatter, so recall
is deterministic — exactly the active tasks and open decisions, not "things that
look similar."
- **Parallel.** Primary and shared-project queries run concurrently; total wall-clock
is ~one query, not the sum.
- **Best-effort.** No Basic Memory, no config, or a slow cloud read never blocks or
errors the session — the worst case is a missing or partial brief.
- **First-run aware.** With no config it nudges toward `/basic-memory:bm-setup`.
## PreCompact — the checkpoint
Right before Claude Code compacts the context window (and the texture of the session
would be lost), the hook writes a durable checkpoint so the next session can resume.
```mermaid
sequenceDiagram
participant CC as Claude Code
participant H as pre-compact.sh
participant BM as Basic Memory
CC->>H: PreCompact (transcript_path, cwd)
H->>H: read settings → primaryProject
alt no primaryProject configured
H-->>CC: exit (never write un-opted-in)
else configured
H->>H: extract opening request + recent thread
H->>BM: write_note type=session status=open
→ primaryProject/sessions/
BM-->>H: ok
end
Note over CC: compaction proceeds;
checkpoint surfaces in the next
SessionStart brief
```
The checkpoint is a schema-conforming `type: session` note, so the *next* session's
SessionStart query (`type=session`) finds it. Capture is extractive today; an
LLM-summarized version is the planned enrichment (PreCompact has a ~600s budget).
## Capture while you work
The opt-in output style turns three behaviors into reflexes during normal work — no
command needed:
```mermaid
flowchart LR
Q["User asks a recall question"] --> S["search the graph first
(structured filters)"] --> A["answer with permalinks"]
D["User makes a material decision"] --> W["write a type:decision note inline"]
```
Because decisions are captured **typed**, they show up in the next session's brief
automatically — the read and write sides reinforce each other.
## Teams — read across, share deliberately
On Basic Memory Cloud, the plugin reads team context into your brief but never
auto-writes to a shared project. Publishing back is always a manual gesture.
```mermaid
flowchart TB
subgraph You["Your session"]
P["primaryProject
(personal capture)"]
end
subgraph Team["Team workspace"]
T1["team/main"]
T2["team/notes"]
end
T1 -- "read-only
(SessionStart)" --> P
T2 -- "read-only
(SessionStart)" --> P
P -- "/basic-memory:bm-share
(deliberate, confirmed)" --> T2
note["Auto-capture (checkpoints, /remember)
writes ONLY to primaryProject"]
```
Team refs are workspace-qualified (`team/notes`) or `external_id` UUIDs, because
project names collide across workspaces. Reads route over the user's OAuth session.
## Where things live
| Path | Role |
|------|------|
| `hooks/session-start.sh`, `hooks/pre-compact.sh` | the ambient bridge (read / write) |
| `hooks/hooks.json` | registers the hooks |
| `output-styles/basic-memory.md` | the capture reflexes |
| `skills/{bm-setup,bm-remember,bm-share,bm-status}/` | the deliberate slash commands |
| `schemas/{session,decision,task}.md` | picoschema seeds (copied into your project at setup) |
| `.claude/settings.json` → `basicMemory` | per-project configuration |
| your Basic Memory projects | all actual content |