{"id":50862156,"url":"https://github.com/nikships/gemdex","last_synced_at":"2026-06-14T22:01:17.075Z","repository":{"id":360377063,"uuid":"1249655672","full_name":"nikships/gemdex","owner":"nikships","description":"Memory layer MCP for AI coding agents — durable save/recall/update on Gemini embeddings + embedded LanceDB hybrid retrieval","archived":false,"fork":false,"pushed_at":"2026-06-12T02:56:02.000Z","size":46651,"stargazers_count":4,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-12T04:20:48.540Z","etag":null,"topics":["agent-memory","ai-coding-assistant","claude-code","cursor","developer-tools","embeddings","gemini","lancedb","mcp","memory","rag","vector-search"],"latest_commit_sha":null,"homepage":"https://gemdex-site-2026.web.app","language":"TypeScript","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/nikships.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"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},"funding":null},"created_at":"2026-05-25T23:35:52.000Z","updated_at":"2026-06-12T03:09:14.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/nikships/gemdex","commit_stats":null,"previous_names":["anand-92/gemdex","nikships/gemdex"],"tags_count":22,"template":false,"template_full_name":null,"purl":"pkg:github/nikships/gemdex","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nikships%2Fgemdex","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nikships%2Fgemdex/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nikships%2Fgemdex/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nikships%2Fgemdex/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nikships","download_url":"https://codeload.github.com/nikships/gemdex/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nikships%2Fgemdex/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34339195,"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-14T02:00:07.365Z","response_time":62,"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","ai-coding-assistant","claude-code","cursor","developer-tools","embeddings","gemini","lancedb","mcp","memory","rag","vector-search"],"created_at":"2026-06-14T22:00:57.429Z","updated_at":"2026-06-14T22:01:17.069Z","avatar_url":"https://github.com/nikships.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n\u003cimg src=\"assets/logo-wordmark.jpg\" alt=\"Gemdex — a memory layer for AI coding agents\" width=\"780\" /\u003e\n\n### A global, persistent memory layer for AI coding agents — Gemini embeddings × LanceDB × MCP\n\n[![npm version](https://img.shields.io/npm/v/gemdex-mcp?color=cf6a4c\u0026label=gemdex-mcp\u0026logo=npm)](https://www.npmjs.com/package/gemdex-mcp)\n[![npm downloads](https://img.shields.io/npm/dm/gemdex-mcp?color=cf6a4c\u0026label=downloads\u0026logo=npm)](https://www.npmjs.com/package/gemdex-mcp)\n[![GitHub stars](https://img.shields.io/github/stars/anand-92/gemdex?style=flat\u0026color=e9b949\u0026logo=github)](https://github.com/anand-92/gemdex/stargazers)\n[![License: MIT](https://img.shields.io/badge/License-MIT-7a9e7e.svg)](LICENSE)\n[![Node.js](https://img.shields.io/badge/Node.js-%E2%89%A520-7a9e7e.svg?logo=node.js\u0026logoColor=white)](https://nodejs.org/)\n[![MCP](https://img.shields.io/badge/MCP-compatible-cf6a4c)](https://modelcontextprotocol.io)\n[![Powered by Gemini](https://img.shields.io/badge/embeddings-Gemini-4285F4?logo=google)](https://ai.google.dev/)\n[![Powered by LanceDB](https://img.shields.io/badge/vector_db-LanceDB-9933ff)](https://lancedb.com/)\n\n**[⭐ Star on GitHub](https://github.com/anand-92/gemdex)** · **[📦 npm](https://www.npmjs.com/package/gemdex-mcp)** · **[💬 Discussions](https://github.com/anand-92/gemdex/discussions)** · **[🐛 Issues](https://github.com/anand-92/gemdex/issues)**\n\n\u003c/div\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"assets/gemdex-hyperframes.gif\" alt=\"Gemdex overview: global memory across agents, repos, local storage, parent-document recall, and desktop management\" width=\"100%\" /\u003e\n\u003c/p\u003e\n\n## Why Gemdex\n\n\u003e Your agent re-learns everything every session. You explained your deploy flow\n\u003e last week; today it has no idea. Gemdex gives it **durable memory** you write\n\u003e on purpose — once, recallable everywhere.\n\nA memory layer is a **deliberately written, persistent store** that is the\nsource of truth. You teach your agent something once, and it remembers forever,\nacross every repo and every session.\n\n- 🧠 **You decide what to remember** — explicit `save_memory` / `recall` /\n  `update_memory`. No silent capture, no background recall.\n- 🌍 **One global pool** — every memory is searchable from everywhere. No\n  scopes, no folders, no tags; embeddings do the disambiguation.\n- 🔎 **Sharp recall, whole answers** — hybrid semantic + BM25 over internal\n  chunks, but recall always returns the **full memory, never a fragment**.\n- 🔌 **Plug-and-play** — speaks MCP over stdio, so any compatible client\n  (Claude Code, Cursor, Codex CLI, Windsurf, Cline, Continue, Zed…) works\n  instantly.\n- 🪶 **Local by default** — use embedded LanceDB at `~/.gemdex`, or connect\n  multiple machines to a Gemdex Server running in infrastructure you own.\n- 🖥️ **Desktop manager** — a native app to browse / edit / delete / export /\n  import your memory layer.\n\n## The motivating workflows\n\n```\nDuring a session:\n  \"We just figured out how to wire up the Junie review workflow — save that to memory.\"\n\nWeeks later, a different repo:\n  \"Set up the Junie review workflow here — check your memory layer for how we do it.\"\n\nDifferent machine, different app:\n  \"Notarize and sign this build — the credentials and steps are in my memory layer.\"\n```\n\n## Quickstart (under a minute)\n\nThere's **no setup step** for the store — LanceDB is embedded and persists at\n`~/.gemdex/lance` automatically the first time you save a memory.\n\n### Wire Gemdex into your agent\n\n**Claude Code (one-command plugin install — recommended):**\n\n```bash\n/plugin marketplace add anand-92/gemdex\n/plugin install gemdex@gemdex\n```\n\nYou'll be prompted for `GEMINI_API_KEY`. Sensitive values are stored in your OS\nkeychain. The plugin ships:\n\n- the `gemdex` MCP server (no local checkout — runs via `npx -y gemdex-mcp@latest`), and\n- a `memory` skill that nudges Claude to save / recall / update **only when you\n  explicitly point at memory**.\n\nSee [`plugin/README.md`](plugin/README.md) for the full layout.\n\n**Claude Code (manual, no plugin):**\n\n```bash\nclaude mcp add gemdex \\\n  -e GEMINI_API_KEY=your-key \\\n  -- npx -y gemdex-mcp@latest\n```\n\n**Any other MCP client** (Cursor, Codex CLI, Windsurf, Cline, Continue, Zed…):\n\n```json\n{\n  \"mcpServers\": {\n    \"gemdex\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"gemdex-mcp@latest\"],\n      \"env\": {\n        \"GEMINI_API_KEY\": \"your-key\"\n      }\n    }\n  }\n}\n```\n\n### Save and recall\n\n```\nSave how we set up the Junie review workflow to memory.\n```\n\n…later, in any repo on any machine:\n\n```\nSet up the Junie review workflow here — check your memory layer.\n```\n\nDone. Your agent now has a tiny, durable knowledge store it writes on purpose\nand reads on command.\n\n### Nudge your agent to actually use it (the single biggest thing you can do)\n\n\u003e Agents won't reach for a new MCP tool on their own. Tell your agent, at the\n\u003e top of every session, that it exists and when to use it.\n\n**For Claude Code** — drop this into `CLAUDE.md` at the repo root (or\n`~/.claude/CLAUDE.md` to apply globally):\n\n```markdown\n## Memory layer (Gemdex)\n\n`gemdex` MCP exposes `save_memory`, `recall`, and `update_memory` — a global,\ndurable memory store shared across every repo and session. EXPLICIT ONLY:\n\n- `save_memory(content, title?)` when the user says remember/save to memory.\n- `recall(query, limit?)` when the user points at memory (\"check your memory\n  layer\", \"how do we usually do X\", \"where are the … credentials\"). Returns\n  full memories, never fragments.\n- `update_memory(id, content?, edits?, title?)` to revise a stored memory —\n  `edits` for a targeted find-and-replace (change part of a large memory without\n  resending it), or `content` for a full rewrite.\n\nNever auto-capture a session and never recall unprompted. There's no delete\ntool — deletion is a human action in the Gemdex desktop app. If these tools\naren't in your toolset, the MCP isn't connected.\n```\n\n**For Codex CLI, Cursor, Windsurf, Cline, Continue, Zed** — paste the same\nsnippet into your client's root instructions file (conventionally `AGENTS.md`).\n\n\u003e If you installed the Claude Code plugin, this nudge already ships as a bundled\n\u003e `memory` skill — you can skip `CLAUDE.md` and it'll still work.\n\n## The 3 MCP tools\n\n| Tool | Input | Returns | When the agent calls it |\n|------|-------|---------|-------------------------|\n| `save_memory` | `content` and/or `attachments`, `title` (optional) | new `id` + resolved title | only when told to remember/save |\n| `recall` | `query` and/or `attachments` (at least one required), `limit` (optional, ~10) | full memories ranked by relevance | only when pointed at memory |\n| `update_memory` | `id` (required); `content` **or** `edits`, `title`, `attachments` (optional — at least one required) | updated `id` + title | to revise a stored memory (`edits` = partial find-and-replace; `content` = full rewrite) |\n\nDeletion is intentionally **not** an agent tool — it's a deliberate human action\nin the desktop app. All three tools embed via Gemini. Local mode requires\n`GEMINI_API_KEY`; remote mode uses the Gemdex Server owner's key.\n\n### Multimodal attachments\n\n`save_memory` and `update_memory` accept an optional `attachments` array of\ninline media — `{ mimeType, data (base64), caption? }` — embedded into the same\nspace as text by `gemini-embedding-2`. Supported types and per-memory caps:\nPNG/JPEG images (≤ 6), MP3/WAV audio (≤ 1), MP4/MOV video (≤ 1), and PDF (≤ 1).\nEach attachment is embedded as\nits own unit; its `caption` (or the memory title) backs the keyword branch. Raw\nbytes are stored as blobs under `~/.gemdex/blobs` and round-trip through\nexport/import. Attachments require the `gemini-embedding-2` model — supplying\nthem to a text-only model returns a clear error.\n\n`recall` works both ways: query by text, by media, or both. Each query\nattachment is embedded into the shared space and runs its own similarity branch,\nfused with the text branch via Reciprocal Rank Fusion — so you can recall a\nmemory from a screenshot, an audio clip, or a PDF as easily as from a phrase.\n\n## How it works\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"assets/architecture.jpg\" alt=\"Gemdex pipeline: save memory → chunker → Gemini embed → LanceDB → recall via MCP\" width=\"100%\" /\u003e\n\u003c/p\u003e\n\n1. **Save** — `content` is split into retrieval **chunks**; each chunk is\n   embedded with Gemini and stored with a `parent_id` pointing back to the whole\n   memory.\n2. **Recall** — hybrid search (dense vector + BM25, fused with Reciprocal Rank\n   Fusion) ranks **chunks**, then each match resolves to its **full parent\n   memory** and results are deduped by `parent_id`. So a query that matches one\n   paragraph of a 300-line playbook gets the entire playbook back, in one shot.\n3. **Store** — everything lives in a single global LanceDB table under\n   `~/.gemdex`. The agent's MCP process and the desktop app's sidecar share the\n   same store, so a memory saved by one shows up in the other.\n\nThis is the well-worn **parent-document retriever** (\"small-to-big\") pattern:\nsharp matching on long content, but the agent always gets the whole memory.\n\n## The desktop app\n\nA native, **manage-only** SwiftUI app for macOS (Apple Silicon) that opens\nstraight into your memory layer:\n\n- Browse / list all memories (sorted by recency).\n- View, create, edit, and delete memories — including inline media attachments\n  (drag-and-drop or pick image / audio / video / PDF, caption them, and preview\n  them in place).\n- \"Find similar\" on any attachment to recall related memories by media.\n- Export all memories to a portable JSONL file; import them back.\n\nThere's **no free-text search box** — recall is an agent/MCP capability; the app\nis a fast local manager (the only recall it surfaces is \"Find similar\", i.e.\nrecall-by-example from an existing attachment). On launch the app spawns its own Node sidecar\n(`gemdex serve`) over localhost and opens directly into the manager. **You never\nrun a sidecar command.**\n\n### First launch\n\nIf `GEMINI_API_KEY` is not configured yet, the app prompts once and stores it\nlocally in `~/.gemdex/.env`.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"assets/app-screenshot-setup.png\" alt=\"Gemdex Memory first-launch API key setup screen\" width=\"100%\" /\u003e\n\u003c/p\u003e\n\n### Memory manager\n\nAfter setup, the app opens into the local manager for browsing, editing,\nexporting, and importing memories.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"assets/app-screenshot-manager.png\" alt=\"Gemdex Memory desktop manager showing stored memories and the empty detail state\" width=\"100%\" /\u003e\n\u003c/p\u003e\n\n```bash\n# from packages/app — requires a Swift 5.9+ toolchain (no Xcode needed)\ncd packages/app\nbash macos/build-app.sh                 # assemble build/Gemdex Memory.app\nopen \"build/Gemdex Memory.app\"          # launch it\n```\n\nDownload a signed, notarized DMG from the\n[latest release](https://github.com/anand-92/gemdex/releases/latest) — it bundles\nits own Node runtime, so it runs with zero manual dependency installation.\n\nThe sidecar is the same package as the MCP server:\n\n```bash\nnpx gemdex serve --port 0   # localhost HTTP/JSON manager API; --port 0 = auto-pick\n```\n\n| Method + path | Purpose |\n|---|---|\n| `GET /health` | readiness probe |\n| `GET /memories` | list (sorted by `updatedAt` desc) |\n| `GET /memories/:id` | full memory |\n| `POST /memories` | create (embeds via Gemini) |\n| `PUT /memories/:id` | edit (re-chunk + re-embed) |\n| `DELETE /memories/:id` | delete |\n| `GET /export` · `POST /import` | portable backup / restore (upsert by id) |\n\nThe sidecar binds `127.0.0.1` only — it's a single-user local app.\n\n## Self-hosted remote mode (BYOI)\n\nRun Gemdex Server with Postgres/pgvector and file or S3-compatible attachment\nstorage, then connect MCP, CLI, and desktop clients to the same global memory\npool. Embedding runs on the server, so remote clients do not need a Gemini key.\n\nIt's two commands. On the server host:\n\n```bash\ngit clone https://github.com/anand-92/gemdex.git\ncd gemdex/packages/server \u0026\u0026 npm run init   # generates secrets, starts Docker, prints the token\n```\n\nOn each client (paste the token when prompted; add `--import-local` to bring\nyour existing local memories along):\n\n```bash\nnpx -y gemdex-mcp@latest init-remote myserver https://memory.example.com\n```\n\n`init-remote` verifies the server, switches the client to remote mode, and\nprints the agent command. You can also run a **local and a remote pool side by\nside** — see the operations guide.\n\nStart with the [`BYOI operations guide`](docs/BYOI_OPERATIONS.md). The\n[`remote mode contract`](docs/BYOI_REMOTE_MODE.md) defines the v1 API, auth,\nattachment handling, compatibility checks, ranking invariants, and non-goals.\n\n## Use as a library\n\nSkip the MCP server and embed the memory store directly:\n\n```ts\nimport { MemoryStore, LanceDBVectorDatabase, GeminiEmbedding } from 'gemdex-core';\n\nconst embedding = new GeminiEmbedding({\n  apiKey: process.env.GEMINI_API_KEY!,\n  model: 'gemini-embedding-2',\n});\n\n// Pass nothing to use the default ~/.gemdex/lance directory.\nconst vectorDatabase = new LanceDBVectorDatabase();\nconst memory = new MemoryStore({ embedding, vectorDatabase });\n\nconst { id } = await memory.save({\n  content: 'Notarize with: xcrun notarytool submit …',\n  title: 'macOS notarization',\n});\n\nconst hits = await memory.recall('how do we notarize builds', 5);\nconsole.log(hits[0].content); // the full memory, never a fragment\n```\n\n## Packages\n\n| Package | Description |\n|---------|-------------|\n| [`gemdex-core`](packages/core) | Memory store (parent-document chunking), Gemini embedding client, embedded LanceDB hybrid retrieval |\n| [`gemdex-mcp`](packages/mcp) | MCP server (`save_memory`/`recall`/`update_memory`) + `gemdex serve` localhost sidecar |\n| [`gemdex-server`](packages/server) | Self-hosted BYOI HTTP backend using Postgres/pgvector and file or S3-compatible blobs |\n| [`packages/app`](packages/app) | native SwiftUI macOS app to manage the memory layer |\n\n## Configuration\n\n\u003cdetails\u003e\n\u003csummary\u003eAll environment variables\u003c/summary\u003e\n\n| Variable | Required | Default | Description |\n|----------|----------|---------|-------------|\n| `GEMINI_API_KEY` | yes | — | Google AI Studio API key (needed to embed on save/recall/update) |\n| `LANCEDB_PATH` | no | `~/.gemdex/lance` | Filesystem path for the embedded memory store |\n| `EMBEDDING_MODEL` | no | `gemini-embedding-2` | Override Gemini embedding model |\n| `EMBEDDING_DIMENSION` | no | model default | Force Matryoshka-resized dimension (256/768/1536/3072) |\n| `GEMINI_BASE_URL` | no | Google default | Custom Gemini endpoint |\n| `HYBRID_MODE` | no | `true` | Disable to use dense-only recall |\n| `GEMDEX_SERVE_PORT` | no | auto (0) | Default port for `gemdex serve` (the app picks one automatically) |\n| `GEMDEX_MODE` | no | `local` | Select the embedded `local` backend or a configured `remote` backend |\n| `GEMDEX_REMOTE_URL` | remote only | — | Gemdex Server root URL |\n| `GEMDEX_REMOTE_TOKEN` | remote only | — | Gemdex Server bearer token |\n\n\u003c/details\u003e\n\n## Privacy \u0026 safety\n\nGemdex is a **power-dev tool with zero guardrails by design**. You may store API\nkeys, credentials, and account details in plaintext. There is no secret\nredaction, encryption mandate, or safety enforcement. In local mode, records\nstay on the client except content sent to Gemini for embedding. In BYOI mode,\nrecords live in your server/database/blob infrastructure and embedding payloads\nare sent from that server to Gemini. Gemdex provides no hosted custody or\naccount service. See the [BYOI security model](docs/BYOI_OPERATIONS.md#security-and-custody).\n\n## Build from source\n\n```bash\ngit clone https://github.com/anand-92/gemdex.git\ncd gemdex\npnpm install\npnpm build\n```\n\nThe MCP entry point lands at `packages/mcp/dist/index.js`. Point your MCP client\nat `node /absolute/path/to/packages/mcp/dist/index.js` to run a local build.\n\n## Roadmap\n\n- [ ] Optional encryption-at-rest for sensitive memories\n- [ ] Packaged desktop app binaries (macOS / Linux / Windows)\n- [ ] Multi-machine sync service (beyond export/import)\n- [ ] Memory linking / references\n- [ ] CLI (`gemdex recall \"...\"`) for non-MCP workflows\n\nHave an idea? [Open a discussion](https://github.com/anand-92/gemdex/discussions/new).\n\n## Contributing\n\nFirst time contributors very welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for\nthe dev loop, then check the `good-first-issue` label.\n\n## Star history\n\n[![Star History Chart](https://api.star-history.com/svg?repos=anand-92/gemdex\u0026type=Date)](https://star-history.com/#anand-92/gemdex\u0026Date)\n\n---\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"assets/star-cta.jpg\" alt=\"If Gemdex gave your agent a memory, drop a star\" width=\"60%\" /\u003e\n\u003c/p\u003e\n\n\u003cdiv align=\"center\"\u003e\n\nIf Gemdex makes your agent remember, **[give it a ⭐](https://github.com/anand-92/gemdex)** — it's the single biggest thing that helps the project grow.\n\n\u003c/div\u003e\n\n## License\n\nMIT. See [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnikships%2Fgemdex","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnikships%2Fgemdex","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnikships%2Fgemdex/lists"}