claude-mem-plus 的远程备份 + 自动同步 + 多用户共享 + 团队共享服务端。 一个 Rust 二进制。一个 SQLite 文件。argon2id + JWT。systemd / launchd / Docker。内置 admin web 控制台。~10 MB 二进制,~5 MB RSS 空闲内存。
If you use claude-mem-plus on more than one machine, or want to share project memory with teammates, cmem-server is the missing piece: a single-binary server that synchronises observations across machines and lets you share entire projects (read-only / fork-allowed / auto-copy) without giving anyone your local filesystem.
中文 README · Install · Deploy · Admin web · API · Architecture · Project sharing · Security · Troubleshooting · Contributing
claude-mem keeps a brilliant per-machine SQLite database of every
observation Claude Code learns about your projects — but it stops at one
machine. The moment you ssh into your VPS, switch from MacBook to
Linux desktop, or want to hand a project context to a teammate, that
local DB is suddenly the wrong DB.
cmem-server is a tiny self-hosted daemon that:
- Accepts JSONL pushes of observations from any number of
claude-memclients (machine token authenticated) - Re-emits them on
pull— own observations across machines, plus observations shared by other users - Owns a project identity layer: same logical project on Mac
(
~/work/nginx-rce) and Linux (~/projects/nginx-rce) is one project, not two - Implements three sharing modes (read-only / fork-allowed / auto-copy) with mode-downgrade notifications
- Ships a built-in admin web console at
/admin(askama + HTMX, no SPA to babysit) - Stores everything in one SQLite file — back up by
cp
- Replacing claude-mem itself
- Multi-tenant SaaS at million-user scale
- Real-time collaborative editing
- Anything that needs Postgres / Redis / Elasticsearch
This is a personal / small-team tool. Simple beats correct-but-bloated.
# On the server (any of: macOS / Ubuntu / Debian / Rocky / Fedora / Arch / Alpine)
git clone https://github.com/bjarne/cmem-server
cd cmem-server
sudo ./scripts/install-server.sh --bind 127.0.0.1:8080That's it. The installer will:
- Detect your OS
- Install build deps (
build-essential/gcc/base-devel...) - Install Rust via
rustup(skipped ifcargois present) cargo build --release- Create
cmemsystem user +/var/lib/cmem-serverdata dir - Generate
/etc/cmem-server.tomlwith a fresh 256-bit JWT secret - Install + enable a hardened
systemdunit (orlaunchdplist on macOS) - Bootstrap a default admin:
admin/admin@123(change immediately!) - Wait for
/healthzto return 200
Open http://127.0.0.1:8080/admin/login and log in.
Verify everything is healthy:
sudo ./scripts/install-server.sh --check
# 8-point check: OS / Rust / binary / config / data dir / service /
# /healthz / admin user. Non-zero exit on any failure (cron-friendly).End users register at http://127.0.0.1:8080/register (admin controls
whether registration is open / invite-only / closed at
/admin/settings — takes effect instantly, no restart).
sudo ./scripts/install-server.sh --domain cmem.example.comThe installer also drops a Caddy snippet that reverse-proxies your
domain to 127.0.0.1:8080 with auto-issued Let's Encrypt certs.
On your laptop, point claude-mem-plus
at the server (the --server flag is consumed by the
install-client.sh companion script):
curl -sSL https://raw.githubusercontent.com/<your>/claude-mem/main/install-client.sh \
| bash -s -- --server https://cmem.example.com
claude-mem sync login --server https://cmem.example.com
claude-mem sync push +-------------------------+
| Browser (admin web) |
+-----------+-------------+
|
HTTPS| /admin/* + /api/admin/*
|
+----------------+ HTTPS v
| claude-mem +-------> +---+--------------------------+
| (Mac / Linux | REST | Caddy (reverse proxy + |
| / Windows) <---------+ Let's Encrypt + HTTP/3) |
+----------------+ +---+--------------------------+
|
loopback :8080
v
+-------+-----------+
| cmem-server | one Rust binary
| axum + sqlx |
+-------+-----------+
|
v
+--------------+-------------+
| /var/lib/cmem-server/ |
| cmem-server.db (WAL) |
| cmem-server.db-wal |
| cmem-server.db-shm |
+----------------------------+
Detailed component diagrams: docs/ARCHITECTURE.md.
Built into the same binary, mounted at /admin. No node, no webpack,
no docker-compose. Tailwind via CDN, askama templates, HTMX for
interactivity.
+--------------------------+
| cmem-server | Dashboard
| admin console | +-------+-------+-------+-------+
| ---------- | | users | mach. | proj. | obs. |
| > Dashboard | | 5 | 10 | 23 | 410 |
| Users | +-------+-------+-------+-------+
| Invites | +------ 24h activity -------+
| Projects | | ### users ## obs # log|
| Observations | +---------------------------+
| Shares |
| Audit Log |
| Export |
| |
| signed in as root |
| [logout] |
+--------------------------+
Pages: dashboard, users, invites, projects, observations, shares, audit log, export (CSV / JSON / full DB dump). Full reference: docs/ADMIN.md.
| Group | Method + Path | Auth | Notes |
|---|---|---|---|
| public | GET /healthz |
— | liveness |
| auth | POST /api/auth/register |
— | hot-configurable: open/invite-only/closed (see /admin/settings) |
| auth | POST /api/auth/login |
— | returns access + refresh |
| auth | POST /api/auth/refresh |
refresh JWT | rotate refresh token |
| auth | POST /api/auth/logout |
access | revokes refresh |
| auth | POST /api/auth/change-password |
access | re-checks old |
| machines | POST /api/machines |
access | issues cmt_<32> token |
| machines | GET /api/machines |
access | list user's machines |
| machines | DELETE /api/machines/:id |
access | revoke token |
| projects | GET /api/projects |
access | list owned + forked |
| projects | POST /api/projects |
access | explicit create |
| projects | GET /api/projects/:id |
access | full detail |
| projects | PATCH /api/projects/:id |
access (owner) | rename / hide |
| projects | DELETE /api/projects/:id |
access (owner) | soft delete |
| sync | POST /api/sync/push |
access or machine | JSONL ingest |
| sync | POST /api/sync/pull |
access or machine | cursor pagination |
| shares | POST /api/shares |
access (owner) | user / public / link |
| shares | GET /api/shares |
access | shares I created |
| shares | PATCH /api/shares/:id |
access (owner) | mode change |
| shares | DELETE /api/shares/:id |
access (owner) | revoke |
| shares | GET /api/shared |
access | shares I received |
| shares | POST /api/shared/notifications/ack |
access | ack downgrades |
| public | GET /register + POST /register |
— | public web sign-up (CSRF + login rate limit) |
| admin | /api/admin/* |
admin JWT | full surface (16 routes) |
| admin web | /admin/settings |
admin cookie | hot-toggle registration_mode (open / invite_only / closed) |
Full request / response shapes: docs/API.md.
| Mode | Recipient sees | Recipient can write | Goes through their pull |
|---|---|---|---|
| read-only | shared view | no | no copy generated |
| fork-allowed | shared view | only after fork |
no copy until fork |
| auto-copy | own copy | yes (it's theirs) | yes, every pull |
Mode downgrades (e.g. fork-allowed -> read-only) raise a notification
on the recipient's next pull and are explicitly acked.
8 invariants, full state matrix, fork semantics: docs/PROJECT_SHARING.md.
# Requirements: rustup stable, sqlite3, OpenSSL dev headers.
git clone https://github.com/bjarne/cmem-server
cd cmem-server
# Cargo workspace, two crates: cmem-shared + cmem-server.
cargo build --workspace --release
# Run tests (uses in-memory SQLite for unit tests).
cargo test --workspace
# Lint (zero warnings policy).
cargo clippy --workspace --all-targets -- -D warnings
cargo fmt --all -- --check
# Run dev server (bind 0.0.0.0:8080, db ./cmem-server.db).
cargo run -p cmem-server -- -c dev-server.tomlSmoke scripts under scripts/:
scripts/smoke_auth.sh # register / login / refresh / change-password / logout
scripts/smoke_sync.sh # push / pull / project resolve flow| Document | Audience | Topic |
|---|---|---|
| INSTALL.md | sysadmin | install on every supported OS |
| DEPLOYMENT.md | sysadmin | VPS / Docker / k8s, backup, monitoring |
| ADMIN.md | admin | admin web pages + CSV / DB export |
| USAGE.md | end-user | claude-mem CLI + viewer flows |
| API.md | client author | REST request / response payloads |
| ARCHITECTURE.md | contributor | crate / module layout, data model |
| PROJECT_SHARING.md | contributor | invariants and state machine |
| SECURITY.md | sysadmin | threat model, hardening checklist |
| TROUBLESHOOTING.md | sysadmin | common failures + recovery |
| CONTRIBUTING.md | contributor | dev setup, commit style, code review |
Chinese versions: docs/i18n/.
| Milestone | Scope | State |
|---|---|---|
| M1 | Workspace + DB schema + /healthz |
done |
| M2 | Auth (argon2id + JWT + refresh) | done |
| M3 | Machines + machine token | done |
| M4 | Projects + identification + merge | done |
| M5 | Sync push / pull (+ shares scaffolding) | partial |
| M6 | Forks (project + observation) | wip |
| M7 | claude-mem client integration | done (TS-side fork) |
| M8 | Deployment + docs + admin web | done |
See docs/Implementation_Plan.md for the authoritative task tracker (kept up to date by docs-maintenance hooks).
MIT. See LICENSE.
Issues / PRs welcome at https://github.com/bjarne/cmem-server. For security disclosures see docs/SECURITY.md.