{"id":51234549,"url":"https://github.com/imsudip/opencode-mem0-selfhost","last_synced_at":"2026-06-28T19:01:17.178Z","repository":{"id":367298501,"uuid":"1280146468","full_name":"imsudip/opencode-mem0-selfhost","owner":"imsudip","description":"Self-host Mem0 REST backend for OpenCode. Fork of @mem0/opencode-plugin with the mem0ai SDK swapped for a thin REST client.","archived":false,"fork":false,"pushed_at":"2026-06-25T10:49:45.000Z","size":103,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-25T12:18:08.865Z","etag":null,"topics":["ai-memory","mem0","memory","opencode","opencode-plugin","persistent-memory","self-host","self-hosted"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/opencode-mem0-selfhost","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/imsudip.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"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":null,"dco":null,"cla":null}},"created_at":"2026-06-25T10:04:59.000Z","updated_at":"2026-06-25T11:09:54.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/imsudip/opencode-mem0-selfhost","commit_stats":null,"previous_names":["imsudip/opencode-mem0-selfhost"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/imsudip/opencode-mem0-selfhost","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imsudip%2Fopencode-mem0-selfhost","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imsudip%2Fopencode-mem0-selfhost/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imsudip%2Fopencode-mem0-selfhost/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imsudip%2Fopencode-mem0-selfhost/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/imsudip","download_url":"https://codeload.github.com/imsudip/opencode-mem0-selfhost/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imsudip%2Fopencode-mem0-selfhost/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34900367,"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-28T02:00:05.809Z","response_time":54,"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-memory","mem0","memory","opencode","opencode-plugin","persistent-memory","self-host","self-hosted"],"created_at":"2026-06-28T19:01:14.270Z","updated_at":"2026-06-28T19:01:17.159Z","avatar_url":"https://github.com/imsudip.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# opencode-mem0-selfhost\n\n\u003e Persistent memory for [OpenCode](https://opencode.ai), backed by a self-hosted\n\u003e [Mem0](https://docs.mem0.ai/open-source/setup) REST server.\n\u003e [Install from npm](https://www.npmjs.com/package/opencode-mem0-selfhost) — no build required.\n\nA community-maintained self-host fork of the official\n[`@mem0/opencode-plugin`](https://github.com/mem0ai/mem0/tree/main/integrations/mem0-plugin/.opencode-plugin).\nThe hooks, tool names, slash skills, scope model, and memory context injection are\nall preserved; only the `mem0ai` SDK call layer is swapped for a small REST\nclient that talks to your self-host server. The plugin sends no data to\nMem0's hosted platform.\n\n---\n\n## Table of contents\n\n- [What this is — and isn't](#what-this-is--and-isnt)\n- [Why a fork?](#why-a-fork)\n- [Status](#status)\n- [Install](#install)\n- [Configure](#configure)\n- [What's included](#whats-included)\n- [Self-host caveats](#self-host-caveats)\n- [Differences from the official plugin](#differences-from-the-official-plugin)\n- [What changed from upstream](#what-changed-from-upstream)\n- [Verify](#verify)\n- [Troubleshooting](#troubleshooting)\n- [Keeping in sync with upstream](#keeping-in-sync-with-upstream)\n- [Development](#development)\n- [Credits and license](#credits-and-license)\n\n---\n\n## What this is — and isn't\n\nThe mem0 project ships three things that are sometimes called \"self-host\":\n\n| Project | What it is | Port | API path | This plugin works against it? |\n|---|---|---|---|---|\n| [`server/`](https://github.com/mem0ai/mem0/tree/main/server) | FastAPI REST server, the documented self-host bundle (API + dashboard) | 8888 (Compose), 8000 (raw Docker) | `/memories`, `/search`, `/entities` — no `/v1/` prefix | **Yes — this is the target** |\n| [`openmemory/`](https://github.com/mem0ai/mem0/tree/main/openmemory) | Separate self-hostable platform (FastAPI + Qdrant + Next.js dashboard) with its own API | 8765 | `/api/v1/...` | No — different endpoints, different auth |\n| `mem0ai` Python SDK self-hosted mode | In-process library (`from mem0 import Memory`); no HTTP at all | — | — | No — different concept entirely |\n\nThis plugin only targets the `server/` Docker stack. The official\n[`docs/open-source/setup`](https://docs.mem0.ai/open-source/setup) page\ndescribes that stack.\n\n## Why a fork?\n\nThe official plugin (`@mem0/opencode-plugin`) is hardcoded to call the\n[Mem0 Platform](https://app.mem0.ai) using the `mem0ai` SDK. There is no\ndocumented way to point it at a self-host server. The hooks, tool\ndefinitions, and skill set are all reusable as-is — only the SDK call\nlayer needs replacing. That's what this fork does.\n\n## Status\n\n- **Published on npm** as [`opencode-mem0-selfhost`](https://www.npmjs.com/package/opencode-mem0-selfhost)\n  (latest = 0.1.4). CI builds and publishes automatically on every\n  `vX.Y.Z` tag via [npm OIDC trusted publishing](https://docs.npmjs.com/trusted-publishers).\n- **Tested against source, not yet against a running server.** Every\n  endpoint, request shape, and response shape was cross-checked against\n  `mem0/server/main.py`, `mem0/server/routers/entities.py`, and the docs at\n  `mem0/docs/open-source/{setup,features/rest-api}.mdx`. End-to-end\n  integration testing against a live `docker compose up` stack is the\n  next step — PRs welcome.\n- 63 unit tests pass (`bun test`).\n- Type-check clean (`bun run type-check`).\n- Build produces a 0.49 MB ESM bundle (`bun run build`).\n\n---\n\n## Install\n\nOpenCode loads plugins in three ways: from npm, from a local file, or\nfrom a directory. The npm install is the recommended one. See\n[opencode.ai/docs/plugins](https://opencode.ai/docs/plugins) for the\nfull mechanism.\n\n### From npm (recommended)\n\nAdd the package to your OpenCode config. Edit `~/.config/opencode/opencode.json`\n(for a global install) or `\u003cproject\u003e/opencode.json` (for a project-local\ninstall):\n\n```json\n{\n  \"plugin\": [\"opencode-mem0-selfhost\"]\n}\n```\n\nRestart OpenCode. It will `bun install` the package (and its dependencies)\nautomatically into `~/.cache/opencode/node_modules/` on first launch. The\nplugin registers its memory tools and skills itself — no MCP server to\nconfigure.\n\nThe `opencode plugin` CLI command documented in the mem0 integration\nguide is shorthand for the same thing.\n\n### Pin a specific version\n\nIf you want a reproducible install (recommended for teams), pin the\nversion:\n\n```json\n{\n  \"plugin\": [\"opencode-mem0-selfhost@0.1.4\"]\n}\n```\n\nOmit the `@\u003cversion\u003e` to track the latest `dist-tag.latest` from npm.\n\n### From a Git checkout (contributors / local dev)\n\nClone the repo, build, and load the bundle via `file://`:\n\n```bash\ngit clone https://github.com/imsudip/opencode-mem0-selfhost.git\ncd opencode-mem0-selfhost\nbun install\nbun run build\n```\n\nThen point your config at the built bundle:\n\n```json\n{\n  \"plugin\": [\n    \"file:///absolute/path/to/opencode-mem0-selfhost/dist/index.js\"\n  ]\n}\n```\n\nThis is the path maintainers use while developing. End users should use\nthe npm install above.\n\n## Configure\n\n```bash\n# Required — the X-API-Key value your self-host server accepts.\n# Per-user keys are prefixed `m0sk_`; the legacy `ADMIN_API_KEY` is also\n# accepted. See \"Self-host caveats\" below for JWT auth.\nexport MEM0_API_KEY=\"m0sk_your-key\"\n\n# Optional — base URL of your self-host Mem0 server.\n# Default is the Docker Compose port; override for raw Docker / uvicorn.\n#   - Docker Compose (`make up` in `server/`): http://localhost:8888\n#   - Raw Docker / uvicorn:                 http://localhost:8000\nexport MEM0_HOST=\"http://localhost:8888\"\n\n# Optional — stable user identity. Defaults to $USER / os.userInfo().username.\nexport MEM0_USER_ID=\"your-name\"\n\n# Optional — override the auto-detected git-remote-based project id.\n# The plugin derives this from the git remote (`owner-repo`), falling back\n# to the repo root dir name, then the cwd. Override here if those don't\n# match what you want stored with the memory.\nexport MEM0_APP_ID=\"my-project\"\n\n# Optional — disable the auto-dream memory-consolidation scheduler.\n# The `/mem0-dream` slash command still works.\nexport MEM0_DREAM=false\n\n# Optional — opt in to anonymous PostHog usage events.\n# Default is OFF. The official plugin defaults to ON; this fork flips it\n# because self-host users tend to be more privacy-sensitive.\nexport MEM0_TELEMETRY=true\n```\n\n`MEM0_HOST` accepts `MEM0_SELF_HOST_URL` as a fallback for ergonomics if\nyou already have it set in your shell.\n\n## What's included\n\nIdentical surface to the upstream plugin, minus the cloud-only pieces:\n\n| Component | Description |\n|-----------|-------------|\n| **9 native memory tools** | `add_memory`, `search_memories`, `get_memories`, `get_memory`, `update_memory`, `delete_memory`, `delete_all_memories`, `delete_entities`, `list_entities`, plus a `get_event_status` compatibility stub (self-host writes are synchronous) |\n| **7 lifecycle hooks** | `config`, `chat.message`, `tool.execute.before`, `tool.execute.after`, `experimental.chat.messages.transform`, `experimental.session.compacting`, `shell.env` |\n| **9 slash skills** | `/mem0-remember`, `/mem0-tour`, `/mem0-search`, `/mem0-status`, `/mem0-scope`, `/mem0-dream`, `/mem0-forget`, `/mem0-pin`, `/mem0-context-loader` — discovered in place from `opencode-skills/` |\n| **Auto-dream** | Gated memory consolidation (time + sessions + memory-count). Opt-out via `MEM0_DREAM=false` or the `dream` block in `~/.mem0/settings.json` |\n| **Scope model** | Per-call `scope: \"project\" \\| \"session\" \\| \"global\"` plus a persistent default set by `/mem0-scope` |\n\n---\n\n## Self-host caveats\n\nThese are the practical gotchas that don't show up in the API shape\nverification. All confirmed by reading the server source and docs.\n\n### Default port depends on how you run the server\n\n- **Docker Compose** (the documented `make up` path in `server/`) publishes\n  internal port 8000 as **8888** on the host.\n- **Raw `docker run -p 8000:8000`** and **`uvicorn main:app`** listen on\n  **8000** unless you remap.\n- The plugin defaults to `http://localhost:8888` (the Compose default). If\n  you run the server another way, set `MEM0_HOST` accordingly.\n\n### Auth: per-user `X-API-Key` is what this plugin supports\n\nThe self-host server accepts three auth modes:\n\n- `X-API-Key: m0sk_…` (per-user key) — **supported by this plugin**\n- `Authorization: Bearer \u003cjwt\u003e` (dashboard session) — **not supported** by\n  this plugin. If you want JWT auth (long-running agent that logs in once\n  and refreshes), this needs adding. Per-user `m0sk_…` keys are the\n  documented \"programmatic\" path, so most users won't notice.\n- `X-API-Key: \u003cADMIN_API_KEY env value\u003e` (legacy shared key) — works\n  with this plugin (it's just an `X-API-Key` header with a different value).\n  Prefer per-user keys for new deployments.\n\n### `GET /memories` with no identifier is admin-only\n\nIf you somehow call `get_memories` with no `user_id`/`agent_id`/`run_id`\nand no `app_id`, the server returns 403 unless the API key has admin role.\nThe plugin always populates `user_id` from `MEM0_USER_ID` before this\ncode path is hit, so it doesn't bite in practice. Worth knowing if you\nbuild tooling on top of the plugin.\n\n### No `/health` endpoint\n\nThe server has no `GET /health` route. The plugin's `health()` method\npings `/openapi.json` (always 200 when the app is up) then falls back to\n`/` (redirect to `/docs`). Use it for connectivity checks; for liveness\nprobes on the server itself, point your orchestrator at `/openapi.json`.\n\n### No `rerank` parameter\n\nThe mem0 Python library's `search()` accepts a `rerank: bool` flag. The\nself-host REST server's `SearchRequest` schema does **not** expose it —\nit's filtered out at the server before the underlying lib sees it. The\nofficial skills were updated to drop `rerank: true` accordingly.\n\n---\n\n## Differences from the official plugin\n\nA short summary. See the [next section](#what-changed-from-upstream) for\nthe full file-by-file diff.\n\n- **No `mem0ai` SDK dependency.** All memory operations are plain `fetch`\n  calls against `MEM0_HOST`.\n- **No phone-home telemetry.** `MEM0_TELEMETRY` defaults to `false`.\n  Upstream defaults to `true`.\n- **No Platform-specific APIs.** Per-project category configuration,\n  `getProject`/`updateProject`, and async `get_event_status` are gone.\n  `get_event_status` is a stub that returns `UNSUPPORTED` for skill\n  compatibility.\n- **`app_id` lives in metadata.** The self-host REST only supports\n  `user_id`, `agent_id`, `run_id`, and `metadata` as top-level identity\n  fields. The plugin writes `app_id` to `metadata.app_id` and filters by\n  it client-side on reads.\n- **`delete_all_memories` is a list-then-delete loop.** The server's\n  `DELETE /memories` bulk endpoint is admin-only; the plugin fetches\n  matching IDs and deletes them one at a time. Works with a regular\n  per-user API key.\n- **Entity management is real, just at different paths.** `list_entities`\n  calls `GET /entities`; `delete_entities` calls\n  `DELETE /entities/{type}/{id}`.\n- **`update_memory` requires `text`.** The server's `MemoryUpdate` schema\n  has `text: str` as required. The plugin reads the current memory first\n  if `text` is omitted, so \"update metadata only\" calls work transparently.\n\n---\n\n## What changed from upstream\n\nA file-by-file diff against\n[`mem0ai/mem0` `integrations/mem0-plugin/.opencode-plugin/`](https://github.com/mem0ai/mem0/tree/main/integrations/mem0-plugin/.opencode-plugin).\nUpstream SHA tracked in `.upstream-sha` (currently pinned to the\n`mem0ai/mem0@main` HEAD this fork was verified against).\n\n### New files\n\n| File | Purpose |\n|---|---|\n| `selfhost-client.ts` | The whole point of the fork — thin REST wrapper around the self-host server. ~480 lines, typed `Memory` / `Entity` shapes matching the server's Pydantic models. |\n| `selfhost-client.test.ts` | 22 unit tests covering host resolution, auth header, `app_id` → `metadata.app_id` migration on `add`, client-side filtering on `getAll` (including `app_id` which the server can't filter), pagination, error formatting with the host in the message, `health()`, and entity endpoints. |\n| `.github/workflows/sync-upstream.yml` | Weekly (and on `workflow_dispatch`) check of `mem0ai/mem0@main`; opens a PR with the upstream diff in the body when it changes. |\n| `.github/workflows/ci.yml` | `type-check` + `bun test` + `bun run build` + artifact presence on every push/PR. |\n| `.upstream-sha` | Pinned upstream SHA used by the sync workflow. |\n| `.gitignore` | Excludes `node_modules/` and `dist/` (upstream ships no `.gitignore`). |\n| `LICENSE` | Apache-2.0; copyright assigned to the project, not upstream. |\n\n### Files modified\n\n**`package.json`** — new name, repo, keywords; `mem0ai` removed from\n`dependencies`; `esbuild` not added; `scripts.build` identical to upstream\n(`bun build` + `tsc --emitDeclarationOnly`); `types` points at\n`dist/opencode-mem0.d.ts` (the actual emitted file, not `dist/index.d.ts`\nwhich the upstream `types` field incorrectly points at).\n\n**`tsconfig.json`** — unchanged.\n\n**`telemetry.ts`** — opinionated diff:\n- `isTelemetryEnabled()` defaults to `false` (was `true`).\n- Env-var parsing inverted: accepts `true`/`1`/`yes`/`on` to enable.\n- Package name check: `\"@mem0/opencode-plugin\"` → `\"opencode-mem0-selfhost\"`.\n- Doc comments rewritten to explain the opt-in rationale.\n\n**`opencode-mem0.ts`** — surgical edits (the diff is too long to enumerate\nline-by-line here; the commit messages in `git log` walk through them):\n- `import {MemoryClient} from \"mem0ai\"` →\n  `import {SelfHostMemoryClient, type Memory} from \"./selfhost-client\"`.\n- Dropped `mkdirSync`/`writeFileSync` from the `fs` import (only used by\n  removed code).\n- Removed entirely: `CODING_CATEGORIES`, `categoriesFingerprint`,\n  `apiKeyFingerprint`, `autoSetupCategories` — the self-host REST has no\n  project-category API, so they're not stubbed, just not present.\n- `extractMemories` retyped: `res: any` → `res: Memory[] | { results?: Memory[] } | undefined`.\n- Client construction: `new MemoryClient({apiKey})` →\n  `new SelfHostMemoryClient({apiKey, defaultUserId, defaultAppId})`, and\n  the construction line moved to **after** `userId`/`appId` resolution\n  so they can be passed as defaults.\n- Error message: \"Get one at https://app.mem0.ai/dashboard/api-keys\" →\n  \"Set it to the X-API-Key value accepted by your self-host Mem0 server.\"\n- Slash command template: appended a self-host note about sync writes\n  and the no-op `get_event_status`.\n- `get_event_status` tool returns a static `{status: \"UNSUPPORTED\", …}`\n  JSON instead of calling the SDK's `/v1/event/{id}/` endpoint.\n- `delete_entities` and `list_entities` tool descriptions corrected (they\n  call real self-host endpoints at `/entities`, not Platform paths).\n- Parameter naming: SDK style `topK`/`pageSize` → REST style\n  `top_k`/`page_size` (8 call sites).\n- `memoryCount` parsing simplified — upstream had a 3-tier fallback\n  (count → array length → results length) for legacy SDK responses; we\n  just read `count` because the self-host REST always returns\n  `{results, count}`.\n\n**`opencode-skills/*/SKILL.md`** — all 9 skills adapted for self-host:\n- `remember`, `pin`, `status` — extract the `id` directly from the\n  `add_memory` response (no `get_event_status` polling).\n- `search`, `tour` — dropped `rerank: true` (not exposed by the server).\n- `dream` — swapped the merge order to write-new-then-delete-old (safer\n  for sync writes; upstream was delete-then-write to avoid event_id churn).\n- `pin` — added `metadata.pinned = true` (so `dream` can detect pinned\n  memories without text-parsing).\n- `scope`, `forget`, `context-loader` — minor wording tweaks, no logic\n  change.\n\n### Files unchanged (byte-identical to upstream)\n\n`scope.ts`, `project.ts`, `dream.ts` — pure logic with no SDK\ndependency; copied verbatim and we own the result under the same Apache-2.0\nlicense.\n\n---\n\n## Verify\n\nAfter installing via npm (or source) and restarting OpenCode:\n\n1. Start OpenCode inside a git repo (so `app_id` resolves from the git\n   remote).\n2. Ask: *\"Search my memories for recent decisions\"*\n3. If the `mem0_*` tools respond, you're connected.\n4. Run `/mem0-status` for a diagnostic summary.\n\nYou can also verify the round trip without OpenCode:\n\n```bash\ncurl -s -X POST \"$MEM0_HOST/memories\" \\\n  -H \"X-API-Key: $MEM0_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d \"{\\\"messages\\\":[{\\\"role\\\":\\\"user\\\",\\\"content\\\":\\\"hello\\\"}],\\\"user_id\\\":\\\"$MEM0_USER_ID\\\",\\\"metadata\\\":{\\\"app_id\\\":\\\"$MEM0_APP_ID\\\"}}\"\n```\n\nExpect a JSON body with `results: [{id, memory, ...}]`.\n\n## Troubleshooting\n\n| Problem | Fix |\n|---------|-----|\n| No tools appearing in OpenCode | Check `~/.config/opencode/opencode.json` (or `\u003cproject\u003e/opencode.json`) has `\"opencode-mem0-selfhost\"` in the `plugin` array, then restart OpenCode. |\n| `Connection refused` | Check `MEM0_HOST`. Default is `http://localhost:8888` (Compose). Raw Docker / uvicorn use 8000. |\n| `401 Unauthorized` | `echo $MEM0_API_KEY` — the value must match a key your self-host server accepts (per-user `m0sk_…` or `ADMIN_API_KEY` env value). |\n| `403 Forbidden` on `delete_all_memories` or `get_memories` with no identifier | API key doesn't have admin role. Use a per-user key (which is what the dashboard setup wizard issues) and pass a `user_id`. |\n| Plugin not loading from source build | Verify the `file://` path in `opencode.json` points to `dist/index.js` and that `bun run build` ran without errors. Also check the file is readable. |\n| `bun install` step fails when OpenCode auto-installs the npm package | Check your network can reach the npm registry. For air-gapped installs, see the `From a Git checkout` path above. |\n| Memories missing project context on search | `app_id` is stored in `metadata.app_id`. Searches must filter on `metadata.app_id`, not top-level `app_id`. The plugin does this automatically. |\n| `get_event_status` returns `UNSUPPORTED` | Expected. Self-host writes are synchronous; the `add_memory` response already contains the memory ID. |\n| `delete_entities` or `list_entities` 404 on older self-host | Requires `mem0` server ≥ a release that ships `routers/entities.py`. Very old pre-1.x builds may not have it. |\n\n---\n\n## Keeping in sync with upstream\n\n`.github/workflows/sync-upstream.yml` runs weekly (Monday 06:00 UTC) and\non `workflow_dispatch`. It:\n\n1. Clones `mem0ai/mem0@main`.\n2. Compares the HEAD to the SHA pinned in `.upstream-sha`.\n3. If they differ, opens a PR that:\n   - Bumps `.upstream-sha` to the new HEAD.\n   - Includes the upstream diff (truncated to ~40 KB) in the PR body, with\n     a list of changed files.\n\nThe PR is **informational** — porting upstream changes into our source\nfiles is a manual step, because upstream uses the `mem0ai` SDK while we\nuse a thin REST client. Read the diff, port the relevant changes to\n`src/` (likely `opencode-mem0.ts`, `scope.ts`, `dream.ts`, and the\nskills), then merge the PR so we don't re-notify for the same upstream\nchanges.\n\nThe diff is small enough that porting is typically a 10–30 minute job\nper upstream release. The PR description makes it clear what files\nchanged upstream.\n\n---\n\n## Development\n\n```bash\nbun install              # install deps (uses bun.lock)\nbun run type-check       # tsc --noEmit\nbun test                 # bun test (63 tests)\nbun run build            # bun build + tsc emit-decls → dist/\n```\n\nThe build produces `dist/index.js` (the bundled plugin) and\n`dist/opencode-mem0.d.ts` (types). The bundle is ESM-targeted for Bun.\n\n### Project layout\n\n```\n.\n├── .github/workflows/   ci.yml, sync-upstream.yml\n├── opencode-skills/     9 slash skills (SKILL.md per skill)\n├── opencode-mem0.ts     main plugin entry\n├── selfhost-client.ts   REST client (the only net-new file)\n├── scope.ts             project.ts             dream.ts\n├── telemetry.ts\n├── *.test.ts            bun:test unit tests\n├── package.json\n├── tsconfig.json\n├── bun.lock\n├── .upstream-sha        pinned mem0ai/mem0 SHA\n├── .gitignore\n├── LICENSE              Apache-2.0\n├── README.md\n└── CHANGELOG.md\n```\n\n### Verification methodology\n\nThe REST client was written by reading:\n\n- `mem0/server/main.py` — endpoint paths, request/response Pydantic models,\n  auth dependencies (`verify_auth` vs `require_admin`).\n- `mem0/server/routers/entities.py` — `/entities` router (list + cascade\n  delete). The first round had stubbed entity endpoints as no-ops. Round 2\n  fixed\n  that.\n- `mem0/server/auth.py` — confirmed `X-API-Key` is the API-key auth\n  header name.\n- `mem0/mem0/memory/main.py` — confirmed the underlying Python lib's\n  return shapes (`add()` → `{results: [...]}`, `search()` → list,\n  `get_all()` → `{results: [...]}`) so the client's response parsers\n  handle them.\n- `mem0/docs/open-source/setup.mdx` and\n  `mem0/docs/open-source/features/rest-api.mdx` — confirmed the\n  public-facing contract (port, paths, auth, no `/v1/` prefix).\n\nEnd-to-end testing against a live `docker compose up` stack is the\nobvious next step. PRs welcome.\n\n---\n\n## Credits and license\n\n- **Upstream**: [`@mem0/opencode-plugin`](https://github.com/mem0ai/mem0/tree/main/integrations/mem0-plugin/.opencode-plugin)\n  by [Mem0](https://mem0.ai) and contributors. All credit for the\n  hooks, tool definitions, skill set, scope model, and dream consolidation\n  design goes to the upstream maintainers. This fork would not exist\n  without their work.\n- **Self-host server**: the [`mem0ai/mem0/server`](https://github.com/mem0ai/mem0/tree/main/server)\n  FastAPI server this plugin targets.\n- **This fork**: maintained by the opencode-mem0-selfhost contributors.\n\n**License**: Apache-2.0. See [LICENSE](./LICENSE).\n\nContributions are welcome — please open an issue before sending a non-trivial\nPR so we can agree on the approach first.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fimsudip%2Fopencode-mem0-selfhost","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fimsudip%2Fopencode-mem0-selfhost","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fimsudip%2Fopencode-mem0-selfhost/lists"}