{
  "markdown": "# Gr0m_Mem\n\n[![CI](https://github.com/MichaelAdamGroberman/gr0m_mem/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/MichaelAdamGroberman/gr0m_mem/actions/workflows/ci.yml)\n[![PyPI](https://img.shields.io/pypi/v/gr0m-mem.svg?logo=pypi&logoColor=white&label=PyPI)](https://pypi.org/project/gr0m-mem/)\n[![Python](https://img.shields.io/pypi/pyversions/gr0m-mem.svg?logo=python&logoColor=white)](https://pypi.org/project/gr0m-mem/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n[![Downloads](https://static.pepy.tech/badge/gr0m-mem)](https://pepy.tech/project/gr0m-mem)\n[![Code style: ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)\n[![Checked with mypy](https://www.mypy-lang.org/static/mypy_badge.svg)](https://mypy-lang.org/)\n\nZero-install persistent memory brain for **any** LLM runtime (Claude Code, Claude Desktop, Cursor, Gemini CLI, Continue, Cline, Zed, OpenAI Codex CLI, Aider, raw OpenAI / Anthropic / Gemini APIs, or a local Llama) that **stops the model from re-asking and re-deriving** across sessions.\n\n> **This is the `main` branch — the zero-install core.**\n> No ChromaDB, no Ollama, no 1 GB embedding model. Pure CPython stdlib + a couple of pure-Python wheels. `pip install gr0m-mem` and it just works.\n>\n> For semantic retrieval (ChromaDB HNSW + Ollama embeddings) switch to the [`semantic`](https://github.com/MichaelAdamGroberman/gr0m_mem/tree/semantic) branch.\n\n## Works with any LLM\n\nGr0m_Mem is universally compatible through three integration paths:\n\n- **MCP server** — Claude Code, Claude Desktop, Cursor, Gemini CLI, Continue, Cline, Zed, OpenAI Codex CLI, and any other [Model Context Protocol](https://modelcontextprotocol.io) client. Setup snippets for every major client in [`docs/integrations.md`](docs/integrations.md).\n- **CLI shell-out** — any agent framework that can run shell commands (OpenAI Agents SDK, LangChain, LlamaIndex, Aider, raw API callers): wrap `gr0m_mem wakeup`, `gr0m_mem remember`, and `gr0m_mem search` as tools.\n- **Paste-into-system-prompt** — models with no MCP and no tool calling at all: copy [`UNIVERSAL_PROMPT.md`](UNIVERSAL_PROMPT.md) into your system prompt and the model will drive the CLI via shell.\n\nThe loop-prevention protocol is the same across all three paths.\n\n## The problem\n\nClaude forgets everything when a session ends. Next time you talk to it:\n\n- It re-introduces itself.\n- It asks what you're working on — again.\n- It re-derives the same architectural decision you already locked in yesterday.\n- It loses track of which features shipped and re-suggests them.\n\nOther memory systems try to fix this with \"let an LLM decide what to remember.\" That path is expensive, loses context, and still leaks reasoning. Gr0m_Mem takes the other path: **record everything important explicitly, surface it at session start, and refuse to contradict it without you saying so.**\n\n## How it fixes the loop\n\nFour tools (and two Claude Code hooks) are the entire product:\n\n| When | Tool | Effect |\n|---|---|---|\n| Session start | `mem_wakeup` | Returns a token-budgeted snapshot of identity / preferences / projects / decisions / open questions. Claude inlines it and stops re-introducing. |\n| After a decision | `mem_record_decision` | Persists the decision + rationale against a subject. |\n| Before asking a familiar question | `mem_recall_decisions` | Retrieves prior decisions on that subject. If any exist, Claude uses them instead of re-asking. |\n| Learning anything durable | `mem_remember` | Stores a preference, project, milestone, context fact, or open question. |\n\nThe plugin's Stop and PreCompact hooks flush a milestone after every session and before every context compaction, so nothing high-value is lost to `/clear` or window compression. Session ids are whitelisted (`tr -cd 'a-zA-Z0-9_-'`) before any path touch — the shell-injection bug MemPalace had to patch (Issue #110) is fixed by design here.\n\n## Zero-install promise\n\n`pip install gr0m-mem` always produces a working brain. The main branch has exactly one backend:\n\n- **`sqlite_fts`** — SQLite FTS5 BM25 full-text search. Ships with CPython's stdlib `sqlite3` on every mainstream platform. No compiled extras, no embedding model, no Ollama, no network. Lexical-only, but `mem_wakeup` + `mem_record_decision` don't care about the backend — they use their own SQLite table.\n\nRun `gr0m_mem doctor` to verify.\n\n### Want semantic retrieval too?\n\nSwitch to the [`semantic`](https://github.com/MichaelAdamGroberman/gr0m_mem/tree/semantic) branch. It adds two more backends with auto-selection:\n\n- **`chromadb`** — HNSW cosine over ChromaDB, best retrieval quality\n- **`sqlite_vec`** — pure-Python cosine over SQLite rows, using Ollama for embeddings\n\nBoth require either the `chromadb` optional extra or a running Ollama with `mxbai-embed-large` (~1 GB). The semantic branch is a drop-in replacement — same tools, same API, richer retrieval.\n\n## Also in the box\n\n- **Temporal knowledge graph** with mandatory `as_of` filtering. `TemporalEdge` carries `valid_from` / `valid_to`, SQLite persistence with partial indexes on `valid_to IS NULL`, and `active_view()` that refuses to run without an explicit temporal decision. The `FactChecker` runs on every `add_triple` and rejects contradictions in strict mode (the thing MemPalace's `fact_checker.py` advertised but never wired).\n- **Per-corpus isolation.** Every corpus is its own FTS5 table — documents from different projects are never mixed. All tools require an explicit `corpus` argument; there is no default tenant.\n- **Reproducible benchmarks.** The loop-prevention benchmark (8 scenarios, 15 probes) runs in CI on every push and must stay at 100%. First committed result: [`benchmarks/results/2026-04-08-loop-prevention.json`](benchmarks/results/2026-04-08-loop-prevention.json).\n\n## Install\n\n### As a Claude Code plugin (preferred)\n\n```bash\nclaude plugin marketplace add MichaelAdamGroberman/gr0m_mem\nclaude plugin install --scope user gr0m_mem\n```\n\nThe plugin registers the MCP server plus the Stop / PreCompact hooks in one step.\n\n### From PyPI\n\n```bash\npip install gr0m-mem              # zero-install core (this branch)\npip install \"gr0m-mem[tokens]\"    # + real tiktoken token counts\n```\n\nThen point your MCP client at `python -m gr0m_mem.mcp_server`.\n\n## Quick start\n\n```bash\ngr0m_mem doctor\ngr0m_mem remember --kind identity --text \"Michael, software engineer, macOS\"\ngr0m_mem remember --kind preference --text \"terse responses, no trailing summaries\"\ngr0m_mem wakeup --tokens 200\n```\n\nNow open Claude Code. It calls `mem_wakeup` at session start and sees you before the first message.\n\n## What it actually looks like\n\nReal, unedited terminal output from a fresh install on macOS:\n\n### `gr0m_mem doctor`\n\n```console\n$ gr0m_mem doctor\ngr0m_mem 0.1.0 (main branch — zero-install core)\n  python:       3.12.12 (/Users/michaelgroberman/Gr0m_Mem/.venv/bin/python)\n  mcp sdk:      installed\n  backend:      sqlite_fts\n    reason:     main branch ships only the SQLite FTS5 backend — no Ollama,\n                no chromadb, no downloads.\n  ollama:       not needed on this branch\n  kg stats:     {'total': 0, 'active': 0, 'closed': 0}\n  wakeup stats: {'total': 0}\n  fts.db:       ~/.gr0m_mem/fts.db\n  graph.db:     ~/.gr0m_mem/graph.db\n  wakeup.db:    ~/.gr0m_mem/wakeup.db\n```\n\n### Recording a few facts and a decision\n\n```console\n$ gr0m_mem remember --kind identity --text \"Michael, software engineer on macOS\"\nremembered: d5b976ce-7832-4e61-8323-d08cd56d9177 (identity) Michael, software engineer on macOS\n\n$ gr0m_mem remember --kind preference --text \"terse responses, no trailing summaries\"\nremembered: 3f28a0be-78f4-4fae-ac71-4e6db6818f03 (preference) terse responses, no trailing summaries\n\n$ python -c \"\n> from gr0m_mem.brain import Brain\n> from gr0m_mem.config import Config\n> b = Brain(Config.from_env())\n> b.wakeup.record_decision(\n>     subject='backend',\n>     decision='sqlite_fts is the zero-dep default',\n>     rationale='pip install gr0m-mem must never fail',\n> )\n> b.close()\n> \"\n```\n\n### `gr0m_mem wakeup --tokens 200` — what Claude sees at session start\n\n```console\n$ gr0m_mem wakeup --tokens 200\n{\n  \"scope\": \"global\",\n  \"token_budget\": 200,\n  \"tokens_used\": 50,\n  \"facts_included\": 3,\n  \"facts_total\": 3,\n  \"text\": \"## IDENTITY\\n- Michael, software engineer on macOS\\n\\n## PREFERENCE\\n- terse responses, no trailing summaries\\n\\n## DECISION\\n- backend: sqlite_fts is the zero-dep default (pip install gr0m-mem must never fail)\"\n}\n```\n\nThe agent inlines the `text` field at the top of every conversation and stops re-asking who you are.\n\n## Requirements\n\n- **CPython 3.10, 3.11, or 3.12.** 3.13+ blocked until chromadb and the MCP SDK publish compatible wheels (affects the `semantic` branch; not an issue here).\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n\n## Contact\n\nMaintained by **Michael Adam Groberman**.\n\n- **GitHub**: [@MichaelAdamGroberman](https://github.com/MichaelAdamGroberman)\n- **LinkedIn**: [michael-adam-groberman](https://www.linkedin.com/in/michael-adam-groberman/)\n\nFor security reports, use GitHub private vulnerability advisories (see [SECURITY.md](SECURITY.md)) — **do not** use LinkedIn DMs for sensitive disclosures.\n",
  "bytes": 9302,
  "sha": "ff1aec1ee876dc3c73a595c2d7a7a36b2978cb73ea955651d2b740d308170011",
  "repo_slug": "michaeladamgroberman/gr0m_mem",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/plg_michaeladamgroberman_gr0m_mem_gr0m_mem_350c3337/readme"
}