claude-mem-house¶
What this does in one paragraph¶
This is the operational toolkit for the house's shared claude-mem memory server: a
self-hosted Postgres + Valkey + claude-mem-server stack that runs in Docker on the main
PC (ANDYGREATROOMPC) and gives every Claude Code install in the house a shared,
searchable memory. scripts/ holds four PowerShell scripts that (1) point a house PC's
Claude Code at the server as a client, (2) turn a second house PC into a warm standby
that mirrors the primary's Postgres hourly for disaster recovery, (3) install that
standby's platform prerequisites (WSL2 + Docker Desktop), and (4) repoint a client at a
different server during failover/failback. None of the scripts hardcode credentials -
API keys and the Postgres password are read from environment variables (or matching
-ApiKey / -PgPassword parameters), never committed.
Why this exists¶
claude-mem is normally a per-device, SQLite-backed Claude Code plugin. The house runs
a shared server-beta variant instead so every device's Claude Code can search the same
memory (Andrew's preferences, project notes, past decisions) instead of each device
starting from scratch. That shared server is a single point of failure by default; the
standby scripts turn a second PC into a warm, hourly-synced failover so the house
doesn't lose shared memory access if the main PC is off, asleep, or its stack breaks.
Usage¶
Client setup (any house PC that should read/write the shared memory)¶
$env:CLAUDE_MEM_HOUSE_API_KEY = "<key from the vault>"
powershell -ExecutionPolicy Bypass -File scripts\claude-mem-client-setup.ps1
Idempotent - installs Node/Bun/claude-mem if missing, writes ~\.claude-mem\settings.json,
registers the claude-mem-server MCP server in Claude Code, and verifies both the REST
API and MCP endpoint respond.
Warm standby (a second house PC that should mirror the primary)¶
# once, elevated:
powershell -ExecutionPolicy Bypass -File scripts\claude-mem-standby-prereqs.ps1
# then, normal user:
$env:CLAUDE_MEM_HOUSE_PG_PASSWORD = "<password from the vault>"
$env:CLAUDE_MEM_HOUSE_API_KEY = "<key from the vault>"
powershell -ExecutionPolicy Bypass -File scripts\claude-mem-standby-setup.ps1
Clones and builds the pinned claude-mem commit, brings up a local copy of the full
Docker stack, writes an hourly pg_dump-pull sync script + scheduled task, opens the
LAN firewall for the server port, and verifies the local stack serves the same API key
as the primary.
Failover / failback (any client, when the primary or a standby changes)¶
# failover to a standby:
.\scripts\claude-mem-switch-server.ps1 -ServerUrl http://<standby-hostname-or-ip>:37877
# failback to the primary:
.\scripts\claude-mem-switch-server.ps1 -ServerUrl http://ANDYGREATROOMPC:37877
Reads the existing API key from ~\.claude-mem\settings.json (never re-enters it),
health-checks the target, updates the URL, and re-registers the MCP server.
Automatic failover (watchdog)¶
src/ClaudeMemWatchdog is a small always-on C# console app that automates what
claude-mem-switch-server.ps1 does by hand: it polls the active server's
/healthz every 30 seconds and, if the primary is down for 3 consecutive
checks AND 5 minutes continuously (a grace window, not just a check count),
fails over to the first healthy + API-key-authorized standby - the same
health/authorize/rewrite-settings.json/re-register-MCP sequence the manual
script performs, native in C# instead of shelled out to PowerShell. It fails
back to the primary once the primary has been continuously healthy for 5
minutes, and if the standby it's currently on dies while failed over, it
moves to the primary (if healthy) or the next standby.
Install it on any house PC:
powershell -ExecutionPolicy Bypass -File scripts\install-watchdog.ps1
This publishes a self-contained ClaudeMemWatchdog.exe, writes
~\.claude-mem\watchdog.json (only if it doesn't already exist - re-running
never clobbers tuned thresholds), and registers a "claude-mem-watchdog"
Scheduled Task that starts it at logon. Logs live at
~\.claude-mem\watchdog.log (auto-rotates past 5 MB); crash-forensics state
at ~\.claude-mem\watchdog-state.json. Like every script in this repo, the
API key is never written to the watchdog's own config - it's resolved at
runtime from ~\.claude-mem\settings.json or the
CLAUDE_MEM_SERVER_API_KEY environment variable, exactly like the manual
switch script.
The main PC's watchdog only fails itself over when its own loopback stack
(http://127.0.0.1:37877) is down past the grace window - which is exactly
the case that should trigger a failover, not a false positive. The 2026-07-14
trigger for building this was Docker Desktop's auto-updater silently
restarting the stack for ~3 minutes; AutoDownloadUpdates is now turned off
on the main PC, so that specific cause shouldn't recur. This watchdog is
defense-in-depth for the other outage classes that can still take the primary
down for real (Wi-Fi drift onto the wrong network, a reboot, a WSL crash) -
cases where a human might not notice for hours that shared memory access is
down.
Repository layout¶
src/ClaudeMemWatchdog/ automatic failover watchdog (C#, net10.0) - see above
tests/ClaudeMemWatchdog.Tests/ its xUnit test suite
scripts/ claude-mem-client-setup.ps1, claude-mem-standby-prereqs.ps1,
claude-mem-standby-setup.ps1, claude-mem-switch-server.ps1,
install-watchdog.ps1
tests/ Scripts.Tests.ps1 (static: parse + secret regression),
Guards.Tests.ps1 (behavioral: real abort-path verification),
Invoke-CI.ps1 (Pester 5 + dotnet test, hermetic)
archive/ superseded scripts, kept for history (never deleted; secrets scrubbed). Do NOT run.
TESTING.md the full testing matrix (unit + coverage + churn + E2E; why the coverage
floor here is an honest 0%, and why Stryker is N/A)
docs/ technical + plain-language architecture, security, making-of journal, board;
docs/watchdog.sample.json is a sample watchdog.json with house values
Never-delete / archive policy¶
Superseded files are never deleted - they move to archive/ with a history-encoding
filename (...CURRENT-<date>.STALE-<date>.superseded-by-<reason>.ps1) and a header block
explaining what replaced them and why. Any secrets in an archived file are scrubbed the
same as in live files (real credentials live only in the vault / server config).
Security¶
- Credentials are never hardcoded.
claude-mem-client-setup.ps1andclaude-mem-standby-setup.ps1read the house API key fromCLAUDE_MEM_HOUSE_API_KEY(or-ApiKey); the standby setup also reads the Postgres password fromCLAUDE_MEM_HOUSE_PG_PASSWORD(or-PgPassword). Both abort with a clear message if unset, before making any network call.claude-mem-switch-server.ps1never takes a credential parameter at all - it re-reads the key already stored in~\.claude-mem\settings.jsonfrom an earlier client setup. - The Postgres password the standby setup writes to a local
.env(for Docker compose) is written only to disk on that device;.envis gitignored and is not part of this repo. The hourly sync script it installs reads the password from the environment or falls back to parsing that same local.env- never a literal in this repo. .envis gitignored; only.env.example(empty placeholders) is committed.- CI runs a Pester test that fails the build if a
cmem_API-key literal, or the specific Postgres password these scripts originally shipped with (now retired), ever reappears in any script - live or archived - plus a Semgrep scan. - Full findings summary:
docs/technical/SECURITY.md. - If you ever need to rotate the API key or Postgres password, change it on the primary server / in the vault - no code change is required here.