{"id":50747486,"url":"https://github.com/deeflect/dory","last_synced_at":"2026-06-10T22:30:48.467Z","repository":{"id":352704044,"uuid":"1204407213","full_name":"deeflect/dory","owner":"deeflect","description":"One memory layer for every AI agent. Local-first, markdown source of truth, and CLI/HTTP/MCP native. Your agent forgot who you are. Again. Dory fixes that.","archived":false,"fork":false,"pushed_at":"2026-06-08T20:42:05.000Z","size":2235,"stargazers_count":8,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-08T22:23:00.651Z","etag":null,"topics":["agents","ai-agents","claude-code","codex","docker","fastapi","knowledge-graph","llm","local-first","markdown","mcp","memory","memory-palace","model-context-protocol","obsidian","python","rag","semantic-search","sqlite","vector-search"],"latest_commit_sha":null,"homepage":"https://dory.deeflect.com","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/deeflect.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"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-04-08T01:33:00.000Z","updated_at":"2026-06-08T20:42:10.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/deeflect/dory","commit_stats":null,"previous_names":["deeflect/dory"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/deeflect/dory","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deeflect%2Fdory","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deeflect%2Fdory/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deeflect%2Fdory/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deeflect%2Fdory/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/deeflect","download_url":"https://codeload.github.com/deeflect/dory/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deeflect%2Fdory/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34174148,"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-10T02:00:07.152Z","response_time":89,"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":["agents","ai-agents","claude-code","codex","docker","fastapi","knowledge-graph","llm","local-first","markdown","mcp","memory","memory-palace","model-context-protocol","obsidian","python","rag","semantic-search","sqlite","vector-search"],"created_at":"2026-06-10T22:30:47.905Z","updated_at":"2026-06-10T22:30:48.451Z","avatar_url":"https://github.com/deeflect.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n\u003cimg src=\"https://media3.giphy.com/media/v1.Y2lkPTc5MGI3NjExa2NjdHJ1NzBmbXc2d3N5eDYzMnh3MDg2YnA2Y2ZwdWQ3cXRydWpwaCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/CJywPvSt4JE0E/giphy.gif\" alt=\"Dory — just keep swimming\" width=\"480\" /\u003e\n\n# 🐟 Dory\n\n**One memory layer. Every agent. Local by default.**\n\n[![Python 3.12+](https://img.shields.io/badge/python-3.12%2B-blue)](https://www.python.org/)\n[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)\n[![Built with uv](https://img.shields.io/badge/built%20with-uv-orange)](https://docs.astral.sh/uv/)\n[![MCP](https://img.shields.io/badge/MCP-native-purple)](https://modelcontextprotocol.io/)\n[![Status](https://img.shields.io/badge/status-building-yellow)]()\n\n*Your agent forgot who you are. Again. Dory fixes that.*\n\n\u003c/div\u003e\n\n---\n\n## The problem\n\nEvery AI agent you use keeps its own half-memory.\n\n- Claude remembers one slice.\n- Codex keeps another.\n- opencode writes to yet another folder.\n- OpenClaw and Hermes park sessions somewhere else entirely.\n- The next model still asks what you're building, what you prefer, and what already happened.\n\nYou end up re-explaining yourself on loop. Decisions get lost. Project state goes stale. No memory actually follows you across tools.\n\n## What Dory is\n\nA **local-first memory daemon** that gives every agent the same brain.\n\nMarkdown is the source of truth. SQLite is a disposable sidecar. Agents read and write through a narrow API — `wake`, `search`, `get`, `memory-write`, `link` — so Claude, Codex, opencode, OpenClaw, Hermes, and anything with HTTP or MCP share one memory substrate while keeping their own personality.\n\n\u003e Dory isn't trying to make every agent identical. It's giving them the same memory so they can act like they share a brain.\n\n## Quickstart\n\n```bash\ngit clone \u003cdory-repo-url\u003e\ncd dory\nuv sync --frozen\nmkdir -p data/corpus\nexport DORY_CORPUS_ROOT=\"$PWD/data/corpus\"\nexport DORY_INDEX_ROOT=\"$PWD/.dory/index\"\nexport DORY_AUTH_TOKENS_PATH=\"$PWD/.dory/auth-tokens.json\"\nuv run dory init\n```\n\nTry it:\n\n```bash\nuv run dory memory-write \"Atlas is the active focus this week.\" \\\n  --subject atlas --kind decision --force-inbox\n\nuv run dory search \"active focus\"\nuv run dory wake --profile coding --budget 1200\nuv run dory wake --profile coding --project atlas\n```\n\nServe it over HTTP:\n\n```bash\nuv run dory-http --corpus-root data/corpus --index-root .dory/index \\\n  --host 127.0.0.1 --port 8766\n```\n\nOr run it as a durable container:\n\n```bash\ncp .env.example .env\nmkdir -p data/corpus\ndocker compose up -d --build\n```\n\nDocker binds HTTP to `127.0.0.1:8766` by default. Only set `DORY_HTTP_BIND=0.0.0.0` behind a trusted LAN, VPN, reverse proxy, or firewall.\n\nCompose builds with `network: host` so dependency installs use the host resolver on private DNS setups. If runtime containers cannot resolve external hosts, set `DORY_DOCKER_DNS_SERVERS` in `.env`. Raw `GEMINI_API_KEY` / `OPENROUTER_API_KEY` values are passed through as compatibility aliases for providers that expect those names.\n\nFull walkthrough → [docs/getting-started.md](docs/getting-started.md)\n\n## The loop\n\n```text\nwake  →  search  →  get  →  memory-write  →  link\n```\n\n- **wake** — bounded hot context once at session start, after compaction, or at a real task switch\n- **project wake** — `wake --project \u003cname\u003e` adds a matching `projects/\u003cslug\u003e/state.md` page by slug, title, or alias\n- **search** — hybrid search across durable memory and session evidence\n- **get** — exact markdown, with hashes and metadata\n- **memory-write** — semantic writes (facts, preferences, decisions, project state)\n- **link** — backlinks, neighbors, graph structure\n\nMarkdown stays editable by hand. Open it in Obsidian, diff it in git, inspect it in the browser wiki, or let agents update it through guarded write APIs. You always have a human-readable audit trail.\n\n## What's in the box\n\n| Surface | What it does |\n|---|---|\n| **CLI** | `uv run dory` — init, search, memory-write, research, ops jobs, migrations |\n| **HTTP daemon** | `/v1/wake`, `/v1/active-memory`, `/v1/search`, `/v1/research`, `/v1/get`, `/v1/write`, `/v1/memory-write`, `/v1/purge`, `/v1/session-ingest`, `/v1/link`, `/v1/status`, `/v1/stream`, `/metrics`, `/wiki` |\n| **Native MCP** | `uv run dory-mcp --mode stdio` or `--mode tcp` |\n| **MCP bridge** | HTTP-backed bridge for remote daemons |\n| **Hermes provider** | `plugins/hermes-dory/` |\n| **OpenClaw package** | `packages/openclaw-dory/` |\n| **Browser wiki** | Read/edit the corpus from a browser (auth-gated) |\n\n## Deployment shapes\n\n- **Repo-local** — development, experiments, throwaway corpora.\n- **Same-host daemon** — one workstation, all local agents hit `127.0.0.1`.\n- **Docker service** — durable always-on daemon, bind-mounted markdown corpus.\n- **Private remote host** — LAN box, VPN host, or VPS reachable over HTTP by multiple machines.\n\nThe corpus, index, auth tokens, public URL, and model provider keys are environment-specific. Keep them out of the public repo.\n\n## Stack\n\n- **Language** — Python (uv + pyproject)\n- **Storage** — Markdown source of truth · SQLite (FTS5, graph edges, embedding cache, chunk vectors, session evidence)\n- **Embeddings** — Gemini by default, or an OpenAI-compatible local/LAN embedding endpoint with `DORY_EMBEDDING_PROVIDER=local`\n- **Dreaming \u0026 maintenance LLM** — Gemini 3.1 Flash via OpenRouter\n- **Active-memory LLM** — optional · OpenRouter or any OpenAI-compatible local/LAN endpoint (Ollama, LM Studio, vLLM). The runtime default is OpenRouter when configured; `.env.example` sets it to `off` for deterministic retrieval-only installs\n- **Auth** — bearer tokens via `.dory/auth-tokens.json`; `DORY_ALLOW_NO_AUTH=true` for local dev only\n\n## Design influences\n\nDory is a composite of patterns that already worked:\n\n- **[Karpathy's LLM Wiki](https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f)** — a persistent markdown layer that compounds instead of forcing rediscovery. Dory keeps that, but generates the wiki from a structured memory core.\n- **[gbrain](https://github.com/garrytan/gbrain)** — human-readable canonical pages, source-backed evidence, entity resolution, backlinks, read-before-write discipline.\n- **[Mem0](https://github.com/mem0ai/mem0)** — scoped memory APIs, explicit add/update/delete semantics, memory ops as first-class tools instead of hidden chat history.\n- **[MemPalace](https://github.com/MemPalace/mempalace) / memory palace systems** — bounded wake-up context, local-first session storage, transcript mining, layered recall.\n- **Markdown + git** — plain files, diffs, reviews, backups, human inspection.\n\nThe goal is practical: one memory layer for all agents, with enough structure to stay useful and enough plain text to stay debuggable.\n\n## Status\n\n- **Core** — CLI, HTTP, MCP, search, and semantic writes are in-repo and covered by tests.\n- **Default runtime** — local-first. Server and corpus live wherever you check out.\n- **Corpus** — a fresh checkout ships without `core/user.md`, `core/soul.md`, `core/env.md`, `core/active.md`, or the `wiki/` tree. You populate those.\n- **Locked goals** — (1) frozen wake-up block, (2) cross-agent shared memory.\n- **Public tree** — current implementation, synthetic evals, and integration surfaces. Private planning notes stay private.\n\n## Docs\n\n| | |\n|---|---|\n| [Getting started](docs/getting-started.md) | Install, init, first wake |\n| [Agent integration](docs/agent-integration.md) | Wire up Claude, Codex, opencode, OpenClaw, Hermes |\n| [Contributing](CONTRIBUTING.md) | Development setup, validation, commit rules, PR rules |\n| [Agent guide](AGENTS.md) | Shared instructions for coding agents working in this repo |\n| [Codebase map](docs/current-state/README.md) | Where everything lives |\n| [Runtime \u0026 data flow](docs/current-state/runtime-and-data-flow.md) | How requests move through the system |\n| [Surfaces \u0026 integrations](docs/current-state/surfaces-and-integrations.md) | CLI, HTTP, MCP, providers |\n| [Operations \u0026 validation](docs/current-state/operations-and-validation.md) | Dream, maintain, reindex, migrate |\n| [Memory kernel roadmap](docs/memory-kernel/README.md) | Current roadmap for hot context, entities, observations, and evidence-backed retrieval |\n| [Ops runbook](references/runbook.md) | Day-to-day operation |\n| [Client runbook](references/client-runbook.md) | For agent integrators |\n| [Evals](eval/README.md) | Benchmarks and coverage |\n\n## Contributing\n\nContributions are welcome, but the public repo has a hard privacy boundary. Use synthetic data in docs, tests, evals, examples, and fixtures. Do not commit private corpora, raw session logs, real personal memories, direct contact details, local absolute paths, private hostnames, tokens, or `.env` files.\n\nRead [CONTRIBUTING.md](CONTRIBUTING.md) before opening a PR. The short version: use Conventional Commits, keep changes scoped, run the relevant `uv` checks, rebuild the OpenClaw plugin when TypeScript changes, and run `scripts/release/check-public-safety.py` for public docs or artifacts.\n\n## Useful entrypoints\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eCLI \u0026 search\u003c/b\u003e\u003c/summary\u003e\n\n```bash\nuv run dory                                # root command\nuv run dory init                           # new corpus\nuv run dory search \"query\"                 # hybrid search\nuv run dory memory-write \"...\" --subject x --kind decision\nuv run dory research \"What are we working on?\" --kind report\n```\n\nSet `DORY_GEMINI_API_KEY` or `GOOGLE_API_KEY` before starting HTTP/MCP or any command that embeds, searches, writes semantic memory, reindexes, or runs evals with the default Gemini provider. To use an OpenAI-compatible local/LAN embedding endpoint instead, set `DORY_EMBEDDING_PROVIDER=local` with `DORY_LOCAL_EMBEDDING_*`. Local query embeddings use `DORY_LOCAL_EMBEDDING_QUERY_INSTRUCTION` for Qwen-style retrieval prompts; set it blank to disable. LLM query planning, expansion, and reranking are opt-in via `DORY_QUERY_PLANNER_ENABLED`, `DORY_QUERY_EXPANSION_ENABLED`, `DORY_QUERY_RERANKER_ENABLED`; local reranking uses `DORY_QUERY_RERANKER_PROVIDER=local` and `DORY_LOCAL_RERANKER_*`. `DORY_QUERY_RERANKER_CANDIDATE_LIMIT` caps how many candidates are sent to the reranker per search. For Docker with a LAN/local OpenAI-compatible embedding and rerank server, run Compose with `-f docker-compose.yml -f docker-compose.local.yml`.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eHTTP \u0026 MCP\u003c/b\u003e\u003c/summary\u003e\n\n```bash\nuv run dory-http --corpus-root \u003ccorpus\u003e --index-root \u003cindex\u003e\nuv run dory-mcp --mode stdio\nuv run dory-mcp --mode tcp --host 127.0.0.1 --port 8765\n```\n\nExample MCP config: [`scripts/claude-code/mcp.example.json`](scripts/claude-code/mcp.example.json). HTTP bearer tokens: `uv run dory auth new \u003cname\u003e`. The browser wiki login also needs `DORY_WEB_PASSWORD`.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eOps jobs\u003c/b\u003e\u003c/summary\u003e\n\n```bash\nuv run dory ops dream-once        # batch dream pass (+ recall-promotion distillation)\nuv run dory ops daily-digest-once # summarize shipped sessions into digests/daily/\nuv run dory ops maintain-once     # maintenance pass\nuv run dory ops wiki-refresh-once # rebuild compiled wiki\nuv run dory ops eval-once         # eval batch\nuv run dory ops watch             # foreground corpus watcher\n```\n\nInstallers: `scripts/ops/install-dory.sh`, `install-backup-cron.sh`, `install-ops-launchd.sh`.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eLegacy corpus migration\u003c/b\u003e\u003c/summary\u003e\n\n```bash\nuv run dory --corpus-root \u003ccorpus\u003e migrate \u003clegacy-corpus\u003e\nuv run dory --corpus-root \u003ccorpus\u003e migrate --estimate --sample 25 \u003clegacy-corpus\u003e\nuv run dory --corpus-root \u003ccorpus\u003e migrate --interactive \u003clegacy-corpus\u003e\n```\n\nStages docs, normalizes to markdown evidence, classifies, extracts memory atoms, bootstraps canonical pages, writes a migration report, quarantines edge cases. Afterwards run `ops wiki-refresh-once`.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eSession ingestion\u003c/b\u003e\u003c/summary\u003e\n\nSession evidence is stored separately from durable memory. `client` and `solo` installs auto-discover local sessions via `scripts/ops/client-session-shipper.py`. The shipper keeps a local spool plus checkpoint state and polls known harness stores — no manual `--source`. Endpoint: `POST /v1/session-ingest`. `search` with `mode=\"recall\"` reads the session evidence plane directly.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eSemantic writes\u003c/b\u003e\u003c/summary\u003e\n\nPreferred write surface is semantic, not path-first.\n\n- CLI: `uv run dory memory-write \"Atlas prefers concise status notes.\" --subject atlas --kind preference`\n- HTTP: `POST /v1/memory-write`\n- MCP: `dory_memory_write`\n- OpenClaw: `memory_write`\n- Hermes: `memory_write(...)`\n\nPath-first `write` stays available for compatibility and debug flows.\n\n\u003c/details\u003e\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n\n## A note on the name\n\nNot affiliated with, endorsed by, or connected to Disney or Pixar. \"Dory\" is an affectionate nod to the fish who couldn't hold a thought — a fitting mascot for a memory daemon. The GIF is embedded from Giphy as fan reference under fair use. If any rights holder objects, open an issue and it's gone.\n\n---\n\n\u003cdiv align=\"center\"\u003e\n\n*Just keep swimming. 🐟*\n\n\u003c/div\u003e\n\n---\n\n### Built by\n\nBuilt by [Dee](https://deeflect.com) — AI Engineer \u0026 Product Designer in LA. Made this because my agents forgot who I was one too many times in a row.\n\nStar if Dory saves you from re-explaining your life every morning. [Open an issue](https://github.com/deeflect/dory/issues) if it doesn't, or if it's quietly forgetting things.\n\nNeed a memory layer (or any real product) shipped solo? [dee.agency](https://dee.agency?utm_source=dory\u0026utm_medium=readme).\n\n[deeflect.com](https://deeflect.com) · [Wikidata](https://www.wikidata.org/entity/Q138828544) · [LinkedIn](https://www.linkedin.com/in/dkargaev/) · [X](https://x.com/deeflectcom)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdeeflect%2Fdory","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdeeflect%2Fdory","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdeeflect%2Fdory/lists"}