You can self-host claude-mem sync by running your own sync hub instead of the default cmem.ai service, and the most usable option today is claude-mem-lan-sync, a small open-source Go program called cmemlan. claude-mem is a plugin that gives Claude Code a long-term memory. Its built-in multi-device sync sends your memories and the text of your prompts to a hosted hub at sync.cmem.ai. With cmemlan, that hub runs on your own machine, for example a small Linux VPS that only your laptop and desktop can reach through a private WireGuard tunnel. We built exactly that in our lab on Debian 13 and synced memories in both directions. The hub used about 11 MB of RAM.
Key facts, checked on 16 October 2026:
- claude-mem had about 101,000 GitHub stars, uses the Apache-2.0 licence and released version 13.39.0 on 13 October 2026. It stores memory locally in SQLite under
~/.claude-mem. - The official Cloud Sync docs say sync uploads observation narratives, session summaries and full prompt text (up to 200 KB per prompt) to the hub under your cmem.ai account. The hub address is a setting,
CLAUDE_MEM_CLOUD_SYNC_HUB_URL, and the installer writeshttps://sync.cmem.aiwhen you choose CMEM Pro. - claude-mem-lan-sync v0.1.0 was released on 17 August 2026 under the MIT licence. Its binary says it was "verified against claude-mem 13.15.0". In our lab it also synced with claude-mem 13.39.0.
- The other community hub, cmem-server (Rust, SQLite, JWT logins, admin web page, MIT), is marked alpha, has no published release and talks to a fork called claude-mem-plus, not to standard claude-mem.
- Our lab hub: a 12 MB binary, 11 MB of resident memory, and 76 KB of data after its first memory.
Why keep claude-mem sync off a hosted service
claude-mem watches what Claude Code does in a session, has a model compress that into short notes it calls observations, and feeds the useful ones back into later sessions. Those notes are the point of the plugin, and they are also a fairly detailed diary of your work: which files you changed, what a bug was, how your staging database is set up, and the prompts you typed.
On one computer, all of that stays in a SQLite file in your home folder. Sync changes the picture. When you turn on cmem.ai Cloud Sync, each device uploads three kinds of rows: observations, session summaries and your prompts. The claude-mem docs say so directly and advise against enabling it if that content must stay on your machine. If you work on client code under an NDA, on a company project with a data policy, or just don't want prompt history on someone else's server, that is a real reason to run the hub yourself.
Self-hosting does not make the data untouchable. It moves the trust to you. The cmemlan hub stores memory bodies as plain text in its own SQLite database, so anyone with root on the hub machine can read them. On a VPS that means you, and anyone who gets your root password. If even that is too much, run the hub on a machine in your home or office instead. Everything below works the same there.
Which self-hosted hub to choose
| Option | Works with | Release status | Good fit |
|---|---|---|---|
| claude-mem-lan-sync (cmemlan) | Standard claude-mem, using its own sync settings | v0.1.0, 17 Aug 2026, signed checksums | One person with two or more machines on a private network or tunnel |
| cmem-server | The claude-mem-plus fork only | Alpha, no release, build from source with Rust | Teams that want user accounts, invites and shared projects and accept a fork |
| claude-mem's own hub code | Standard claude-mem | Source in services/sync-api (TypeScript, Bun, Dockerfile), no self-hosting guide | Developers willing to read the code |
| cmem.ai Cloud Sync | Standard claude-mem | Hosted Pro service, up to 64 devices per account | People happy for prompts and notes to live on a third-party host |
We picked cmemlan because it is the only one with a tagged release, it works with the claude-mem you already have, and its author wrote a clear security model. That model has one line you should read before you rent anything: the README says "Do not run this on a VPS" and recommends Tailscale for remote access. The worry is a hub exposed to the open internet, because it speaks plain HTTP. The setup below follows the advice in spirit. The hub listens only on a WireGuard tunnel address, the firewall drops everything else, and the program itself refuses to listen on a public address. In our test, cmemlan serve --bind 0.0.0.0:8787 stopped with "refusing to bind a public or wildcard address". If your devices are always on one home network, a home server is the simpler choice and you don't need us at all.
The lab: what we built and measured
We used two Debian 13 containers on an Amsterdam test server with an AMD EPYC 7742 processor, each limited to 1 GB of RAM and 1 CPU core. Other test labs shared the same 8 cores, so your plan's numbers can differ. One container played the VPS running the hub, the other a developer's laptop. Both ran claude-mem 13.39.0. Nothing here needs a graphics card: the hub only stores and serves records, and the summarising is done by the model provider you choose in claude-mem, which for the default Claude provider means Anthropic's cloud.
| Measurement (our lab) | Result |
|---|---|
| Hub resident memory (RSS) | 11 to 13 MB |
| Hub binary size | 12 MB |
| Hub data on disk | 76 KB after 1 memory, about 140 KB after 3 (including the SQLite write-ahead log) |
| Whole hub container, idle | 42 MB used of 1 GB |
| claude-mem worker on a device (Bun plus the Python search helper) | about 340 MB RSS |
| claude-mem install time | 17 seconds |
| Upload from laptop to hub | within 8 seconds |
| New memory showing up on the other device | 2 to 3 minutes (the client polls the hub) |
The hub is so light that even our smallest plan is mostly idle. The memory cost sits on the devices that run claude-mem itself, not on the hub.
Step 1: prepare the server
Start from a fresh Debian 13 server and harden SSH first; our Debian 13 security guide covers keys and fail2ban. Then install the tools and create a normal user that will own the hub. The hub never needs root:
# as root
apt-get update
apt-get install -y curl ca-certificates wireguard-tools nftables sqlite3 cron
useradd -m -s /bin/bash cmem
Step 2: download and check cmemlan
The project publishes ready binaries with a checksum file. Download both and let sha256sum confirm the file is the one the author built:
# as root
cd /tmp
V=0.1.0
curl -fsSLO https://github.com/andrhamm/claude-mem-lan-sync/releases/download/v$V/cmemlan_${V}_linux_amd64.tar.gz
curl -fsSLO https://github.com/andrhamm/claude-mem-lan-sync/releases/download/v$V/checksums.txt
sha256sum --ignore-missing -c checksums.txt
tar xzf cmemlan_${V}_linux_amd64.tar.gz
install -m 0755 cmemlan /usr/local/bin/cmemlan
cmemlan --version
You should see cmemlan_0.1.0_linux_amd64.tar.gz: OK and then cmemlan 0.1.0 (verified against claude-mem 13.15.0). If the checksum line says FAILED, delete the file and download it again.
Step 3: build a private WireGuard tunnel
WireGuard is a small, fast VPN built into the Linux kernel. It gives the server and your laptop private addresses (here 10.66.0.1 and 10.66.0.2) that only they can use. Our WireGuard VPN server guide explains it in depth; this is the minimum. Make a key pair on each machine, the server and the laptop:
# as root, on both machines
umask 077
wg genkey | tee /etc/wireguard/private.key | wg pubkey > /etc/wireguard/public.key
cat /etc/wireguard/public.key
The last line prints a public key such as AyP6oM6Q...ZiI=. Public keys are safe to copy between machines; the private key never leaves its machine. On the server, write the tunnel config, putting the laptop's public key in place of LAPTOP_PUBLIC_KEY:
# as root, on the server
cat > /etc/wireguard/wg0.conf <<CONF
[Interface]
Address = 10.66.0.1/24
ListenPort = 51820
PrivateKey = $(cat /etc/wireguard/private.key)
[Peer]
# laptop
PublicKey = LAPTOP_PUBLIC_KEY
AllowedIPs = 10.66.0.2/32
CONF
chmod 600 /etc/wireguard/wg0.conf
systemctl enable --now wg-quick@wg0
wg show wg0
On a Linux laptop, the matching config points at the server's public IPv4 address:
# as root, on the laptop
cat > /etc/wireguard/wg0.conf <<CONF
[Interface]
Address = 10.66.0.2/24
PrivateKey = $(cat /etc/wireguard/private.key)
[Peer]
PublicKey = SERVER_PUBLIC_KEY
Endpoint = YOUR_VPS_IP:51820
AllowedIPs = 10.66.0.1/32
PersistentKeepalive = 25
CONF
chmod 600 /etc/wireguard/wg0.conf
systemctl enable --now wg-quick@wg0
ping -c 3 10.66.0.1
Three replies with 0% packet loss mean the tunnel works. On Windows or macOS, use the official WireGuard app with the same values. If you already use Tailscale, you can skip this step: bind the hub to the server's Tailscale address instead, because cmemlan allows Tailscale's 100.64.0.0/10 range by default. Our guides to Tailscale on a VPS and Headscale versus NetBird cover that route.
Step 4: run the hub as a service
The hub has a built-in --install-service option, but it creates a per-user service. A normal system service with User=cmem is easier to manage on a server, and it lets us make the hub wait for the tunnel. The hardening lines come from the unit that cmemlan serve --print-unit generates:
# as root
cat > /etc/systemd/system/cmemlan.service <<'UNIT'
[Unit]
Description=cmemlan sync hub for claude-mem
After=wg-quick@wg0.service
Requires=wg-quick@wg0.service
[Service]
User=cmem
ExecStart=/usr/local/bin/cmemlan serve --data-dir /home/cmem/.local/share/cmemlan --bind 10.66.0.1:8787 --allow-cidr 10.66.0.0/24 --no-mdns
Restart=on-failure
RestartSec=5
NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=strict
ProtectHome=read-only
ReadWritePaths=/home/cmem/.local/share/cmemlan
CapabilityBoundingSet=
RestrictAddressFamilies=AF_INET AF_INET6
MemoryMax=512M
[Install]
WantedBy=multi-user.target
UNIT
install -d -o cmem -g cmem -m 0700 /home/cmem/.local/share/cmemlan
systemctl daemon-reload
systemctl enable --now cmemlan
ss -tlnp | grep 8787
journalctl -u cmemlan --no-pager | tail -5
Three flags do the security work. --bind 10.66.0.1:8787 listens only on the tunnel. --allow-cidr 10.66.0.0/24 makes the hub turn away any address outside the tunnel range. --no-mdns stops the hub from announcing itself on the local network, which is useless on a server. The ss line should show 10.66.0.1:8787, and the journal prints a hub id and a fingerprint like EwXd-kYjw-DEiM. Note the fingerprint; it proves later that your laptop is talking to your hub and not to an impostor.
Step 5: lock the firewall
nftables is Debian's firewall. This ruleset allows SSH, the WireGuard port and the hub port only on the tunnel interface, and drops everything else:
# as root
cat > /etc/nftables.conf <<'NFT'
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
iif "lo" accept
ct state established,related accept
ip protocol icmp accept
ip6 nexthdr icmpv6 accept
tcp dport 22 accept
udp dport 51820 accept
iifname "wg0" tcp dport 8787 accept
}
chain forward {
type filter hook forward priority 0; policy drop;
}
}
NFT
nft -c -f /etc/nftables.conf && systemctl enable --now nftables && systemctl restart nftables
From the laptop, a request through the tunnel answered 401 (the hub is there and wants a key), while the same request to the server's normal address timed out. Once SSH keys work, you can also limit the port 22 rule to your own fixed IP address, if you have one. After a reboot of the server, WireGuard, the hub and the firewall all came back on their own in our test.
Step 6: connect your laptop
Install claude-mem on the laptop first. We learned this the hard way: the claude-mem installer resets the sync settings, so if you connect to the hub first, the installer wipes that connection. claude-mem needs Node.js; on Debian 13 the packaged Node 20.19 printed a warning that one library wants Node 22, but everything we tested worked. Normally you run npx claude-mem install and answer its questions. We used the non-interactive form:
# as your normal user, on the laptop
npx -y claude-mem@13.39.0 install --ide claude-code --provider claude --runtime worker
npx claude-mem start
npx claude-mem status
The installer finished in 17 seconds and showed Cloud sync: OFF (local). The status shows Worker is running and its local port, 37700 in our case. With the Claude provider, the installer still printed an optional cmem.ai sign-in link; you don't need to open it. Install cmemlan on the laptop the same way as in step 2. Then open a pairing window on the server:
# as the cmem user, on the server
cmemlan pair --data-dir ~/.local/share/cmemlan
It prints a one-time code such as 327-191-636 and the fingerprint. The code works for five minutes and only once. On the laptop:
# as your normal user, on the laptop
cmemlan connect http://10.66.0.1:8787 --code 327-191-636 --fingerprint EwXd-kYjw-DEiM
curl -s http://127.0.0.1:37700/api/sync/status
connect writes the hub address, a key and a device id into ~/.claude-mem/settings.json, keeps a backup of the old file and restarts the claude-mem worker. The status JSON should contain "reachable":true and "health":{"state":"ok". One quirk: in our lab, cmemlan status and cmemlan doctor reported the hub as unreachable with HTTP 400, while claude-mem's own status said reachable and memories flowed. Trust the claude-mem status line above, and the hub's journal.
Test it without spending a Claude session
claude-mem normally creates memories while you work in Claude Code. To test the sync path on its own, its worker accepts a manual memory on its local port:
# as your normal user, on the laptop
curl -s -X POST http://127.0.0.1:37700/api/memory/save -H 'Content-Type: application/json' \
-d '{"project":"shop-api","title":"Test from laptop","text":"The staging database runs on port 5433, not 5432."}'
It answered "Memory saved as observation #1", and within 8 seconds the sync status showed "headSeq":"1", meaning the hub had stored one record. On our second device (its worker used port 37701), the record appeared through curl -s "http://127.0.0.1:37701/api/observations?project=shop-api" with the full text. A memory saved on the second device reached the laptop about two minutes later, and the next one took about three. The client polls the hub rather than holding a live connection, so expect minutes, not seconds.
Two more commands are worth knowing. Existing memories are not sent automatically: after connect, the tool points you to cmemlan backfill --dry-run to preview what would upload (we did not run a backfill). cmemlan devices on the server lists every device that has contacted the hub, and cmemlan revoke DEVICE_ID shuts one out, for example a lost laptop. Restart the hub after a revoke so it takes effect at once.
What we did not use: a reverse proxy with HTTPS
A normal web app on a VPS sits behind a reverse proxy such as Caddy or nginx with a TLS certificate, as in our reverse proxy guide. We tried that here with Caddy and its internal certificate authority on the tunnel address. curl and Node.js on the laptop both refused the certificate (UNABLE_TO_GET_ISSUER_CERT_LOCALLY), and claude-mem's sync uses Node's fetch, so sync would simply stop. The cmemlan security notes warn about this exact case. WireGuard already encrypts the traffic between your devices and the server, so plain HTTP inside the tunnel is not sent in the clear over the internet. If you need a real certificate, the project suggests tailscale serve, which we did not test because it needs a Tailscale account.
Back up the hub database
Backing up the hub is your job. Each device keeps its own full copy of its memories, but the hub holds the shared history and the device list. SQLite has a safe online copy command, so you don't need to stop the hub:
# as the cmem user, on the server
mkdir -p -m 700 ~/backups
sqlite3 ~/.local/share/cmemlan/hub.db ".backup '$HOME/backups/hub-$(date +%F).db'"
sqlite3 ~/backups/hub-$(date +%F).db "PRAGMA integrity_check; SELECT count(*) FROM ops;"
( crontab -l 2>/dev/null; echo '15 3 * * * sqlite3 $HOME/.local/share/cmemlan/hub.db ".backup $HOME/backups/hub-$(date +\%F).db" && find $HOME/backups -name "hub-*.db" -mtime +14 -delete' ) | crontab -
crontab -l
The check printed ok and 3, our three test memories. The cron line makes a copy every night at 03:15 and keeps two weeks. A copy on the same disk is not a backup against losing the server, and the file holds your memories in plain text, so send it encrypted to another place. Our restic offsite backup guide does that in a few commands. Also keep ~/.local/share/cmemlan/psk, the hub's key; without it, devices must pair again.
Which plan and which city
The hub alone barely registers on any server. What decides the plan is what else you run next to it. A common pattern is a VPS that also runs Claude Code around the clock, as in our Claude Code 24/7 guide; that server then becomes a third device sharing the same memory. Claude Code's own docs ask for 4 GB of RAM, and the claude-mem worker took about 340 MB in our lab.
| Your setup | Plan | Why |
|---|---|---|
| Sync hub and WireGuard only | VPS Nano (1 shared vCPU, 1 GB, 20 GB NVMe) | The hub used 11 MB and the whole system about 42 MB in our test |
| Hub plus other small private services (a VPN for your team, Vaultwarden, an MCP server) | VPS Micro (2 shared vCPU, 2 GB, 40 GB NVMe) | Room for a few light services side by side |
| Hub plus Claude Code and claude-mem running on the server | VPS Mini (4 shared vCPU, 4 GB, 80 GB NVMe) | Meets Claude Code's 4 GB requirement |
| Hub plus Claude Code that builds and tests large projects all day | VDS Small (4 dedicated vCPU, 8 GB, 240 GB NVMe) | Dedicated cores for compilers and test suites |
Distance hardly matters for sync itself, because devices poll every few minutes. Pick the city by where you and your other servers are, and by which country's law you want the data under. On 6 October 2026 we measured our servers with ping.pe: Frankfurt and London reached Amsterdam in about 7 ms, and Vienna reached Prishtina in about 19 ms, with Skopje 3 ms from Prishtina on our own network.
| You are mostly in | City | Page |
|---|---|---|
| Western or Central Europe | Amsterdam | VPS in the Netherlands |
| Ireland or the UK | Dublin | VPS in Ireland |
| Kosovo and the Balkans | Prishtina | VPS in Kosovo |
All plans run on KVM with NVMe storage, unmetered traffic, their own IPv4 address and IPv6, and you can move up a plan later from the client area with a short reboot. Availability by city is on the plans page. If you are building a wider private AI toolbox, our same-week guide to a self-hosted MCP gateway fits on the same server.
Frequently asked questions
Does claude-mem send my data to the cloud?
Not by default. claude-mem stores memory in a local SQLite database under ~/.claude-mem. Cloud Sync is off until three settings are filled in: a hub URL, a token and a user id. When you enable cmem.ai Cloud Sync, observations, session summaries and prompt text are uploaded to that hub. The model that writes the memories also runs at your chosen provider, such as Anthropic.
Can I self-host the claude-mem sync server?
Yes. claude-mem reads the hub address from CLAUDE_MEM_CLOUD_SYNC_HUB_URL, and the community project claude-mem-lan-sync (MIT, v0.1.0 from August 2026) implements a compatible hub. It runs as one small Go binary with a SQLite file, and in our test it used about 11 MB of RAM.
Is it safe to run a claude-mem sync hub on a VPS?
Only if it is not reachable from the internet. The hub speaks plain HTTP and stores memories as plain text, and its author advises against running it on a VPS. Bind it to a WireGuard or Tailscale address, allow only that range, and drop the port in the firewall. Anyone with root on the server can still read the data.
How fast does claude-mem sync between two computers?
In our lab, a new memory reached the self-hosted hub within 8 seconds and appeared on the other device after 2 to 3 minutes, because the client polls the hub. That is fine for memory, which you use in your next session, not the next second.
What is the difference between cmemlan and cmem-server?
cmemlan works with standard claude-mem and is meant for one person's devices on a private network. cmem-server is a Rust server with user accounts, an admin page and team sharing, but it is alpha, has no release yet and needs the claude-mem-plus fork.
Which server do I need for a claude-mem sync hub?
The smallest one. A VPS Nano with 1 GB of RAM runs the hub and WireGuard with room to spare. Choose a VPS Mini with 4 GB if the same server also runs Claude Code, which asks for 4 GB of memory.
Your memory, your server
claude-mem makes Claude Code remember your projects, and sync makes that memory follow you between machines. With cmemlan, a WireGuard tunnel and a firewall, the sync hub runs on a server you control, uses almost no resources, and never offers its port to the open internet. A VPS Nano or VPS Mini in Amsterdam, Dublin or Prishtina is enough. Questions about the setup, or want us to install it for you as quoted setup work? Message us on Telegram.