# Architecture Source: https://docs.pmbai.dev/concepts/architecture How the pieces fit: agent host, MCP server, the warm daemon, and files on disk. ## The big picture ```mermaid theme={null} flowchart LR A["Agent host
(Claude Code, Cursor…)"] -->|MCP stdio| B["PMB MCP server"] B --> C["Engine"] C -->|read ~35ms| R["Hybrid recall
BM25 + vector + graph + rerank"] C -->|write <1ms| W["Async embed queue
SQLite first, vectors later"] R --> D[("SQLite")] R --> E[("LanceDB")] W --> D W --> E ``` * **Storage** - every event in SQLite; vectors in LanceDB beside it. Both are files on disk; copy them anywhere with `cp`. * **Recall** - BM25 (lexical) + dense vector + entity graph, fused with Reciprocal-Rank-Fusion plus an optional cross-encoder rerank. * **Writes** - async; the MCP tool returns sub-ms, embedding happens on a background thread. ## One warm daemon, many clients Rather than each agent loading its own model and vector store, PMB runs **one warm daemon** (Engine + model + LanceDB) that N clients share for instant recall. | Mode | Transport | What runs | | -------------------- | --------------------------------------- | ------------------------------------------------------------------------------------ | | Local (default) | daemon + HTTP, stdio proxy where needed | One warm runtime; Claude Code/Cursor point at the daemon, Codex via `pmb mcp proxy`. | | Local stdio | stdio | One per-client process - compatible, but more cold-start cost. | | Team / multi-machine | streamable HTTP + bearer token | One shared server for remote agents (behind a private network). | ## Two surfaces, one engine PMB reaches the agent two ways, and they're complementary: The deliberate ceiling - `prepare`, `recall`, `record_batch`… the agent calls these on purpose. The involuntary floor - auto-recall, ambient write, session restore, follow-through. Memory works without the model remembering to call a tool. On hook-enabled hosts (Claude Code, Codex), MCP and hooks are kept **together** * they're complementary, not redundant. See [How it works](/concepts/how-it-works) and [Core engine](/concepts/core-engine). # Core engine Source: https://docs.pmbai.dev/concepts/core-engine The part of PMB that stores, ranks, and serves memory - stores, runtime, and the read/write paths. ## What the Engine owns `src/pmb/core/engine/base.py` builds one `Engine` per workspace, composed from focused mixins. The constructor opens SQLite immediately but keeps BM25, LanceDB, embedding models, and graph caches lazy - so `pmb stats` and `pmb config` don't pay the vector-store cold start. Workspace detection, layered settings, model choice, and feature gates. SQLite for truth, LanceDB for vectors, BM25 for exact terms, graph tables for links. Session tracker, recall cache, write outbox, embed queue, touch buffer. Write, batch, recall, lessons, overview, goals, dedup, health, ambient APIs. ## Storage schema SQLite is the source of truth (`events.sqlite`); LanceDB is the vector side index beside it. | Store | Table / file | Purpose | | ------- | -------------------------------- | ------------------------------------------------------------------------- | | SQLite | `events` | Main log: ULID, type, content, metadata, importance, access counts, tier. | | SQLite | `event_edges` | Event-to-event reasoning edges (cause/support/conflict/derived). | | SQLite | `lesson_surfaces` | Which lessons were shown and whether they were followed. | | SQLite | `write_outbox` | Durable queue for async `record_batch` writes (replayable). | | SQLite | `embed_queue_pending` | Durable embedding queue with retry + dead-letter. | | SQLite | `error_log` | Swallowed background errors, surfaced by `pmb doctor`. | | SQLite | `graph_entities` / `graph_edges` | Canonical entities + weighted co-mention edges. | | LanceDB | `events` | Vector rows: `ulid`, `vector`, `text`. | | Cache | `bm25_index.pkl` | Cached BM25 token index, rebuilt when stale. | ## Write path ```mermaid theme={null} flowchart LR Tool["record_*"] --> Event[("events (SQLite)")] Event --> Embed["Embed queue"] --> Vectors[("vectors")] Event --> Entities["Entities"] --> Graph[("graph")] Event --> Ready["Recall-ready"] ``` Writes are **durable first**: the event lands in SQLite before any optional background work. Embeddings, graph extraction, and dedup may lag - they have retry paths and safe fallbacks - and recall can still find a fresh event via SQLite + BM25 while the embedder warms. ## Recall path ```mermaid theme={null} flowchart LR Query["Query"] --> Worthy{"Worth recalling?"} Worthy -->|No| Quiet["Quiet"] Worthy -->|Yes| Cand["Candidates"] Cand --> BM25["BM25"] --> Merge["RRF fusion"] Cand --> Vec["Vectors"] --> Merge Merge --> Rank["Rank (PAMVR)"] --> Gates["Gates"] --> Ctx["Context"] ``` The hot path never calls an LLM. Optional LLM work happens at write time, maintenance time, or for explicit commands (`consolidate`, `reflect`, `distill`). ## Concurrency & durability Dashboard, MCP, hooks, and CLI can touch one workspace at once. The daemon keeps one warm Engine/model/vector store instead of loading per agent. Async writes and pending embeddings have durable tables that replay after restart. Recall access-count updates are coalesced so parallel recalls don't fight SQLite. ## Code map | Concern | Source | | -------------------------------- | ----------------------------- | | Engine composition | `src/pmb/core/engine/base.py` | | Write / recall / lessons / goals | `src/pmb/core/engine/` | | Event schema + lifecycle | `src/pmb/core/events.py` | | BM25 / LanceDB backends | `src/pmb/core/search.py` | | Entity graph | `src/pmb/graph/store.py` | | MCP tools + server | `src/pmb/mcp/` | # How it works Source: https://docs.pmbai.dev/concepts/how-it-works Hybrid recall, async writes, lifecycle hooks, and a storage model that's just files on your disk. ## The shape of it Your agent calls PMB over MCP (local stdio). Reads go through a hybrid ranker; writes return in under a millisecond and embed in the background. Everything lands in one SQLite file, with vectors next to it. BM25 (lexical) + dense vectors + an entity graph, fused with Reciprocal-Rank-Fusion and an optional cross-encoder rerank. One call - `prepare(message)` - returns project context, surfaced lessons, recent activity and open goals in 4-16ms. The MCP tool returns immediately; the embed + vector insert happen on a background thread. No LLM call on the read or write path, ever, by default. Every event lives in SQLite; vectors live in LanceDB beside it. Both are files - copy them anywhere with `cp`, commit them, put them on a USB stick. ## Memory that doesn't wait to be asked The hard part of agent memory isn't storing - it's getting the agent to *use* what's stored. Soft instructions get skipped, so PMB wires hooks at the protocol level (on Claude Code): Every prompt is classified (sub-ms) and the matching memory is injected **before** the model thinks. The agent never decides to call `recall`. If the agent forgets to record its work, PMB synthesizes one entry from the observed actions - outcome-scored, tagged `source=autowrite`, reversible. After the context window compacts, PMB rebuilds “where you left off” so the agent picks the thread back up instead of re-asking you. At turn end PMB checks which surfaced lessons actually showed up in the work, and marks them followed - without the model self-reporting. ## Dedup, four layers Exact text match → cosine ≥ 0.92 auto-merge → cosine 0.80-0.92 borderline (verified later) → manual review in the dashboard. Old values are archived, never deleted; full history is queryable as-of any point in time. Multilingual with no language packs: the default embedder covers 50+ languages, so a Russian query finds an English fact. The cold lexical path self-compiles from your own traffic - a language you use gets faster over time, zero config. # Does PMB actually help? Source: https://docs.pmbai.dev/concepts/measuring-impact How PMB measures its own value - conservatively, on your data, and honest about when it can't be trusted. Most memory tools assert they improve your agent and back it with one flattering number. PMB takes the opposite stance: **measure it conservatively, on *your* data, and say loudly when the signal isn't trustworthy yet.** A memory system you can't measure is one you can't trust. There are two different questions inside "does it help?", and they need two different methods. Does recall find the **right** memory? Measured with reproducible benchmarks - LoCoMo recall\@10 ≈ 94.5%, multilingual top-10 ≈ 99.2%. Does **using** memory change outcomes? Measured by Earned Memory, joining each surfaced lesson to the outcome of the turn it was active in. ## Earned Memory - three honest layers PMB joins each surfaced lesson to the turn's outcome (tests pass/fail, red→green, build, deploy - no LLM) and reports effectiveness at three levels of rigor, refusing to overclaim at each one. `success_rate(lesson active)` minus `success_rate(no lesson)`. Useful first look, but **confounded**: lessons surface on harder turns, so a helpful lesson can show negative lift. A flag for review, never ground truth. Each lesson carries a **95% Wilson confidence interval** and a conservative verdict - `useful`/`harmful` only when the CI clears the baseline **and** n ≥ `min_n`; otherwise `unverified` or `insufficient`. An n=1 fluke can never read as a real effect. The cleanest control without randomization: compare the **same lesson** when **followed** vs **ignored**. Both arms share the same trigger population, so it holds the surfacing trigger fixed. ## What PMB will not do An untrustworthy metric never drives behaviour. Earned Memory is measurement-only: it does not feed ranking or decay until the outcome signal is dense enough to trust. PMB would rather show you `insufficient` than let a flattering-but-wrong number quietly re-weight your memory. ## Run it on your own data ```bash theme={null} pmb health lessons-impact -w 90 ``` Seeing `signal: insufficient` early is the honest answer, **not a bug** - outcome turns are rare, so a young workspace simply hasn't earned a verdict yet. A lesson only earns "useful"/"helps" once the statistics back it. # Memory model Source: https://docs.pmbai.dev/concepts/memory-model What PMB stores, the kinds of memory it keeps, and how memories age. ## Everything is an event Every memory is an append-only event with a ULID, a type, content, an importance score, a timestamp, access counters, and a tier. Events aren't edited in place: an update appends a new event, and a removal either archives (soft delete) or purges (hard delete). That keeps history honest and recovery easy. ## Types of memory PMB separates memory by type so the agent can treat each kind with the right weight. | Type | What it is | Comes from | | --------------------- | ---------------------------------------------------------- | --------------------------------------- | | `fact` | An atomic, durable fact | `record_fact`, `record_batch` | | `keyed_fact` | A mutable personal attribute (subject / attribute / value) | `record_keyed_fact` | | `decision` | A project-shaping choice | `record_batch` activity `kind=decision` | | `lesson` | A procedural rule that surfaces before relevant work | `pmb learn`, `record_batch` | | `goal` | A future intention with a status | `record_goal` | | `activity` | A lightweight log of a turn | `record_activity` | | `milestone` | A checkpoint in a named state-chain | `record_milestone` | | `qa` | A stored question/answer pair | `remember` | | `git`, `file`, `code` | Repository and code context | `pmb sync`, `index_project` | | `image` | An image with optional cross-modal embedding | `record_image` | ## Facts that change: keyed facts Some facts have exactly one current value - your city, your employer, a pet's name. `record_keyed_fact` stores these as `(subject, attribute, value)` and **upserts**: writing a new value archives the old one, so recall returns only the current value while the history stays queryable. ```text theme={null} record_keyed_fact("user", "city", "Warsaw") record_keyed_fact("user", "employer", "Anthropic") ``` ## Importance, pinning, and forgetting Every event has a 0.0-1.0 score that drives ranking and decay. Defaults vary by type - a fact starts higher than a routine activity. Pinning locks a memory at max importance; a pinned memory is never auto-archived. A daily decay lowers importance over time; old, low-importance memory is eventually archived. Tune with `decay.factor_per_day` or run `pmb decay`. ## Three tiers: how fast memory fades Every event sits in one of three tiers that differ only in fade speed. Recalling a memory promotes it toward a slower-fading tier - what you use sticks, what you never touch decays. | Tier | Holds | Fades over | | -------- | ---------------------------------- | ---------- | | Working | New activity and routine events | days | | Episodic | Events you've recalled a few times | weeks | | Semantic | Facts, decisions, and lessons | months | ## Soft delete vs hard delete Archiving (soft delete) hides a memory from recall but keeps the row, so you can restore it. A hard delete purges the row, its search vector, and its graph links. See [Deleting memories](/guides/deleting-memories). # Privacy & security Source: https://docs.pmbai.dev/concepts/privacy-and-security Local-first by design - what stays on your machine, secret redaction, and the team-mode boundary. PMB is local-first by design. Your memory is a SQLite file and a vector index on your own machine, and nothing leaves it unless you run a sync or export command on purpose. ## What stays local Global config, daemon token, and every workspace live under `~/.pmb/`. Recall runs locally - no LLM call, no network request. Binds to `127.0.0.1` only; never exposed to the network. There is no PMB server to phone home, by design. The only commands that touch the network are the explicit sync/export commands - and only when you run them. ## Secret redaction Before an event is written, PMB scans its text for credentials and replaces each with a `[REDACTED:]` marker, so secrets aren't stored: * **API keys:** Anthropic, OpenAI, Google, Stripe, AWS. * **Tokens:** GitHub, Slack, JWTs, bearer / `Authorization` headers. * **PEM private key blocks.** * **`KEY=value` lines** for `API_KEY`, `SECRET`, `PASSWORD`, `TOKEN`, `DATABASE_URL`. Redaction is pattern-based - a bare high-entropy string with no recognizable prefix can still slip through. Treat it as a strong safety net, not a guarantee. ## Memory poisoning & procedural lessons Local storage keeps PMB private, but it doesn't make every remembered fact authoritative. PMB surfaces lessons as rules before an agent acts, so a low-trust memory could become a future instruction if recorded without review. * Treat recalled lessons as **evidence with provenance**, not invisible policy - check source, confidence, freshness, and `surface_id` before a risky action. * Review durable rules with `pmb lessons` and the broader view with `pmb audit`. * Be more conservative with automatic writes than explicit `learn`/`remember`; archive suspect ones with `pmb forget-auto`. * Keep imported third-party histories in a separate workspace until trusted. ## Team mode: the bearer token is the boundary Locally there's no network surface. The moment you expose the MCP server over HTTP for a team, the bearer token is the only thing between your agent and any host that can reach the port. Set `PMB_MCP_BEARER_TOKEN`, and put the server behind a private network (Tailscale) or an SSH tunnel. Only team mode should listen beyond localhost. # Adding a language Source: https://docs.pmbai.dev/contributing/adding-a-language Short version: you probably don't have to do anything. A language works because the embedder already knows it. As of v0.9 PMB has **no per-language packs** in its core. A language works because the multilingual embedder already knows it - not because someone hand-wrote a list. ## Why most languages just work The embedder (`paraphrase-multilingual-MiniLM-L12-v2`, 50+ languages) maps same-meaning text to nearby vectors across languages. A Russian query finds an English fact, no translation. Classified by English semantic anchors; the embedder projects your language next to them, so "was sind meine Ziele" lands on the same `goals_query` anchor as "what are my open goals". As the warm tier classifies your messages, it logs which n-grams co-fired with which anchor and distils the high-precision ones into `$PMB_HOME/lang/auto.yaml`. Your common phrasings then classify *cold*, at regex speed - generated from your own traffic, not a pack. ## Check that your language works ```bash theme={null} pmb warmup # load the embedder once pmb recall "" # should surface the right facts cat "$PMB_HOME/lang/auto.yaml" # grows from your traffic over days ``` Honest limits: ALD only learns while the **warm daemon** runs and needs some traffic; CJK (no spaces) stays warm-anchor-only; exact top-1 is weaker for zh/ja (still strong in top-3). ## If your language is weak: swap the embedder The real lever now - not writing a pack: ```bash theme={null} pmb config set embedding.model BAAI/bge-m3 # broader language coverage pmb reindex pmb daemon restart ``` Anchor calibration is keyed by model id, so it rebuilds itself automatically. ## Escape hatch: hand-seed a pack The file-based pack mechanism still exists to bootstrap a language's cold path before ALD has traffic. Opt-in and additive - with no pack files PMB behaves exactly as shipped. ```bash theme={null} pmb lang list # shipped templates (de, es, fr) + what's enabled pmb lang enable de # copy the template to $PMB_HOME/lang/de.yaml pmb daemon restart pmb reindex ``` # Contributing Source: https://docs.pmbai.dev/contributing/contributing PMB is easiest to improve when changes stay small, documented, and covered by the relevant checks. ```mermaid theme={null} flowchart LR Pick["Pick a focused change"] --> Edit["Edit code or docs"] Edit --> Check["Run targeted checks"] Check --> Docs["Update docs when behavior changes"] Docs --> PR["Open a pull request"] ``` ## Setup ```bash theme={null} git clone https://github.com/oleksiijko/pmb.git && cd pmb python -m venv .venv && source .venv/bin/activate pip install -e ".[dev]" pytest # full suite (~4 min) pytest -k recall # fast subset (~12s) ``` Use the venv's Python, not system Python - `.venv/bin/python -m pytest` (or `.venv\Scripts\python.exe -m pytest` on Windows). Bare `pytest` outside the venv just reports missing deps. ## What good looks like One concern per PR. Open a discussion before a large change so we can align. When behaviour changes, update the CHANGELOG, the command/config reference, and the relevant guide. Lint (ruff) is blocking; the suite runs on Linux/macOS/Windows × Py 3.11-3.13. Usually nothing to do - the embedder already knows it. License: **Apache-2.0**. Issues and PRs welcome. # Roadmap Source: https://docs.pmbai.dev/contributing/roadmap Honest and local-first. Every item keeps memory on your disk, offline by default, with no call-home. Dates are intentionally absent - this is a one-maintainer project. Order signals priority, not a schedule. ## Shipped - v0.9 "Anchor Engine" Language packs are no longer required. The RU/UK packs were **deleted**; many languages now ride one mechanism instead of a pack each: * **Semantic anchors** - English exemplars classify intents + keyed-fact extraction; the multilingual embedder transfers them cross-lingually. * **ALD (anchor→lexicon distillation)** - the cold lexical path self-compiles from your own traffic into `$PMB_HOME/lang/auto.yaml`. * **Measured** - RU/UK recall top-1 = 1.00; 101-query multilingual eval top-3 ≈ 0.91; a blocking CI gate runs the eval with packs off so recall can't regress. ## Next Add a cold-path-coverage-over-time metric and report how fast it self-heals a language in real use. Re-measure recall + anchor p95 on a normal machine and tighten the gate. Promote v0.9 keyed extraction to default only once field false-positive rate is measured. Make `bge-m3` a first-class documented upgrade for CJK / lower-resource languages. ## Ingest & storage * **Backup** via litestream (continuous SQLite replication to a bucket you own). * **Optional cloud-sync** - bring-your-own bucket, never a PMB-hosted service. * **tree-sitter** project indexing for Rust / TypeScript. * **Image OCR** so screenshots and scanned PDFs become searchable memory. ## Non-goals No hosted PMB service, no telemetry, no call-home - there's nothing to add later because there's no server. No silent network calls on the read/write path; optional LLM passes stay explicit and opt-in. # Connect your agent Source: https://docs.pmbai.dev/guides/connect Wire PMB into Claude Code, Cursor, Codex and others - one command, then just talk to your agent. ```bash theme={null} pmb connect claude-code # or cursor, codex, windsurf, gemini, vscode, zed, opencode, continue ``` `pmb connect` writes the agent's MCP config and appends the usage rules to `CLAUDE.md` / `AGENTS.md`. Restart the agent and memory is live. ## Three tiers of integration **Claude Code** - auto-recall before each message, ambient write, session restore, follow-through. Memory works without calling a tool. **Codex** - MCP plus ambient write on turn-complete; no per-turn read hook. **Cursor · Windsurf · Gemini · VS Code · Zed · OpenCode · Continue** - memory via tools; ambient optional via `pmb ambient-watch`. ## Useful flags ```bash theme={null} pmb connect cursor --workspace personal # share one memory across agents pmb connect codex --active # proactive logging (agent records its own work) pmb connect --list # every agent + where its config lives pmb connect claude-code --probe # confirm pmb-mcp starts after wiring ``` Prefer the all-in-one path: `pmb setup` (or `pmb setup --all`) detects your agents, picks the model, wires + warms + starts the shared daemon in one flow. ## Remove it anytime Delete the `pmb` entry from the agent's MCP config to disconnect - your stored memory stays on disk and is still readable via the CLI. # The dashboard Source: https://docs.pmbai.dev/guides/dashboard A local web UI over everything PMB captured - your memory as a live graph and timeline. ```bash theme={null} pmb dashboard # http://127.0.0.1:8765, or the next free port ``` It binds to `127.0.0.1` only - nothing leaves your machine. PMB dashboard - Map view ## The tabs Every entity and connection as a live force-directed graph - people, files, projects, decisions; color by type, size by degree. Your memory as a journal, git-graph by project, newest first. Per-rule follow-rate and dead-lesson detection - see which rules pull weight. A ranker debugger: run a query and see why each result scored as it did. Borderline duplicate pairs, with inline merge. Per-tool latency from the MCP telemetry. Plus **Overview**, **Entities**, and **Arcs** (narrative threads). PMB dashboard - Timeline view The dashboard and the MCP HTTP server both default to port `8765`. If the default dashboard port is busy, `pmb dashboard` auto-skips to the next free port. Use `pmb dashboard --port 18888` when you want a fixed port. # Deleting memories Source: https://docs.pmbai.dev/guides/deleting-memories Archive, restore, or permanently purge - soft delete by default, hard delete when you mean it. ## Soft delete vs hard delete Hides a memory from recall but keeps the row - fully **reversible**. The default for `forget` / `delete`. Removes the row, its search vector, and graph links - **not** reversible. `delete --hard` only. ## Commands ```bash theme={null} pmb forget # archive one memory (reversible) pmb delete # archive after preview + confirmation pmb delete --hard # permanently purge after confirmation pmb restore # bring back a soft-deleted / archived memory pmb forget-topic project-x --dry-run # archive everything about a topic ``` ## Clean up automatic writes If an untrusted session or a noisy agent run may have polluted memory, archive what the ambient layer wrote itself: ```bash theme={null} pmb forget-auto --minutes 120 # archive source=autowrite from the last 2h ``` Set an expiry instead of deleting: `pmb ttl 30d`, then `pmb prune-expired` (from cron) archives anything past its TTL. Pinned memories (`pmb pin `) are never auto-archived. # Ingest your project Source: https://docs.pmbai.dev/guides/ingest Feed PMB your codebase, PDFs, and existing chat history - so the agent starts informed. ## Index the codebase ```bash theme={null} pmb index project . # scan files + symbols for project-aware recall pmb track modules # one-line "what this file does" per file pmb track changes # summarise the INTENT of new commits (the "why") pmb track install # run track changes automatically after each commit ``` The agent reads this back with the `project_structure(name)` MCP tool - languages, files grouped by directory (purpose + symbol count), key modules, and recent change intents - no filesystem scan. ## Index PDFs ```bash theme={null} pmb index pdf paper.pdf # extract + chunk + embed pmb index pdf ~/docs --recurse # a whole directory ``` ## Import existing history Bring memory from elsewhere and rebuild the graph after: ```bash theme={null} pmb import chatgpt ~/Downloads/conversations.json pmb import claude export.json pmb import markdown ~/notes/ # an Obsidian vault pmb import mem0 export.json ``` Keep imported third-party histories in a **separate workspace** until you trust the resulting facts and lessons - see [Privacy & security](/concepts/privacy-and-security). ## Capture as you go ```bash theme={null} pmb note "decided to use Postgres for JSONB" --pin pmb learn "always run make fmt before committing" pmb watch ~/notes/daily.md # auto-capture new paragraphs ``` # Ollama & offline LLM Source: https://docs.pmbai.dev/guides/ollama PMB works fully offline without any LLM. Ollama is only for the few opt-in background commands. PMB needs **no LLM** for its core: recall, writes, and the read hook are all model-free. An LLM is only used by a few opt-in, off-the-hot-path commands (`consolidate`, `reflect`, `distill`, the `llm:*` graph extractor). For those, Ollama keeps everything local. ## Set it up ```bash theme={null} pmb ollama status # health check + installed models pmb ollama use balanced # pick a profile: tiny / balanced / quality pmb ollama test # smoke-test the local model ``` ## Use it for the optional LLM passes ```bash theme={null} pmb config set consolidate.backend ollama pmb consolidate # cluster memories, extract one rule per cluster - local ``` Backends resolve `auto` as Claude CLI → Anthropic → Ollama. Pin Ollama explicitly to stay fully offline. The graph extractor can also run on Ollama for a cleaner knowledge graph: `pmb config set graph.extractor llm:ollama`. It never blocks the write path - on timeout it falls back to the regex extractor for that one event. ## Model and endpoint precedence Maintenance clients use explicit model/URL arguments first, then `PMB_OLLAMA_MODEL` / `PMB_OLLAMA_URL` (or `OLLAMA_HOST` for the URL), then workspace/global `ollama.model` and `ollama.url`, then built-in defaults. `pmb ollama status` and `pmb ollama test` use the same settings. `pmb consolidate` honors `consolidate.backend` unless `--backend` is supplied; `--backend auto` explicitly requests auto detection. ```bash theme={null} pmb ollama use llama3.2:3b --for consolidate pmb config set ollama.url http://localhost:11434 pmb consolidate --dry-run ``` An HTTP 404 from a running Ollama server can mean the selected model is missing. Check `ollama list` and pull that exact model; it is distinct from a connection failure. Embedding-model settings remain separate from generation-model settings. # Team & sync Source: https://docs.pmbai.dev/guides/team Share one memory across machines or a team - git-synced workspaces, or an optional HTTP MCP server. ## Sync a workspace over git The simplest cross-device / backup path - your memory is just files, so git moves them: ```bash theme={null} pmb workspace init --remote git@github.com:me/pmb-memory.git pmb workspace push # back up / share pmb workspace pull # on another machine pmb workspace status ``` For a public remote, encrypt into one portable bundle: ```bash theme={null} pip install 'pmb-ai[crypto]' pmb workspace export memory.pmb # scrypt + AES/HMAC pmb workspace import memory.pmb team # decrypt into a local workspace ``` ## Shared HTTP server (team mode) Expose one warm server to remote agents: ```bash theme={null} pmb mcp serve --transport streamable-http --host 0.0.0.0 --bearer-token ``` Team mode is the **only** mode that should listen beyond localhost. The bearer token is the boundary - set `PMB_MCP_BEARER_TOKEN` and put the server behind a private network (Tailscale) or an SSH tunnel. ## Point several agents at one memory ```bash theme={null} pmb connect claude-code --workspace personal pmb connect cursor --workspace personal # both read/write the same workspace; SQLite WAL handles concurrent writes ``` # Troubleshooting Source: https://docs.pmbai.dev/guides/troubleshooting The usual suspects - cold start, the daemon, empty recall, and how to diagnose. Start here - it diagnoses the install and runtime state: ```bash theme={null} pmb doctor ``` ## First recall is slow The first recall after a fresh boot loads the embedding model (\~1-2s, the model is \~450MB). Warm it once: ```bash theme={null} pmb warmup ``` The daemon also prewarms in the background on boot. Subsequent recalls are \~35ms warm. ## Recall returns nothing Intents/extraction are warm-only. `pmb daemon status`; start it with `pmb daemon start` (or `pmb setup`, which pins it warm). `pmb stats` to check counts. A young workspace is genuinely empty - index a project (`pmb index project .`) or capture a few notes. Auto-recall stays quiet on trivial messages by design. Use `pmb recall "…"` directly from the terminal to bypass the gate. ## Port already in use The dashboard and the MCP HTTP server both default to `8765`. Current PMB versions auto-skip the default dashboard port when it is already busy: ```bash theme={null} pmb dashboard ``` Use an explicit port when you want a fixed address: ```bash theme={null} pmb dashboard --port 18888 ``` ## Stray / duplicate warm processes ```bash theme={null} pmb daemon kill-all # stop the daemon + kill registered PMB processes, clear registry pmb setup # re-wire cleanly ``` ## Still stuck? ```bash theme={null} pmb doctor --strict # non-zero exit on real problems ``` Open an issue on [GitHub](https://github.com/oleksiijko/pmb) with the `doctor` output. # PMB Source: https://docs.pmbai.dev/introduction Local-first memory for your AI coding agent. One SQLite file on your disk. No cloud, no API keys, no re-explaining. Your AI agent forgets everything between sessions. PMB remembers - locally. PMB gives Claude Code, Cursor, Codex and other MCP agents a real memory: decisions, lessons, and project facts. They live in **one SQLite file on your disk** and come back through MCP - no cloud, no API keys, no LLM call on the read path. And it's the only agent memory that **tells you when it's actually helping**, instead of claiming "+X%". Without memory the agent asks clarifying questions; with PMB it recalls the answer in 6ms. ```bash pip theme={null} pip install pmb-ai pmb connect claude-code ``` ```bash npx theme={null} npx pmb-ai setup ``` ## Start here Install, wire your agent, and let memory work automatically. Hybrid recall, async writes, hooks, and the storage model. How PMB measures its own value - honestly. Every command, by category: connect, recall, manage, hooks, config. ## Why PMB One file on disk. No keys, no telemetry, no cloud to trust. Claude Code, Cursor, Codex, Windsurf, Zed - one `pmb connect`. 50+ languages out of the box; a Russian query finds an English fact. Tells you when a memory isn't helping. No fake numbers. ## What it feels like ```text Without memory theme={null} you ▸ fix the pricing bug from last Tuesday ai ▸ which file is that in? what was the bug? ``` ```text With PMB theme={null} you ▸ fix the pricing bug from last Tuesday ai ▸ recalled in 6ms → verdict-policy.ts:142, bundle fallback dropped below the 25% floor. ``` The agent didn't ask. It read its memory and showed up to the task informed. # Quickstart Source: https://docs.pmbai.dev/quickstart Install PMB, wire your agent, and let memory work automatically. ```bash theme={null} pip install pmb-ai ``` Prefer npm? `npx pmb-ai setup` installs the Python package, then runs setup. One command wires PMB over MCP and appends the rules to `CLAUDE.md` / `AGENTS.md` so the agent knows how to use it. ```bash theme={null} pmb connect claude-code # or cursor, codex, windsurf, zed… ``` Memory is automatic. On Claude Code, lifecycle hooks inject the right memory **before the model thinks** - you never have to remember to call a tool. Trivial messages inject nothing. ```bash theme={null} pmb dashboard # your memory as a live graph, on 127.0.0.1 pmb stats # what's stored pmb doctor # confirm everything's wired ``` Everything is local **stdio** - the server runs as a child process of your agent. No network, no port, no token. Apache-2.0, fully offline. ## Point several agents at one memory ```bash theme={null} pmb connect claude-code --workspace personal pmb connect cursor --workspace personal # both now read/write the same memory ``` Sharing one memory across machines or a team? That's an optional HTTP mode with bearer-token auth - you don't need it for local use. # Config, UI & maintenance Source: https://docs.pmbai.dev/reference/cli/config Settings, the web dashboard, background upkeep, and the few opt-in LLM-powered commands. ## Config & UI ### `pmb config list` Every setting, its value, and where it comes from (`--only-overridden`). ### `pmb config get | set | reset [value]` Read / change / reset a setting (workspace or `--global`). ```bash theme={null} pmb config set recall.top_k 8 pmb config list --only-overridden ``` ### `pmb dashboard` Local web dashboard on `127.0.0.1:8765`: graph, timeline, a live **Settings** editor (replaces the old `tune`/`tui` TUIs), an **Errors** view, perf, and a recall debugger. `pmb connect --active` builds the agent's proactive rules from the `agent.*` toggles (log\_decisions, log\_lessons, apply\_lessons, …). Change them, then re-run `pmb connect --active` to regenerate. ## Maintenance ### `pmb regraph` · `pmb prune-graph` · `pmb reindex` Rebuild the entity graph; drop weak edges to keep recall fast; re-embed all events (after switching the embedding model). ### `pmb rehearse` Spaced-repetition refresh of important-but-idle memories. ### `pmb session start | end | current | brief` Session management. `brief` = a digest of what was decided/done/learned **this session** (also the `session_brief` MCP tool). `end` can auto-distill lessons. ### `pmb sync [--days N]` · `pmb schedule` Capture git commits into memory; print OS scheduler config (cron / schtasks). ## Ollama (optional, fully local) ### `pmb ollama status | use | test` Health-check + list models; select a profile (tiny/balanced/quality); smoke-test. Ollama is optional - PMB works fully offline without any LLM. ## LLM-powered commands These are the **only** commands that need an LLM backend (Claude CLI / `ANTHROPIC_API_KEY` / Ollama). They run off the recall hot path - recall itself never calls an LLM. ### `pmb consolidate` Sleep-stage consolidation: cluster related memories, extract one rule per cluster. ### `pmb reflect` For each event, an LLM asks "why does this matter?" and stores searchable bridges for multi-hop queries. ### `pmb distill` Extract durable lessons/failures from a session's events automatically. ### `pmb arcs cluster` Cluster events into narrative threads ("Postgres adoption journey"). ```bash theme={null} pmb consolidate --backend auto # auto = Claude CLI > Anthropic > Ollama pmb distill # turn a session into lessons ``` ### Entity-graph extractor Swap how event text becomes graph nodes - `regex` (default, offline), `spacy` (POS + NER, no LLM), or `llm:claude|ollama|codex`. ```bash theme={null} pmb config set graph.extractor spacy ``` # Hooks & ambient memory Source: https://docs.pmbai.dev/reference/cli/hooks Force-feed memory at the protocol level - so it works without the model remembering to call anything. Hooks make memory work without the model remembering to act. `pmb hooks install claude-code` wires all four lifecycle hooks; Codex and MCP-only hosts get the equivalent via their own mechanisms. ## Install & inspect ### `pmb hooks install ` Wire the lifecycle hooks. Claude Code: UserPromptSubmit + PostToolUse + SessionStart + Stop. Codex: a `notify` → `pmb codex-notify`. ### `pmb hooks list` Show which hooks are installed. ### `pmb hooks capabilities` What ambient mechanism each agent supports: `hooks` (Claude Code) / `rollout` (Codex) / `mcp-only` (git observer). ### `pmb hooks uninstall ` Remove the hooks. ## Preview what hooks do ### `pmb auto-context "..."` Preview the per-turn memory a UserPromptSubmit hook would inject. ### `pmb session-restore [-m MIN]` Preview the "where you left off" digest a SessionStart hook injects after a compaction. ### `pmb lesson-followcheck --dry-run` Preview deterministic follow-through scoring for surfaced lessons. ```bash theme={null} pmb auto-context "fix the pricing bug" pmb session-restore -m 180 ``` ## Ambient auto-write Ambient write fills the gap when the agent forgets to record its work. It's **on by default**, never duplicates the agent's own `record_*` calls, and only journals a turn that clears an outcome bar (tests passed, a failure fixed, a deploy ran). ### `pmb autowrite [--dry-run]` Ambient auto-write for the current turn. LLM optional ### `pmb ambient-watch [...]` Ambient auto-write for MCP-only hosts (Cursor/Zed/VS Code): poll git, auto-write once the project goes idle. Pass several directories to run them in one process: ```bash theme={null} pmb ambient-watch app api docs --save pmb ambient-watch --all ``` ### `pmb forget-auto [--minutes N]` Archive memory the ambient layer wrote itself (`source=autowrite`). Reversible. `pmb track-action` and `pmb codex-notify` are hook-invoked (you don't run them by hand) - the PostToolUse journal and the Codex turn-complete bridge. ## Repeat-prevention When a message reads as pushback (profanity, ALL-CAPS, a repeat-word plus a negated action), PMB records a **draft lesson on the first complaint** so the rule exists when it's needed - not after the seventh time. If a later message or tool call strongly overlaps a known rule or past failure, the guard surfaces it loudly, even inside an autonomous tool loop. Tune via `auto_recall.*` and `hooks.pretool_guard`. # Manage, sync & backup Source: https://docs.pmbai.dev/reference/cli/manage Export, delete, pin, snapshot - and the only commands that ever touch the network, run on purpose. ## Own your data ### `pmb export [--format markdown | json] [--out FILE]` Dump all memory to readable text (`--include-archived`). Plain, unencrypted. ```bash theme={null} pmb export --format json --out memory.json ``` ### `pmb delete ` / `pmb forget ` Archive one or more memories after a preview + confirmation (reversible). Add `--hard` to `delete` to permanently purge memories, vectors, and graph links. ### `pmb restore ` Restore a soft-deleted or archived memory. ### `pmb forget-topic ` Archive everything about a topic in one command. `--dry-run`, `--yes`, `--in content|tag|source`. ```bash theme={null} pmb delete 0193abc12345_deadbeef pmb restore 0193abc12345_deadbeef pmb forget-topic project-x --dry-run ``` ### `pmb pin ` Pin a memory (max importance, never auto-archived). ### `pmb tag ` / `pmb untag` Tag / untag a memory for local organization. ### `pmb ttl 30d | clear` · `pmb prune-expired` Set/clear an expiry; archive memories past their TTL (run from cron). ### `pmb snapshot create | list | verify | restore` Local snapshots with SQLite online backup and SHA-256 file manifests. `verify ` checks integrity without restoring; `list --json` prints metadata. Stop PMB servers, agents, and dashboards before restoring. Restore validates first, saves a verified safety copy, replaces stale files, and rolls back file moves on an I/O error. Legacy snapshots have no file checksums. ### `pmb decay` · `pmb dedupe` · `pmb compact` Apply the forgetting curve; deduplicate (offline cosine by default; `--run-pending` uses an LLM for borderline pairs LLM optional); move old archived events to cold storage + VACUUM. ```bash theme={null} pmb snapshot create --note "before refactor" pmb decay ``` ## Sync & backup These are the **only** commands that touch the network - and only when you run them. Everything else is fully local. ### `pmb workspace init [--remote URL]` Turn the workspace into a git repo. ### `pmb workspace push | pull | status` Sync memory to/from a git remote (cross-device, team, backup). ### `pmb workspace clone ` Clone a remote workspace locally. ### `pmb workspace export [--key-file]` / `import ` Encrypt the workspace into one portable bundle (scrypt + AES/HMAC) - safe even on a public remote - and decrypt it back. Needs `pip install 'pmb-ai[crypto]'`. ### `pmb workspaces` List all known workspaces. ```bash theme={null} pmb workspace init --remote git@github.com:me/pmb-memory.git pmb workspace push ``` # Recall & explore Source: https://docs.pmbai.dev/reference/cli/read Search memory, explain the ranking, and browse what PMB knows - all offline. Most reading is automatic (hooks call `prepare`/`recall` for you). These are for inspection and one-off lookups from the terminal. ## Search ### `pmb recall` Search memory. Each hit shows source, confidence, freshness, and markers for lessons and failures. ```bash theme={null} pmb recall "where do I live now" -k 5 ``` ### `pmb why` Explain the ranking - which PAMVR rules fired and each multiplier. ```bash theme={null} pmb why "what port did we choose" ``` ### `pmb overview` Structured "what do I know about X?" - facts, decisions, lessons, goals, timeline. Also an MCP tool. ```bash theme={null} pmb overview "authentication" ``` ## Browse ### `pmb timeline` Chronological, day-grouped view. Flags: `--days`, `--type`, `--newest-first`. ```bash theme={null} pmb timeline --days 7 ``` ### `pmb insights` Analytics: totals, type breakdown, weekly growth, top topics, lessons/goals. ```bash theme={null} pmb insights ``` ### `pmb digest` Recap of recent memories: `today` / `week` / `month` (or `--days N`). ```bash theme={null} pmb digest week ``` ### `pmb audit` "What does PMB know about me?" - grouped, read-only view plus memory-health signals. ```bash theme={null} pmb audit ``` ### `pmb lessons` List the durable lessons & failures (procedural memory). ```bash theme={null} pmb lessons ``` ### `pmb reminders` Goals that are overdue or due soon. Flags: `--within N`, `--all`. ```bash theme={null} pmb reminders --within 7 ``` ### `pmb list` Recent events. Flags: `-n 20`, `--type T`. ```bash theme={null} pmb list -n 20 --type decision ``` ### `pmb stats` Workspace stats. ```bash theme={null} pmb stats ``` ## Graph ### `pmb graph` Inspect the entity/association graph: `stats` / `top` / `neighbors` / `rebuild`. ```bash theme={null} pmb graph top pmb graph neighbors "auth" ``` # Setup & connect Source: https://docs.pmbai.dev/reference/cli/setup-connect Wire PMB into your agent, manage the warm daemon, switch models, and diagnose the install. Every command supports `--help` for its full flag list. Everything is offline unless tagged otherwise. ## Setup ### `pmb setup [agent]` Recommended one-command setup. Detects your agent, picks the memory model, wires MCP + rules + hooks, warms the engine, and starts the shared daemon - in one guided flow. Omit `agent` to auto-detect. ```bash theme={null} pmb setup # guided pmb setup --all # wire every detected agent, one shared warm daemon ``` ### `pmb init [--name NAME]` Initialize a workspace in the current directory. Optional - a workspace auto-detects from cwd. ## Connect an agent ### `pmb connect ` Wire PMB into an agent's MCP config and install its rules. Points at the shared daemon by default; `--stdio` keeps a per-client server. Agents: `claude-code`, `cursor`, `codex`, `windsurf`, `gemini`, `vscode`, `zed`, `opencode`, `continue`. ```bash theme={null} pmb connect claude-code pmb connect cursor --workspace personal # share one memory across agents pmb connect codex --active # proactive-logging rules pmb connect --list # all agents + where config lives ``` | Flag | What it does | | ------------------ | -------------------------------------------------------------------------- | | `--active` | Install proactive-logging rules (agent records its own decisions/lessons). | | `--workspace NAME` | Point several agents at one shared workspace. | | `--probe` | After wiring, briefly spawn `pmb-mcp` to confirm it starts. | | `--stdio` | Per-client server instead of the shared daemon. | ## Models & daemon ### `pmb model [light | balanced | best]` Switch the embedding model later: download, re-embed memory, and restart the daemon in one step. Omit the arg for the interactive menu. ### `pmb daemon start | stop | status | restart` Manage the one warm daemon (Engine + model + LanceDB) that N clients share for instant recall. ```bash theme={null} pmb daemon status pmb daemon kill-all # stop daemon + kill stray PMB processes, clear registry ``` ### `pmb mcp serve | status | proxy` Run a shared HTTP MCP server (team mode), list running servers + their RAM, or run the stdio↔daemon bridge (`proxy`, auto-wired for Codex). ## Diagnose ### `pmb doctor` Diagnose the install and runtime state. `--remote user@host:/path` prints an SSH-tunneled MCP snippet. ### `pmb warmup` Pre-load the model + BM25 + LanceDB so the next recall is fast (avoids the \~1-2s cold start). # Capture & track Source: https://docs.pmbai.dev/reference/cli/write Write memory from the terminal, import existing history, and layer a semantic 'why' over your code. ## Capture memory ### `pmb note` Jot a memory from the terminal. `--pin` keeps it forever; `--ttl 30d` auto-expires it. ```bash theme={null} pmb note "decided to use Postgres for JSONB" --pin ``` ### `pmb learn` Record a durable lesson. `--failed` records a failure to avoid repeating. ```bash theme={null} pmb learn "always run make fmt before committing" ``` ### `pmb fact` Record a standalone fact. `--ttl 30d` optional. ```bash theme={null} pmb fact "the staging DB is read-only" ``` ### `pmb remember` Store a question / answer pair. ```bash theme={null} pmb remember "deploy command" "make deploy ENV=prod" ``` ### `pmb import` Import existing history and rebuild the graph after. Sources: `chatgpt`, `claude`, `mem0`, `markdown` (Obsidian vault). ```bash theme={null} pmb import chatgpt ~/Downloads/conversations.json ``` ### `pmb watch` Auto-capture new paragraphs from a notes file or folder. `--once` for cron. ```bash theme={null} pmb watch ~/notes/daily.md ``` ## Project tracking A semantic layer over `pmb index project`: the structural index says which symbols exist, this says **why** a file exists and **why** it changed. Local, idempotent. ### `pmb track changes` Summarise the intent of new git commits and link it to the files touched. Idempotent via a per-repo cursor. Flags: `--since`, `--max-commits`, `--backend`. ```bash theme={null} pmb track changes ``` ### `pmb track modules` A one-line "what this file does" per indexed file. Run `pmb index project` first. Flags: `--limit`, `--force`. ```bash theme={null} pmb index project . && pmb track modules ``` ### `pmb track install` Install a git post-commit hook so `track changes` runs automatically (background, non-blocking, never clobbers an existing hook). ```bash theme={null} pmb track install ``` ## Resume note A committable markdown snapshot of "where we are now", sourced from PMB's typed memory. ### `pmb resume save` Write the resume note now. `--path .pmb/resume.md` to choose the location. ```bash theme={null} pmb resume save ``` ### `pmb resume show` Print the current resume note. ```bash theme={null} pmb resume show ``` ### `pmb resume install` Enable auto-refresh at every turn end (Stop hook). Hand-edited additions below the `PMB-RESUME-MARKER` line are preserved across regenerations. ```bash theme={null} pmb resume install ``` # Configuration Source: https://docs.pmbai.dev/reference/configuration PMB works with zero config - every setting has a tuned default. These are the knobs you're most likely to touch. ## How configuration works Settings resolve in this order, first match wins: 1. a per-call override, 2. the workspace config (`~/.pmb/workspaces//config.yaml`), 3. the global config (`~/.pmb/config.yaml`), 4. the built-in schema default. ```bash theme={null} pmb config list # common keys: value, source, default pmb config list --pro # everything, including advanced knobs pmb config get pmb config set pmb config set # or the dashboard Settings tab ``` ## Recall quality | Key | Default | What it does | | ------------------------------- | ------- | ----------------------------------------------------------- | | `recall.top_k` | `5` | How many results recall returns. | | `recall.bm25_weight` | `0.7` | Lexical vs semantic balance (1.0 = pure BM25). | | `recall.recency_half_life_days` | `30` | How fast a memory's recency boost decays. | | `recall.keyed_fact_boost` | `0.35` | Extra weight for current keyed facts (e.g. your city). | | `recall.ppr_enabled` | `true` | Use the entity graph to spread relevance to related memory. | | `recall.rerank` | `false` | Run a slower cross-encoder reranker on results. | ## The read hook (auto-recall) | Key | Default | What it does | | -------------------------------- | ------- | ------------------------------------------------------------------ | | `auto_recall.enabled` | `true` | Inject relevant memory before the model thinks. | | `auto_recall.budget_chars` | `4000` | Size cap on the injected block. | | `auto_recall.correction_capture` | `true` | On pushback, record a DRAFT lesson on the first complaint. | | `auto_recall.repeat_guard` | `true` | Surface an existing rule LOUD when a message strongly overlaps it. | ## Daemon & connect | Key | Default | What it does | | ------------------------ | ---------------- | ------------------------------------------------------- | | `connect.default_daemon` | `true` | Point JSON hosts at the one shared daemon. | | `daemon.autostart` | `true` | Start a daemon in the background when a cold hook runs. | | `daemon.idle_exit_min` | `120` | Exit after N idle minutes (connecting pins this to 0). | | `daemon.tool_profile` | (set by connect) | MCP tool profile: minimal / lean / default / full. | ## Ambient auto-write | Key | Default | What it does | | -------------------------- | ---------- | ----------------------------------------------------------------- | | `autowrite.enabled` | `true` | Journal a turn the agent didn't record itself. | | `autowrite.min_importance` | `0.45` | Quality bar a turn must clear to be journaled. | | `autowrite.synthesizer` | `template` | `template` needs no model; an LLM backend gives richer summaries. | ## Agent logging (active mode) | Key | Default | What it does | | -------------------------- | ------- | ----------------------------------------------------------------- | | `agent.active_mode` | `false` | Install proactive-logging rules by default. | | `agent.apply_lessons` | `true` | The self-improvement loop: recall + follow lessons before a task. | | `agent.context_continuity` | `true` | Re-orient after a long session with `session_brief`. | ## Background brain & maintenance | Key | Default | What it does | | -------------------------- | ------------------- | ---------------------------------------------------------------- | | `consolidate.auto_trigger` | `false` | Run sleep-stage consolidation automatically. | | `decay.factor_per_day` | `0.985` | The forgetting curve applied by `pmb decay`. | | `dedup.enable` | `true` | Deduplicate near-identical memories. | | `graph.extractor` | `regex` | How entities are pulled from text (`regex` / `spacy` / `llm:*`). | | `embedding.model` | multilingual MiniLM | The embedder. Change with `pmb model` (re-embeds for you). | There are \~150 advanced "pro" knobs (`pmb config list --pro`). They're advanced on purpose - defaults are ablation-tuned and a blocking CI gate protects recall quality, so changing them is opt-in and rarely needed. # Agents & MCP tools Source: https://docs.pmbai.dev/reference/mcp-tools Which agents PMB supports, and the core-10 tools an agent sees by default. ## Supported agents `pmb connect ` wires 9 agents, in three tiers by integration depth. **Claude Code** - all 4 lifecycle hooks: auto-recall before each message, ambient write, session restore, follow-through. **Codex** (OpenAI) - MCP plus ambient write (rollout + notify); no per-turn read hook, so it inherits the default tool surface. **Cursor · Windsurf · Gemini CLI · VS Code · Zed · OpenCode · Continue** - memory via tools; ambient optional via a git observer. Only Claude Code and Codex install hooks. The rest are pure MCP: memory works, but the agent "remembers" via explicit tool calls and the rules appended to `CLAUDE.md` / `AGENTS.md`, not automatically before each turn. ## Tool profiles PMB trims the tool list so a fresh agent isn't drowned in choices. Set `PMB_TOOL_PROFILE`, or let `pmb connect` pick one. | Profile | Tools | For | | --------- | ----- | ------------------------------------------ | | `minimal` | 10 | **The default.** The core memory loop. | | `lean` | 30 | `default` minus hook-covered browse tools. | | `default` | 34 | Fuller day-to-day set. Opt in. | | `full` | \~65 | Everything, incl. maintenance/admin. | ## The core-10 (default surface) One read-first call at task start: project context, lessons, recent activity, open goals. Hybrid semantic + lexical search over memory. The single write path - facts, goals, activities in one call. Upsert a mutable personal attribute (city, employer…). Surface procedural rules and close the self-improvement loop. Graph-driven full context for a named project. Re-orient after your context compacted. See and move what's in flight. Everything outside the core-10 is one flag away (`PMB_TOOL_PROFILE=default` or `full`). Hidden tools are still callable from the CLI.