Skip to content

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.ps1 and claude-mem-standby-setup.ps1 read the house API key from CLAUDE_MEM_HOUSE_API_KEY (or -ApiKey); the standby setup also reads the Postgres password from CLAUDE_MEM_HOUSE_PG_PASSWORD (or -PgPassword). Both abort with a clear message if unset, before making any network call. claude-mem-switch-server.ps1 never takes a credential parameter at all - it re-reads the key already stored in ~\.claude-mem\settings.json from 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; .env is 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.
  • .env is 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.