{"id":50998850,"url":"https://github.com/welikecode/mint-mory","last_synced_at":"2026-06-22T14:00:50.782Z","repository":{"id":365861719,"uuid":"1273717015","full_name":"WeLikeCode/mint-mory","owner":"WeLikeCode","description":"Typed, graph-linked, self-consolidating memory for LLM agents — single-file SQLite, with MCP/CLI/HTTP. ’Member or die!","archived":false,"fork":false,"pushed_at":"2026-06-21T08:58:10.000Z","size":905,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-06-21T13:03:49.902Z","etag":null,"topics":["agent-memory","agents","embeddings","knowledge-graph","llm","local-first","mcp","memory","python","rag","sqlite","vector-search"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/WeLikeCode.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":"ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-06-18T19:58:39.000Z","updated_at":"2026-06-21T08:58:14.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/WeLikeCode/mint-mory","commit_stats":null,"previous_names":["welikecode/mint-mory"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/WeLikeCode/mint-mory","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WeLikeCode%2Fmint-mory","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WeLikeCode%2Fmint-mory/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WeLikeCode%2Fmint-mory/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WeLikeCode%2Fmint-mory/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/WeLikeCode","download_url":"https://codeload.github.com/WeLikeCode/mint-mory/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WeLikeCode%2Fmint-mory/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34651752,"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-22T02:00:06.391Z","response_time":106,"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":["agent-memory","agents","embeddings","knowledge-graph","llm","local-first","mcp","memory","python","rag","sqlite","vector-search"],"created_at":"2026-06-20T12:03:55.801Z","updated_at":"2026-06-22T14:00:50.729Z","avatar_url":"https://github.com/WeLikeCode.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# MintMory\n\n[![CI](https://github.com/WeLikeCode/mint-mory/actions/workflows/ci.yml/badge.svg)](https://github.com/WeLikeCode/mint-mory/actions/workflows/ci.yml)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n[![Python 3.12+](https://img.shields.io/badge/python-3.12%2B-blue.svg)](https://www.python.org/)\n\n**Typed, graph-linked, self-consolidating memory for LLM agents — in a single SQLite file.**\n\nMintMory gives an agent a long-term memory that is *typed* (every memory has a\ncategory), *linked* (memories connect through a concept graph), *searchable*\n(hybrid keyword + substring + vector), and *self-improving* (a background\n\"dreaming\" pass consolidates, links, summarises, and resolves contradictions).\nIt is local-first and dependency-light: no external vector database, no required\nmodel downloads, no cloud. One `.db` file holds everything.\n\nThe data model is inspired by the Palantir Foundry Ontology: knowledge is most\nuseful when it is typed, linked, and queryable — not stored as opaque blobs.\n\n---\n\n## Highlights\n\n- **One core, three transports.** The same domain logic is exposed as a **CLI**\n  (Typer), an **MCP server** (for Claude Code, Cursor, Open WebUI, …), and an\n  **HTTP API** (FastAPI).\n- **Hybrid search.** FTS5 keyword (BM25) + FTS5 **trigram substring** + optional\n  **vector** similarity, fused with Reciprocal Rank Fusion and relevance-normalised.\n- **Pure-Python by default.** The default embedder is an in-process feature-hashing\n  embedder — no PyTorch, no network. Swap in `sentence-transformers`, Ollama, or\n  OpenAI embeddings via an extra when you want them.\n- **Typed ontology.** 8 memory categories and 12 typed concept-link relationships.\n- **Dreaming.** Idempotent background consolidation: anomaly detection, concept\n  linking (hub-aware pruning), LLM summaries, contradiction resolution, archival,\n  rehabilitation. The LLM tier is optional and off by default.\n- **Agent-supplied summaries.** An alternative to the LLM-backed dreaming path:\n  call `summary_jobs` (MCP / CLI / HTTP) to get the concepts that need\n  summarising, write each summary yourself (you are the LLM), and send it back\n  with `summary_put`. No `MINTMORY_LLM_*` backend required — works with\n  `MINTMORY_LLM_PROVIDER=none`.\n- **Agent-supplied image understanding (G5).** Close the image-description gap\n  without a vision backend: call `image_jobs` to get the indexed raster images\n  that still need a description, look at each (via its `path` or inline base64\n  for online-only files), write one combined description blob, and store it with\n  `image_caption_put`. SVG text is extracted automatically (pure-Python, no model).\n  Proprietary formats (`.psd`, `.xd`, …) remain metadata-only. Optional `[image]`\n  / `[ocr]` extras; `ocr` is a future stub.\n- **Automated LLM vision captioning.** Set `MINTMORY_VISION_PROVIDER=llm` to\n  caption raster images server-side via an OpenAI-compatible vision model (Ollama\n  `llava`, LM Studio, hosted endpoint). `index-tree --vision` then captions inline\n  during the walk; `mintmory vision-run` / `vision_run` (MCP) /\n  `POST /images/caption-run` (HTTP) caption already-indexed pending images without\n  re-walking. No new required dependency — reuses stdlib `urllib` from `core/llm.py`.\n  `agent` stays the default (zero behaviour change). `ocr` stays a stub.\n- **Personal notes.** First-class user-authored \"remember this\" notes that are\n  authoritative, anchorable to other memories, time-aware, and protected from\n  auto-archival.\n- **Document \u0026 folder ingestion.** Bulk-ingest files (PDF/DOCX/XLSX/PPTX via the\n  optional `docs` extra) and recurrently index a directory tree — including\n  cloud/online-only folders, indexed by metadata without downloading.\n- **Single file.** SQLite + `sqlite-vec` + FTS5. Back it up by copying one file.\n\n---\n\n## Install\n\nMintMory uses [uv](https://docs.astral.sh/uv/). Clone and sync:\n\n```bash\ngit clone https://github.com/WeLikeCode/mint-mory.git\ncd mint-mory\nuv sync                 # core + CLI + MCP + API\nuv sync --extra docs    # optional: PDF/DOCX/XLSX/… ingestion (markitdown)\nuv sync --extra local   # optional: local sentence-transformers embeddings\n```\n\nRequires Python 3.12+.\n\n---\n\n## Quickstart\n\n### CLI\n\n```bash\nexport MINTMORY_DB=~/.mintmory/memories.db\n\nmintmory add \"The parking integration uses OAuth PKCE\" --category fact\nmintmory note \"Remember the prod gateway rotates certs monthly\" --about \"gateway\"\nmintmory search \"oauth gateway\"\nmintmory ingest ./docs --glob \"*.md,*.pdf,*.docx\"     # bulk ingest (needs the docs extra for binaries)\nmintmory dream --full                                  # consolidate\nmintmory doctor                                        # one-shot health check\n```\n\n### MCP (e.g. Claude Code / Cursor)\n\n```jsonc\n{\n  \"mcpServers\": {\n    \"mintmory\": {\n      \"command\": \"uv\",\n      \"args\": [\"run\", \"--project\", \"/path/to/mint-mory\", \"mintmory-mcp\"],\n      \"env\": { \"MINTMORY_DB\": \"/path/to/your/memories.db\" }\n    }\n  }\n}\n```\n\nTools exposed: `memory_add`, `memory_search`, `memory_get`, `memory_archive`,\n`memory_stats`, `memory_dream`, `session_feedback`, `summary_list`,\n`summary_get`, `summary_jobs`, `summary_put`, `memory_note`, `notes_list`,\n`image_jobs`, `image_caption_put`, `vision_run`.\n\n### HTTP API\n\n```bash\nmintmory serve --port 8080      # FastAPI + OpenAPI docs at /docs\n```\n\n### Multiple agents, one memory\n\nSeveral agents can share one MintMory instance — either as **one MCP process per\nagent against a shared `.db`** (same machine), or as **a single shared server**\n(HTTP REST or MCP-over-SSE) for networked / many-agent setups. Concurrent access\nvia MCP is supported in both forms. See **[`docs/multi-agent.md`](docs/multi-agent.md)**\nfor the topologies, discovery, and concurrency tuning.\n\n---\n\n## Architecture\n\n```\n        CLI (Typer)        MCP (FastMCP)        HTTP (FastAPI)\n              \\                  |                   /\n               \\                 |                  /\n                =========  mintmory.core  =========\n                 types · storage · search · dreaming\n                 embedder · scoring · notes · config\n                              |\n                   one SQLite .db file\n            (sqlite-vec + FTS5 porter + FTS5 trigram)\n```\n\n- **Storage:** a single SQLite database. Vectors via `sqlite-vec`; keyword search\n  via FTS5 (`porter`); substring search via a second FTS5 (`trigram`) index.\n- **Search:** keyword (BM25) + trigram substring + optional vector, fused with RRF,\n  relevance min-max normalised, then nudged by usefulness/recency.\n- **Dreaming:** six idempotent steps run on demand (`mintmory dream`) — safe to run\n  repeatedly; the LLM-backed steps are skipped when no LLM tier is configured.\n\nSee [`AGENTS.md`](AGENTS.md) for the deep design contract and\n[`docs/`](docs/) for ADRs, the OpenAPI spec, and experiment records.\n\n---\n\n## Configuration\n\nEverything is environment-driven (pydantic-settings); **every default reproduces\nsensible local-first behaviour**. Common knobs:\n\n| Variable | Default | Meaning |\n|---|---|---|\n| `MINTMORY_DB` | `~/.mintmory/memories.db` | database path |\n| `MINTMORY_EMBED_PROVIDER` | `hashing` | `hashing` (pure-Python) / `local` / `ollama` / `openai` |\n| `MINTMORY_LLM_PROVIDER` | `none` | enable summaries + contradiction resolution (`ollama`/`openai`) |\n| `MINTMORY_LLM_BASE_URL` / `_MODEL` / `_API_KEY` | — | OpenAI-compatible LLM tier |\n| `MINTMORY_NOTE_BONUS` | `0.05` | ranking boost for user notes |\n| `MINTMORY_SQLITE_BUSY_TIMEOUT_MS` | `5000` | how long a writer waits for a lock (multi-agent); `0` = fail fast |\n\nThe LLM tier is OpenAI-compatible, so it works with Ollama, LM Studio, vLLM, or a\nhosted endpoint. It is **off by default** (fully offline).\n\n**Agent-supplied summaries** do not require an LLM tier. Use\n`mintmory summary-jobs` / `summary_jobs` (MCP) / `GET /summaries/jobs` to get\nthe pending L3 summary work-list, write the text, and return it with\n`mintmory summary-put` / `summary_put` / `PUT /summaries/{concept}`. The\nselection policy (`MINTMORY_SUMMARY_*` settings, stoplist) is respected\nregardless of which path writes the summary.\n\n---\n\n## Image Understanding (agent-supplied and automated vision, G5)\n\nMintMory supports two vision paths — agent-supplied (default) and automated\nserver-side (`llm`). Both use the same persistence layer (`image_caption_put`,\nthe `image_jobs` work-list, the no-drift guarantee) and the same `[image]` extra\nfor optional Pillow downscaling.\n\n### Agent-supplied path (default, `provider=agent`)\n\nThe agent that already holds the image in context is the vision capability. The\nloop works identically over all three transports:\n\n1. **Index the tree.** Run `mintmory index-tree --vision /path/to/folder`. SVG files\n   have their embedded `\u003ctext\u003e` / `\u003ctitle\u003e` / `\u003cdesc\u003e` content extracted automatically\n   (pure stdlib, no model). Raster images (`.jpg`, `.png`, `.gif`, `.webp`, …) are\n   queued as agent jobs and recorded in the manifest with `index_mode=vision`.\n   Proprietary formats (`.xd`, `.vsdx`, `.psd`, …) are skipped and flagged\n   (`vision-skipped`) — they remain metadata-only.\n\n2. **Get the work-list.** Call `image_jobs` (MCP), `mintmory image-jobs` (CLI), or\n   `GET /images/jobs` (HTTP). Only raster images that do NOT yet have an active\n   description are returned by default (`include_all=False`). Each job carries the\n   `file_id`, `path`, `rel`, `mime`, `size`, and `online_only` flag. For\n   online-only (cloud-placeholder) images, or when `include_bytes=True`, the\n   response also includes an inline base64 `image_b64` payload within the configured\n   size cap (`MINTMORY_VISION_MAX_IMAGE_MB`, default 8 MB); oversized images set\n   `oversized=True` and omit the payload so the agent can fall back to `path`.\n\n3. **Describe each image.** You (the calling agent) are the vision-capable model.\n   Write one combined description blob: what the image depicts plus any legible text.\n\n4. **Store the description.** Call `image_caption_put` (MCP), `mintmory\n   image-caption-put` (CLI), or `PUT /images/{file_id}` (HTTP). MintMory persists\n   the description as a searchable `context` memory ANNOTATES-linked to the image\n   file-record and archives any prior description (no-drift: the image drops from the\n   default `image_jobs` work-list immediately).\n\n**No vision backend is required for the `agent` path** — it is the default.\n\n### Automated LLM vision path (`MINTMORY_VISION_PROVIDER=llm`)\n\nSet `MINTMORY_VISION_PROVIDER=llm` to caption raster images automatically via an\nOpenAI-compatible vision model (e.g. Ollama `llava`, LM Studio, a hosted endpoint).\n\n**Inline during indexing** — `mintmory index-tree --vision /path/to/folder`\ncaptions each raster as it is encountered (instead of queuing an agent job).\nPer-image failures (network/timeout/empty response) are logged and skipped; one\nbad image never aborts the walk.\n\n**Caption already-indexed images** (without re-walking the tree):\n\n```bash\nmintmory vision-run                      # CLI — describes pending images\nmintmory vision-run --limit 20           # cap to 20 images\nmintmory vision-run --budget 100         # 100 MB download budget for online-only\nmintmory vision-run --all                # re-caption ALL images (not just pending)\n```\n\nOr via MCP: call `vision_run` (with optional `limit`, `budget_mb`, `include_all`).\nOr via HTTP: `POST /images/caption-run` (body: `{\"limit\":0,\"budget_mb\":0,\"include_all\":false}`).\n\nWith `provider=agent` (the default), `vision-run` / `vision_run` /\n`POST /images/caption-run` are no-ops (they return `{\"provider\":\"agent\",\"described\":0}`)\n— zero behaviour change unless you opt in.\n\n**No new required dependency.** The vision HTTP call reuses the stdlib `urllib`\nmachinery already in `core/llm.py` (OpenAI-compatible `/chat/completions` shape\nwith a multimodal `image_url` content part). No `openai` SDK.\n\n**Optional extras:**\n\n```bash\nuv sync --extra image   # Pillow: auto-downscale large embedded payloads (lazy import)\nuv sync --extra ocr     # pytesseract: reserved for the future 'ocr' vision provider\n```\n\n**Relevant env knobs** (`MINTMORY_VISION_*`):\n\n| Variable | Default | Meaning |\n|---|---|---|\n| `MINTMORY_VISION_PROVIDER` | `agent` | `agent` (default) / `llm` (automated server-side) / `ocr` (stub, future) |\n| `MINTMORY_VISION_BASE_URL` | `http://localhost:11434/v1` | Base URL for the vision model endpoint (`llm` path only) |\n| `MINTMORY_VISION_MODEL` | `llava` | Vision model name (`llm` path only) |\n| `MINTMORY_VISION_API_KEY` | — | Bearer API key for the vision endpoint (omitted if not set) |\n| `MINTMORY_VISION_VISION_MAX_TOKENS` | `512` | Max tokens in the caption response (`llm` path only) |\n| `MINTMORY_VISION_VISION_TIMEOUT_S` | `120.0` | Per-image HTTP timeout in seconds (1–600; `llm` path only) |\n| `MINTMORY_VISION_VISION_TEMPERATURE` | `0.0` | Sampling temperature for the vision model (0.0–2.0; `llm` path only) |\n| `MINTMORY_VISION_VISION_PROMPT` | `\"\"` | Override the default caption prompt (empty = use built-in default) |\n| `MINTMORY_VISION_MAX_IMAGE_MB` | `8.0` | Max on-disk size to embed as base64 (0 = no cap) |\n| `MINTMORY_VISION_DOWNSCALE_MAX_PX` | `1568` | Longest-edge downscale target for embedded payloads (needs `[image]`; 0 = off) |\n| `MINTMORY_VISION_MAX_DOWNLOAD_MB` | `200.0` | Budget for downloading online-only image bytes (shared with `--max-download-mb`) |\n\n---\n\n## Development\n\n```bash\nuv run pytest          # tests (coverage gate ≥ 80%)\nuv run ruff check .    # lint\nuv run ruff format .   # format\nuv run mypy packages   # strict type-check\n```\n\nChanges are designed spec-first under [`openspec/`](openspec/): each change has a\n`proposal.md`, a frozen `design.md`, `tasks.md`, and capability spec deltas. See\n[`CONTRIBUTING.md`](CONTRIBUTING.md).\n\n---\n\n## License\n\n[MIT](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwelikecode%2Fmint-mory","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwelikecode%2Fmint-mory","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwelikecode%2Fmint-mory/lists"}