{"id":49567320,"url":"https://github.com/bjarne56/cmem-server","last_synced_at":"2026-05-09T18:00:53.767Z","repository":{"id":355331898,"uuid":"1227673094","full_name":"bjarne56/cmem-server","owner":"bjarne56","description":"Self-hosted sync server for claude-mem-plus. Single Rust binary, SQLite, JWT, admin web. Cross-machine memory sync + project sharing for Claude Code.","archived":false,"fork":false,"pushed_at":"2026-05-08T17:26:20.000Z","size":513,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-08T17:41:51.038Z","etag":null,"topics":["admin-web","axum","claude-code","claude-mem","cmem","cmem-sync","jwt","memory","rust","self-hosted","sqlite","sync","sync-server"],"latest_commit_sha":null,"homepage":"https://github.com/bjarne56/claude-mem-plus","language":"Rust","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/bjarne56.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"docs/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"docs/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":null,"dco":null,"cla":null}},"created_at":"2026-05-03T02:18:12.000Z","updated_at":"2026-05-08T17:26:25.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/bjarne56/cmem-server","commit_stats":null,"previous_names":["bjarne56/cmem-server"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/bjarne56/cmem-server","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bjarne56%2Fcmem-server","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bjarne56%2Fcmem-server/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bjarne56%2Fcmem-server/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bjarne56%2Fcmem-server/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bjarne56","download_url":"https://codeload.github.com/bjarne56/cmem-server/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bjarne56%2Fcmem-server/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32829581,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-08T08:22:46.396Z","status":"online","status_checked_at":"2026-05-09T02:00:06.633Z","response_time":123,"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":["admin-web","axum","claude-code","claude-mem","cmem","cmem-sync","jwt","memory","rust","self-hosted","sqlite","sync","sync-server"],"created_at":"2026-05-03T12:02:28.460Z","updated_at":"2026-05-09T18:00:53.717Z","avatar_url":"https://github.com/bjarne56.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# cmem-server\n\n[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)\n[![Rust](https://img.shields.io/badge/rust-stable-orange.svg)](rust-toolchain.toml)\n[![axum](https://img.shields.io/badge/axum-0.7-brightgreen.svg)](https://github.com/tokio-rs/axum)\n[![SQLite](https://img.shields.io/badge/sqlite-3-003B57.svg)](https://www.sqlite.org/)\n[![Status](https://img.shields.io/badge/status-alpha-yellow.svg)](docs/Implementation_Plan.md)\n\n\u003e **claude-mem-plus 的远程备份 + 自动同步 + 多用户共享 + 团队共享服务端。**\n\u003e 一个 Rust 二进制。一个 SQLite 文件。argon2id + JWT。systemd / launchd /\n\u003e Docker。内置 admin web 控制台。~10 MB 二进制，~5 MB RSS 空闲内存。\n\nIf you use [claude-mem-plus](https://github.com/bjarne56/claude-mem-plus) on more\nthan one machine, or want to share project memory with teammates,\n**cmem-server** is the missing piece: a single-binary server that\nsynchronises observations across machines and lets you share entire\nprojects (read-only / fork-allowed / auto-copy) without giving anyone\nyour local filesystem.\n\n[中文 README](docs/i18n/README.zh.md) · [Install](docs/INSTALL.md) ·\n[Deploy](docs/DEPLOYMENT.md) · [Admin web](docs/ADMIN.md) ·\n[API](docs/API.md) · [Architecture](docs/ARCHITECTURE.md) ·\n[Project sharing](docs/PROJECT_SHARING.md) ·\n[Security](docs/SECURITY.md) · [Troubleshooting](docs/TROUBLESHOOTING.md) ·\n[Contributing](docs/CONTRIBUTING.md)\n\n---\n\n## Why?\n\n`claude-mem` keeps a brilliant per-machine SQLite database of every\nobservation Claude Code learns about your projects — but it stops at one\nmachine. The moment you `ssh` into your VPS, switch from MacBook to\nLinux desktop, or want to hand a project context to a teammate, that\nlocal DB is suddenly the wrong DB.\n\n`cmem-server` is a tiny self-hosted daemon that:\n\n- Accepts JSONL pushes of observations from any number of `claude-mem`\n  clients (machine token authenticated)\n- Re-emits them on `pull` — own observations across machines, plus\n  observations shared by other users\n- Owns a **project identity layer**: same logical project on Mac\n  (`~/work/nginx-rce`) and Linux (`~/projects/nginx-rce`) is one\n  project, not two\n- Implements three sharing modes (read-only / fork-allowed / auto-copy)\n  with mode-downgrade notifications\n- Ships a built-in admin web console at `/admin` (askama + HTMX, no SPA\n  to babysit)\n- Stores everything in **one SQLite file** — back up by `cp`\n\n### Non-goals\n\n- Replacing claude-mem itself\n- Multi-tenant SaaS at million-user scale\n- Real-time collaborative editing\n- Anything that needs Postgres / Redis / Elasticsearch\n\nThis is a personal / small-team tool. **Simple beats correct-but-bloated.**\n\n---\n\n## 5-minute quick start\n\n```bash\n# On the server (any of: macOS / Ubuntu / Debian / Rocky / Fedora / Arch / Alpine)\ngit clone https://github.com/bjarne/cmem-server\ncd cmem-server\nsudo ./scripts/install-server.sh --bind 127.0.0.1:8080\n```\n\nThat's it. The installer will:\n\n1. Detect your OS\n2. Install build deps (`build-essential` / `gcc` / `base-devel` ...)\n3. Install Rust via `rustup` (skipped if `cargo` is present)\n4. `cargo build --release`\n5. Create `cmem` system user + `/var/lib/cmem-server` data dir\n6. Generate `/etc/cmem-server.toml` with a fresh 256-bit JWT secret\n7. Install + enable a hardened `systemd` unit (or `launchd` plist on macOS)\n8. Bootstrap a default admin: **`admin` / `admin@123`** (change immediately!)\n9. Wait for `/healthz` to return 200\n\nOpen `http://127.0.0.1:8080/admin/login` and log in.\n\nVerify everything is healthy:\n\n```bash\nsudo ./scripts/install-server.sh --check\n# 8-point check: OS / Rust / binary / config / data dir / service /\n# /healthz / admin user. Non-zero exit on any failure (cron-friendly).\n```\n\nEnd users register at `http://127.0.0.1:8080/register` (admin controls\nwhether registration is **open / invite-only / closed** at\n`/admin/settings` — takes effect instantly, no restart).\n\n### Behind a domain (auto HTTPS via Caddy)\n\n```bash\nsudo ./scripts/install-server.sh --domain cmem.example.com\n```\n\nThe installer also drops a Caddy snippet that reverse-proxies your\ndomain to `127.0.0.1:8080` with auto-issued Let's Encrypt certs.\n\n### Connect a client\n\nOn your laptop, point [claude-mem-plus](https://github.com/bjarne56/claude-mem-plus)\nat the server (the `--server` flag is consumed by the\n`install-client.sh` companion script):\n\n```bash\ncurl -sSL https://raw.githubusercontent.com/\u003cyour\u003e/claude-mem/main/install-client.sh \\\n    | bash -s -- --server https://cmem.example.com\nclaude-mem sync login --server https://cmem.example.com\nclaude-mem sync push\n```\n\n---\n\n## Architecture at a glance\n\n```\n                   +-------------------------+\n                   |   Browser (admin web)   |\n                   +-----------+-------------+\n                               |\n                          HTTPS|  /admin/* + /api/admin/*\n                               |\n+----------------+    HTTPS    v\n|  claude-mem    +-------\u003e +---+--------------------------+\n|  (Mac / Linux  |  REST   |   Caddy (reverse proxy +     |\n|   / Windows)   \u003c---------+   Let's Encrypt + HTTP/3)    |\n+----------------+         +---+--------------------------+\n                               |\n                          loopback :8080\n                               v\n                       +-------+-----------+\n                       |   cmem-server     |   one Rust binary\n                       |   axum + sqlx     |\n                       +-------+-----------+\n                               |\n                               v\n                +--------------+-------------+\n                |   /var/lib/cmem-server/    |\n                |     cmem-server.db (WAL)   |\n                |     cmem-server.db-wal     |\n                |     cmem-server.db-shm     |\n                +----------------------------+\n```\n\nDetailed component diagrams: [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md).\n\n---\n\n## Admin web console\n\nBuilt into the same binary, mounted at `/admin`. No node, no webpack,\nno docker-compose. Tailwind via CDN, askama templates, HTMX for\ninteractivity.\n\n```\n+--------------------------+\n| cmem-server              |  Dashboard\n| admin console            |  +-------+-------+-------+-------+\n| ----------               |  | users | mach. | proj. | obs.  |\n| \u003e Dashboard              |  |   5   |  10   |  23   |  410  |\n|   Users                  |  +-------+-------+-------+-------+\n|   Invites                |  +------ 24h activity -------+\n|   Projects               |  | ###  users  ##  obs  # log|\n|   Observations           |  +---------------------------+\n|   Shares                 |\n|   Audit Log              |\n|   Export                 |\n|                          |\n| signed in as root        |\n| [logout]                 |\n+--------------------------+\n```\n\nPages: dashboard, users, invites, projects, observations, shares, audit\nlog, export (CSV / JSON / full DB dump). Full reference:\n[docs/ADMIN.md](docs/ADMIN.md).\n\n---\n\n## REST API surface\n\n| Group | Method + Path | Auth | Notes |\n|-------|---------------|------|-------|\n| public | `GET /healthz` | — | liveness |\n| auth | `POST /api/auth/register` | — | hot-configurable: open/invite-only/closed (see `/admin/settings`) |\n| auth | `POST /api/auth/login` | — | returns access + refresh |\n| auth | `POST /api/auth/refresh` | refresh JWT | rotate refresh token |\n| auth | `POST /api/auth/logout` | access | revokes refresh |\n| auth | `POST /api/auth/change-password` | access | re-checks old |\n| machines | `POST /api/machines` | access | issues `cmt_\u003c32\u003e` token |\n| machines | `GET  /api/machines` | access | list user's machines |\n| machines | `DELETE /api/machines/:id` | access | revoke token |\n| projects | `GET  /api/projects` | access | list owned + forked |\n| projects | `POST /api/projects` | access | explicit create |\n| projects | `GET  /api/projects/:id` | access | full detail |\n| projects | `PATCH /api/projects/:id` | access (owner) | rename / hide |\n| projects | `DELETE /api/projects/:id` | access (owner) | soft delete |\n| sync | `POST /api/sync/push` | access or machine | JSONL ingest |\n| sync | `POST /api/sync/pull` | access or machine | cursor pagination |\n| shares | `POST /api/shares` | access (owner) | user / public / link |\n| shares | `GET  /api/shares` | access | shares I created |\n| shares | `PATCH /api/shares/:id` | access (owner) | mode change |\n| shares | `DELETE /api/shares/:id` | access (owner) | revoke |\n| shares | `GET  /api/shared` | access | shares I received |\n| shares | `POST /api/shared/notifications/ack` | access | ack downgrades |\n| public | `GET /register` + `POST /register` | — | public web sign-up (CSRF + login rate limit) |\n| admin | `/api/admin/*` | admin JWT | full surface (16 routes) |\n| admin web | `/admin/settings` | admin cookie | hot-toggle registration_mode (open / invite_only / closed) |\n\nFull request / response shapes: [docs/API.md](docs/API.md).\n\n---\n\n## Project sharing in 90 seconds\n\n| Mode | Recipient sees | Recipient can write | Goes through their `pull` |\n|------|----------------|---------------------|---------------------------|\n| **read-only** | shared view | no | no copy generated |\n| **fork-allowed** | shared view | only after `fork` | no copy until fork |\n| **auto-copy** | own copy | yes (it's theirs) | yes, every pull |\n\nMode downgrades (e.g. `fork-allowed` -\u003e `read-only`) raise a notification\non the recipient's next pull and are explicitly acked.\n\n8 invariants, full state matrix, fork semantics:\n[docs/PROJECT_SHARING.md](docs/PROJECT_SHARING.md).\n\n---\n\n## Build from source\n\n```bash\n# Requirements: rustup stable, sqlite3, OpenSSL dev headers.\ngit clone https://github.com/bjarne/cmem-server\ncd cmem-server\n\n# Cargo workspace, two crates: cmem-shared + cmem-server.\ncargo build --workspace --release\n\n# Run tests (uses in-memory SQLite for unit tests).\ncargo test --workspace\n\n# Lint (zero warnings policy).\ncargo clippy --workspace --all-targets -- -D warnings\ncargo fmt --all -- --check\n\n# Run dev server (bind 0.0.0.0:8080, db ./cmem-server.db).\ncargo run -p cmem-server -- -c dev-server.toml\n```\n\nSmoke scripts under `scripts/`:\n\n```bash\nscripts/smoke_auth.sh    # register / login / refresh / change-password / logout\nscripts/smoke_sync.sh    # push / pull / project resolve flow\n```\n\n---\n\n## Documentation map\n\n| Document | Audience | Topic |\n|----------|----------|-------|\n| [INSTALL.md](docs/INSTALL.md) | sysadmin | install on every supported OS |\n| [DEPLOYMENT.md](docs/DEPLOYMENT.md) | sysadmin | VPS / Docker / k8s, backup, monitoring |\n| [ADMIN.md](docs/ADMIN.md) | admin | admin web pages + CSV / DB export |\n| [USAGE.md](docs/USAGE.md) | end-user | claude-mem CLI + viewer flows |\n| [API.md](docs/API.md) | client author | REST request / response payloads |\n| [ARCHITECTURE.md](docs/ARCHITECTURE.md) | contributor | crate / module layout, data model |\n| [PROJECT_SHARING.md](docs/PROJECT_SHARING.md) | contributor | invariants and state machine |\n| [SECURITY.md](docs/SECURITY.md) | sysadmin | threat model, hardening checklist |\n| [TROUBLESHOOTING.md](docs/TROUBLESHOOTING.md) | sysadmin | common failures + recovery |\n| [CONTRIBUTING.md](docs/CONTRIBUTING.md) | contributor | dev setup, commit style, code review |\n\nChinese versions: [docs/i18n/](docs/i18n/).\n\n---\n\n## Status\n\n| Milestone | Scope | State |\n|-----------|-------|-------|\n| M1 | Workspace + DB schema + `/healthz` | done |\n| M2 | Auth (argon2id + JWT + refresh) | done |\n| M3 | Machines + machine token | done |\n| M4 | Projects + identification + merge | done |\n| M5 | Sync push / pull (+ shares scaffolding) | partial |\n| M6 | Forks (project + observation) | wip |\n| M7 | claude-mem client integration | done (TS-side fork) |\n| M8 | Deployment + docs + admin web | done |\n\nSee [docs/Implementation_Plan.md](docs/Implementation_Plan.md) for the\nauthoritative task tracker (kept up to date by docs-maintenance hooks).\n\n---\n\n## License\n\nMIT. See [LICENSE](LICENSE).\n\n## Contact\n\nIssues / PRs welcome at \u003chttps://github.com/bjarne/cmem-server\u003e.\nFor security disclosures see [docs/SECURITY.md](docs/SECURITY.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbjarne56%2Fcmem-server","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbjarne56%2Fcmem-server","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbjarne56%2Fcmem-server/lists"}