{"id":50804837,"url":"https://github.com/oleksiijko/pmb","last_synced_at":"2026-06-13T00:01:25.657Z","repository":{"id":360807464,"uuid":"1248675679","full_name":"oleksiijko/pmb","owner":"oleksiijko","description":"Local-first persistent memory for AI coding agents (Claude Code, Cursor, Codex) via MCP. 94.5% LoCoMo recall@10, 70ms p50, multilingual, zero API keys.","archived":false,"fork":false,"pushed_at":"2026-06-05T01:02:10.000Z","size":3656,"stargazers_count":75,"open_issues_count":5,"forks_count":4,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-06-05T03:10:12.155Z","etag":null,"topics":["ai-agents","ai-memory","bm25","claude-code","codex","cursor","knowledge-graph","lancedb","llm","local-first","mcp","memory","model-context-protocol","privacy","python","rag","semantic-search","sentence-transformers","sqlite","vector-search"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/pmb-ai/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/oleksiijko.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":"CITATION.cff","codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":"NOTICE","maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-25T00:05:59.000Z","updated_at":"2026-06-05T00:59:10.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/oleksiijko/pmb","commit_stats":null,"previous_names":["oleksiijko/pmb"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/oleksiijko/pmb","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oleksiijko%2Fpmb","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oleksiijko%2Fpmb/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oleksiijko%2Fpmb/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oleksiijko%2Fpmb/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/oleksiijko","download_url":"https://codeload.github.com/oleksiijko/pmb/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oleksiijko%2Fpmb/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34266916,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-12T02:00:06.859Z","response_time":109,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-agents","ai-memory","bm25","claude-code","codex","cursor","knowledge-graph","lancedb","llm","local-first","mcp","memory","model-context-protocol","privacy","python","rag","semantic-search","sentence-transformers","sqlite","vector-search"],"created_at":"2026-06-13T00:00:48.173Z","updated_at":"2026-06-13T00:01:25.599Z","avatar_url":"https://github.com/oleksiijko.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n\u003cimg src=\"https://raw.githubusercontent.com/oleksiijko/pmb/main/docs/assets/logo.png\" width=\"160\" alt=\"PMB logo\"\u003e\n\n# PMB\n\n### Local-first memory for your AI coding agent.\n### One file on your disk. Twenty-nine MCP tools. No cloud.\n\n[![PyPI](https://img.shields.io/pypi/v/pmb-ai.svg?label=pypi)](https://pypi.org/project/pmb-ai/)\n[![License](https://img.shields.io/badge/license-Apache_2.0-blue.svg)](LICENSE)\n[![MCP](https://img.shields.io/badge/MCP-native-purple.svg)](https://modelcontextprotocol.io)\n[![Local](https://img.shields.io/badge/local--first-✓-success.svg)](#privacy)\n\n[Install](#install) · [Demo](#what-it-feels-like) · [How it works](#how-it-works) · [FAQ](#faq)\n\n\u003c/div\u003e\n\n---\n\nPMB gives Claude Code, Cursor, Codex and the other MCP-aware agents a\nreal memory. Decisions you made last week. Lessons you taught them.\nPersonal facts about you. Project structure. PDFs. They survive every\nrestart, every model upgrade, every agent switch — because they live\nin **one SQLite file on your disk**.\n\nNo API keys. No subscription. No LLM call on the read path. Just files.\n\n```bash\npip install pmb-ai\npmb setup           # one prompt, detects your agent, wires it up\n# restart your agent\n```\n\nThat's it. Your agent now remembers.\n\n---\n\n## What it feels like\n\n```\nYou:    fix that LoadGuard pricing bug we hit last Tuesday\n\nAgent:  prepare(message=\"fix LoadGuard pricing bug\")\n        ↓ (6 ms)\n        → project_context: 12 events about LoadGuard,\n          4 lessons (incl. \"never lower NEGOTIATE/SKIP under 25%\"),\n          3 decisions, 2 open goals\n        → active_arcs: \"LoadGuard verdict-policy refactor (started Tue)\"\n        → lessons: 1 directly matches \"pricing\"\n        → recent_activity: 8 commits this week\n\n        Looking at src/engine/verdict-policy.ts (you opened it Tuesday\n        14:32, last changed Wednesday). The pricing bug you mentioned\n        is on line 142 where the bundle fallback was tightening below\n        the rate-floor. Per the lesson you saved, we should never\n        drop the threshold under 25% — let me restore the guard there.\n```\n\nThe agent didn't ask. It didn't guess. It read its memory in **6 ms**\nand showed up to the task already informed.\n\n---\n\n## What you can put in there\n\n```bash\n# Personal facts that change                  (with time-travel: old\n#                                                values archived, never lost)\nrecord_keyed_fact(\"user\", \"city\", \"Warsaw\")\n\n# Project structure — symbols, imports, .gitignore-aware\npmb index project .\n\n# PDFs (research papers, manuals, contracts)\npmb index pdf paper.pdf\npmb index pdf ~/docs --recurse\n\n# Whatever your agent decides to log as it works\n# (decisions, lessons, completed tasks, goals)\n```\n\nPMB is content-agnostic. If it's text the agent will care about later,\nPMB will remember and retrieve it.\n\n---\n\n## What the agent gets back\n\nA single MCP call — `prepare(message)` — returns the right things at\nthe right level of detail, in 4-16 ms:\n\n| Field | What it is |\n|---|---|\n| `project_context` | Full project overview if the message mentions a project: key facts, lessons (RULES to follow), decisions, open goals, related entities, the project's narrative arc |\n| `lessons` | Procedural rules matching the query, each with a `surface_id` so the agent can confirm it followed the rule later |\n| `recent_activity` | Last 24 h of decisions / edits / completions for session continuity |\n| `open_goals` | In-progress goals so the agent knows what you're pursuing |\n| `active_arcs` | Narrative arcs the project is currently living in |\n\nFor everything else there's `recall(query)` (hybrid search, 35 ms warm)\nand 27 other tools listed in [docs/COMMANDS.md](docs/COMMANDS.md).\n\n---\n\n## How it works\n\n```mermaid\nflowchart LR\n    A[Your agent] --\u003e|MCP stdio| B[PMB MCP server]\n    B --\u003e C[Engine]\n    C --\u003e|read 35 ms| R[Hybrid recall\u003cbr/\u003eBM25 + vector + graph + rerank]\n    C --\u003e|write \u0026lt; 1 ms| W[Async embed queue\u003cbr/\u003eSQLite first, vectors later]\n    R --\u003e D[(SQLite)]\n    R --\u003e E[(LanceDB)]\n    W --\u003e D\n    W --\u003e E\n    style A fill:#dbeafe,color:#1e3a8a\n    style B fill:#ede9fe,color:#5b21b6\n    style C fill:#dcfce7,color:#14532d\n```\n\n**Storage** — every event lives in SQLite. Vectors live in LanceDB next\nto it. Both are files on your disk; copy them anywhere with `cp`.\n\n**Recall** — BM25 (lexical) + dense vector (semantic) + entity graph\n+ optional cross-encoder rerank, fused via Reciprocal-Rank-Fusion.\n\n**Writes** — async. The MCP tool returns in under a millisecond. The\nactual embed + LanceDB insert happens on a background thread.\n\n**Dedup** — four layers. Exact text match → cosine ≥ 0.92 auto-merge\n→ cosine 0.80-0.92 borderline (LLM verify later) → manual review in\nthe dashboard. Old values get archived, never deleted; full history\nis queryable via `keyed_fact_as_of(t)`.\n\n**Multilingual — no language packs.** The default embedder\n(`paraphrase-multilingual-MiniLM-L12-v2`) covers 50+ languages, so a\nRussian query like *где я живу* finds an English keyed-fact stored as\n*user.city = Warsaw* with no translation. Intent detection and keyed\nextraction ride **English semantic anchors** that transfer cross-lingually\nthrough the embedder — one mechanism for every language the model knows,\ninstead of a hand-written pack per language. The cold lexical path then\n**self-compiles** from your own traffic (anchor→lexicon distillation), so a\nlanguage you actually use gets faster over time with zero configuration.\nRecall stays strong across ~11 languages (overall top-3 ≈ 0.9 on a\n101-query eval; top-1 = 1.00 for en/fr/pt/ru, CJK weaker on exact top-1).\nSee [docs/adding-a-language.md](docs/adding-a-language.md).\n\n---\n\n## Install\n\n```bash\npip install pmb-ai\n```\n\nOr from source:\n\n```bash\ngit clone https://github.com/oleksiijko/pmb.git \u0026\u0026 cd pmb\npython -m venv .venv \u0026\u0026 source .venv/bin/activate\npip install -e .\n```\n\nPrime the model once so the first `recall` is fast (the embedding model is\n~90 MB; without this the very first query pays a one-time cold-start load):\n\n```bash\npmb warmup\n```\n\n\u003e **Running the tests?** Use the venv's Python, not your system Python —\n\u003e `.venv/bin/python -m pytest` (or `.venv\\Scripts\\python.exe -m pytest` on\n\u003e Windows). Running bare `pytest` outside the venv just reports missing\n\u003e `numpy`/`fastmcp`/`typer` — that's a missing venv, not a broken project.\n\nWire one or more agents:\n\n```bash\npmb connect claude        # Claude Code\npmb connect codex         # OpenAI Codex CLI\npmb connect cursor        # Cursor\npmb connect windsurf gemini vscode zed opencode continue   # also supported\n```\n\nPoint several agents at the same memory:\n\n```bash\npmb connect claude --workspace personal\npmb connect cursor --workspace personal\n# both now read/write the same workspace\n```\n\nEverything above is **stdio** — the server runs as a child process of your\nagent. No network, no port, no token. That's the whole story for one person\non one machine.\n\n\u003e Sharing one memory across machines or a team? That's an optional HTTP\n\u003e mode with bearer-token auth — see [docs/TEAM.md](docs/TEAM.md). You don't\n\u003e need it for local use.\n\nInspect:\n\n```bash\npmb dashboard     # http://127.0.0.1:8765\npmb tui           # terminal UI\npmb stats         # quick numbers\npmb doctor        # health check\n```\n\n---\n\n## CLI cheat sheet\n\n```bash\n# Memory\npmb stats                                  show counts and storage info\npmb recall \"query\"                          search with full debug\npmb tui                                     interactive terminal UI\npmb dashboard                               web UI on port 8765\n\n# Ingest\npmb index pdf paper.pdf                     extract + chunk + embed\npmb index pdf ~/docs --recurse              entire directory\npmb index project .                         scan codebase\npmb import chatgpt ~/Downloads/export.json  bring existing history\n\n# Maintenance\npmb regraph                                 rebuild entity graph\npmb consolidate                             run sleep pass (optional)\npmb compact                                 archive old events\npmb dedupe                                  resolve borderline duplicates\n\n# Hooks (force-feed PMB at the protocol level — no model cooperation)\npmb hooks install claude-code               wire all 4 lifecycle hooks\npmb hooks list                              show what's installed\npmb hooks capabilities                      ambient mechanism each agent supports\npmb hooks uninstall claude-code             remove them\npmb auto-context \"fix bug in PMB\"           preview per-turn injection\npmb session-restore -m 180                  preview post-compaction restore\npmb lesson-followcheck --dry-run            preview follow-through scoring\n\n# Ambient memory (the write side — memory journals the agent's work)\npmb autowrite --dry-run                     preview ambient auto-write for this turn\npmb ambient-watch .                         ambient auto-write for MCP-only hosts (git observer)\npmb forget-auto                             drop memory the ambient layer wrote itself\n\n# Config\npmb config list                             default tier (25 keys you care about)\npmb config list --pro                       every key, including 80 advanced knobs\npmb config set recall.ppr_enabled true      toggle a feature\npmb connect --rules-only                    refresh CLAUDE.md only\n```\n\nFull reference: [docs/COMMANDS.md](docs/COMMANDS.md).\n\n## Settings — 25 you care about, 80 you don't\n\nPMB has 105 tunables. The 25 that affect day-to-day quality are\n**default-tier** — visible in `pmb config list`. The rest are\ninternal weights, ablation knobs, and experimental flags, hidden\nbehind `--pro` so the surface stays scannable.\n\nDefault-tier highlights:\n\n| Key | Default | What it does |\n|---|---|---|\n| `recall.top_k` | 5 | How many results recall returns |\n| `recall.bm25_weight` | 0.7 | BM25 vs vector mix (1.0 = pure BM25) |\n| `recall.ppr_enabled` | **true** | Multi-hop graph diffusion, gated by intent |\n| `recall.keyed_fact_boost` | 0.35 | How hard personal-attr facts win on personal queries |\n| `recall.rerank` | false | Always-on cross-encoder (regresses LoCoMo, keep off) |\n| `embedding.model` | `paraphrase-multilingual-MiniLM-L12-v2` | The vector model |\n| `graph.extractor` | `regex` | `regex` / `spacy` / `llm:claude` / `llm:ollama` / `llm:codex` |\n| `mcp.record_batch_async` | true | Fire-and-forget writes (sub-ms return) |\n| `agent.active_mode` | false | Proactive logging in `pmb connect --active` |\n| `agent.apply_lessons` | true | Agent surfaces lessons before acting |\n| `agent.log_decisions` | true | Auto-log \"we chose X over Y\" |\n| `agent.log_lessons` | true | Auto-log \"we always/never do X\" |\n| `dedup.enable` | true | All four dedup layers |\n| `decay.factor_per_day` | 0.985 | Importance half-life |\n| `consolidate.auto_trigger` | false | Run the sleep-pass automatically |\n| `chat.model` | `haiku` | Default model for `pmb-chat` |\n\nPro tier (`pmb config list --pro`) is where you go to tweak the\nrecall scoring weights (`recall.causation_boost`, `recall.arc_boost`,\n`recall.ppr_alpha`), reranker internals (`recall.rerank_top_n`,\n`recall.rerank_close_epsilon`), vocab mining\n(`recall.auto_vocab_*`), dedup thresholds (`dedup.cosine_high`),\nconsolidate sleep heuristics, or experimental flags\n(`recall.pamvr_enabled`, `recall.adaptive_decompose`,\n`recall.typo_correction`).\n\nEvery pro-tier key still reads with `pmb config get \u003ckey\u003e` and writes\nwith `pmb config set \u003ckey\u003e` — they're hidden from `list`, not gated.\n\n---\n\n## Dashboard\n\n`pmb dashboard` opens a local web UI on port 8765. Nothing leaves\nyour machine.\n\n\u003cdiv align=\"center\"\u003e\n\u003cimg src=\"https://raw.githubusercontent.com/oleksiijko/pmb/main/docs/assets/02_dashboard.png\" width=\"780\" alt=\"PMB dashboard - Map view\"\u003e\n\u003c/div\u003e\n\nNine tabs: **Map** (entity graph, live), **Timeline** (git-graph by\nproject), **Overview**, **Entities**, **Arcs** (narrative threads),\n**Lessons** (per-rule follow-rate, dead-lesson detection),\n**Duplicates** (inline merge), **Performance** (per-tool latency),\n**Recall** (debug ranker).\n\n---\n\n## Hooks — memory that doesn't wait to be asked\n\nThe hard part of agent memory isn't storing — it's getting the agent to\n*use* what's stored. Soft instructions in a rules file get skipped. So\nPMB wires four hooks at the protocol level (`pmb hooks install\nclaude-code`), and each removes a dependency on the model remembering to\nact:\n\n- **UserPromptSubmit → auto-recall.** Every message is classified (regex,\n  multilingual, sub-ms) and the matching memory is fetched *for* the\n  agent — lessons, past decisions, recall hits, project overview — and\n  injected before the model thinks. The agent never has to decide to call\n  `recall`. Trivial messages inject nothing.\n- **PostToolUse → ambient observe.** Every tool the agent runs is appended\n  to a lightweight action journal (`pmb track-action` — a single SQLite\n  INSERT, no model, no vectors). Reads and `ls` are filtered out; edits,\n  tests and commits are kept. This is the raw material the Stop hook turns\n  into a memory if the agent never journals its own work.\n- **SessionStart → session-restore.** When the context window compacts,\n  the agent normally forgets what it just did. This hook rebuilds \"where\n  you left off\" from what the session recorded — decisions, completed\n  work, lessons, open goals — so it picks the thread back up instead of\n  re-asking you.\n- **Stop → follow-through + ambient auto-write.** At turn end PMB does two\n  things. (a) *Follow-through:* it checks which surfaced lessons actually\n  showed up in what the agent did (token overlap, gated on distinctive\n  tokens) and marks them followed — *deterministically*, without the model\n  self-reporting. (b) *Ambient auto-write:* if the agent did NOT call a\n  `record_*` tool this turn, it synthesizes one activity entry from the\n  observed actions, so real work is captured even when the agent stays\n  silent. See **Ambient memory** below.\n\nPreview any of them without an agent: `pmb auto-context \"...\"`,\n`pmb session-restore -m 180`, `pmb lesson-followcheck --dry-run`,\n`pmb autowrite --dry-run`.\n\n---\n\n## Ambient memory — the write side\n\nAuto-recall fixed the *read* side: the agent no longer has to remember to\ncall `recall`. **Ambient memory** does the same for the *write* side —\nthe memory journals the agent's work even when it forgets `record_batch`:\n\n- **Coordinated — never a duplicate.** If the agent already called a\n  `record_*` tool this turn, ambient stays silent; the agent's own summary\n  is richer. It only fills the gap.\n- **Outcome-scored, not churn.** A turn is journaled only if it clears a\n  quality bar driven by *results* — tests passed, a failure got fixed, a\n  deploy/migrate ran, the breadth of edits — not by how many files were\n  touched alone. Two mechanical edits and nothing else are dropped.\n- **Honest + reversible.** Every ambient entry is tagged\n  `source=autowrite`, shown as auto in the dashboard, and removable in one\n  command (`pmb forget-auto`). **ON by default** — capturing work the\n  agent forgot is PMB's signature; turn it off with\n  `pmb config set autowrite.enabled false`.\n- **Works on every host.** Claude Code via the PostToolUse + Stop hooks;\n  OpenAI Codex by parsing its session rollout on `agent-turn-complete`\n  (`pmb codex-notify`); MCP-only hosts (Cursor, Zed, VS Code) via a git\n  observer that watches the working tree (`pmb ambient-watch .`). See what\n  your agent supports with `pmb hooks capabilities`.\n\nSynthesis is template-based by default (instant, deterministic, no model).\nOpt into a nicer one-line summary from a local/CLI model with `pmb config\nset autowrite.synthesizer llm:ollama` (or `llm:claude` / `llm:codex`) — it\nhas a timeout and falls back to the template, so it never blocks the turn.\n\n---\n\n## Self-improvement loop\n\nEvery lesson the agent surfaces carries a `surface_id`. Follow-through is\nrecorded two ways: the agent can confirm explicitly via\n`mark_lesson_followed(surface_id, True)`, and the **Stop hook** infers it\nautomatically from recorded activity. The **Lessons tab** then shows, per\nrule:\n\n- How often it was shown to the agent\n- How often it was followed (confirmed or auto-detected)\n- `💀 DEAD` only when a rule is repeatedly **ignored** (✗ ≥ 2) — surfaced-\n  but-unconfirmed is shown as `? UNVERIFIED`, never punished as dead\n- `★ USEFUL` for rules followed ≥ 2×\n\nYou see which rules actually help and prune the ones that don't.\n\n---\n\n## Numbers\n\n| | |\n|---|---|\n| Recall p50 / p95 warm | **35 ms / 110 ms** |\n| `prepare(message)` warm | **4–16 ms** |\n| `record_batch_async` | **\u0026lt; 1 ms** |\n| MCP cold boot | **3.7 s** |\n| LoCoMo recall@10 (n=10) | **94.5 %** *(reproducible — see below)* |\n| Multilingual mega-stress top-10 (900 q) | **99.2 %** |\n\nReproduce locally:\n\n```bash\npython scripts/benchmarks/benchmark_locomo.py --n-conversations 10\npython scripts/benchmarks/mega_stress_test.py\n```\n\n---\n\n## \u003ca name=\"privacy\"\u003e\u003c/a\u003ePrivacy\n\n- 100 % offline by default. No network calls from the engine.\n- Zero telemetry. There is no call-home to add later, because there is\n  no PMB server to call.\n- Workspace = directory under `~/.pmb/\u003cname\u003e/`. Copy it to Dropbox,\n  push it to git, share it on a USB drive. Your call.\n- Secrets are auto-redacted at write time (OpenAI / Anthropic / AWS /\n  Stripe / GitHub keys; configurable).\n- Apache 2.0 licensed. Forks welcome.\n\n---\n\n## FAQ\n\n**Does PMB call an LLM?**\nOn read: never. On write: never by default. Optional: `pmb consolidate`\ncan run a local Ollama or Claude CLI pass over recent events to write\nshort reflections — opt-in, never required.\n\n**What about cost?**\n$0. There is no PMB service.\n\n**Does the agent need to know about PMB?**\nAfter `pmb connect`, the right rules are appended to `CLAUDE.md` /\n`AGENTS.md` automatically. The agent learns the 29 default MCP tools (of\n64 total — the rest are admin/sleep-mode ops, gated behind the `full`\ntool profile) and the `prepare()` pattern from those rules.\n\n**Will it slow my agent down?**\nThe MCP tools return in single-digit milliseconds for everything\nexcept `recall` (35–110 ms warm), which is below human perception.\n\n**Can two agents share one memory?**\nYes. Point them at the same workspace with `pmb connect \u003cagent\u003e\n--workspace personal`. SQLite's WAL mode + a 10 s busy-timeout (set\nautomatically) handle the concurrent writes.\n\n**What if I want to wipe a fact?**\n`pmb forget \u003culid\u003e` archives it. Archives are excluded from recall\nbut survive on disk — you can always restore. Hard-delete is\n`pmb forget \u003culid\u003e --hard`.\n\n**Will this work on Windows?**\nYes. PMB is tested on Windows 11, macOS 14, and Ubuntu 22.04. Cyrillic\npaths and console encoding are handled.\n\n**What if I leave a project?**\n`pmb workspace archive \u003cname\u003e` puts that memory on ice. `pmb workspace\nrestore \u003cname\u003e` brings it back six months later.\n\n**Does it work with PDFs / code / Markdown?**\nPDFs: `pmb index pdf paper.pdf`. Code: `pmb index project .`. Markdown:\n`pmb import markdown ~/notes/`. ChatGPT / Claude exports:\n`pmb import chatgpt path.json`.\n\n**Cold start is slow.**\nFirst recall after a fresh boot loads the embedding model (~3 s). Run\n`pmb warmup` once or just let the prewarm thread on MCP server boot do\nits job in the background.\n\n**Roadmap?**\nSee [docs/ROADMAP.md](docs/ROADMAP.md). Highlights: hosted backup via\nlitestream, optional cloud-sync (BYO bucket), tree-sitter for Rust/TS\nproject indexing, image OCR.\n\n---\n\n## Contributing\n\nIssues and PRs welcome. There's one full-time maintainer; please open\na discussion before a large change so we can align on direction.\n\n```bash\ngit clone https://github.com/oleksiijko/pmb.git \u0026\u0026 cd pmb\npython -m venv .venv \u0026\u0026 source .venv/bin/activate\npip install -e \".[dev]\"\npytest                  # full suite, ~4 minutes\npytest -k recall        # fast subset, ~12 s\n```\n\nLicense: **Apache 2.0**.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foleksiijko%2Fpmb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foleksiijko%2Fpmb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foleksiijko%2Fpmb/lists"}