Skip to content

Making of - claude-mem-house

A living journal of how this repo came to be and how it changes over time.

Chapter 1: the org-migration tool-repo fan-out (2026-07-08)

This repo was built as one of eight tools shipped in parallel through the house's standard tool-repo pipeline (pilot: house-council-client), ahead of a pending org migration - every fan-out repo builds and commits locally only, no GitHub repo, no push, until the migration lands.

Source material. Four PowerShell scripts Andrew had been hand-carrying between house PCs from C:\Users\fives\OneDrive\: a client-setup script that points a house PC's Claude Code at the shared claude-mem server, a warm-standby setup + prereqs pair that turns a second PC into an hourly-synced disaster-recovery mirror, and a switch-server script for failover/failback. These already managed real house infrastructure - the ANDYGREATROOMPC:37877 server-beta stack (Postgres 17 + Valkey 8 + claude-mem-server) - so the goal was packaging, not redesign.

What changed vs. the OneDrive originals. A manual read (the automated pre-scan missed both, see docs/technical/SECURITY.md) turned up two embedded credentials: the house claude-mem API key (cmem_...) in two scripts, and the standby's Postgres password - the latter duplicated a second time inside a here-string that the standby script writes out as a separate generated script file. Both scripts were rewritten to read these from environment variables / matching parameters, defaulting the same way the pilot's council connect scripts default their bearer tokens. The generated sync script was changed to resolve the password at its own run time (env var, else the standby's local .env) instead of carrying a baked-in literal.

Testing shape. These are full standalone installer/failover CLI scripts (Docker, winget, scheduled tasks, DNS resolution, pg_dump) - a harder shape for coverage than the pilot's two connect scripts, because their guard clauses call exit, and PowerShell's exit kills the entire process even when the failing script was invoked via & from inside another script. That rules out in-process test execution (which is how the pilot achieved ~45% coverage) for anything that needs to prove an abort path works. The resolution: behavioral guard tests spawn the real scripts as child processes (real verification, invisible to Pester's in-process coverage instrumentation) alongside static parse + secret-regression tests. Net measured coverage is an honest 0%, documented in TESTING.md rather than silently accepted or gamed with a coverage-only rewrite. Full happy-path E2E (mocking the claude-mem HTTP surface) is deferred - tracked as a board ticket.

Codex security review. First pass came back "Not CLEAN": no active secrets, but real findings - unpinned bun.sh/npx installer execution (accepted, documented inline as the vendor's own install method), CI supply-chain items inherited verbatim from the mandated house CI template (self-hosted PR runners, unpinned semgrep/Pester - tracked at the fleet level, not this repo alone), a real shell-injection gap where the generated standby sync script interpolated the Postgres password unescaped into sh -c '...' strings (fixed - added POSIX single-quote escaping), and a test file that kept the retired password's plaintext split across a string concatenation, still reconstructable (fixed - the test now stores only a SHA-256 hash and hashes password-shaped candidates for comparison, so the plaintext credential appears nowhere in this repo's history from this point forward). Full disposition table: docs/technical/SECURITY.md.

First ticket, closed at build time: package and harden the OneDrive scripts into this repo, passing the house secret/security/testing gates. See docs/BOARD.md.