Files
felhom.eu/workspace/README.md
T
admin f65ea89a24
gates / gates (push) Successful in 8s
workspace: version the root CLAUDE.md + InstructionsLoaded hook, and report which rules fire (R-229)
install_workspace.py lays down the two things that shaped every session while existing on one
host only. Unlike install_skills.py the targets are LIVE CONFIG, so: timestamped backup before
every write, settings.json MERGED (this script owns exactly one key), a diverged CLAUDE.md
reported rather than silently resolved, and an unparseable settings.json refused outright.

Proven: all 7 top-level settings keys survived byte-identically, and run 2 wrote nothing.

rules_report.py surfaces the column that matters -- rules that have NEVER fired, which are
mis-globbed or dead. 6 of 9 on first run. The hook now self-rotates at 5 MB.

The memory store is BACKED UP, NOT COMMITTED (auto-written, may name hosts/paths): added to
dooplex-backup.service's User Data component. /opt/backup/scripts/ is itself unversioned host
state -- filed, not fixed here.
2026-08-06 10:57:01 +02:00

3.4 KiB

workspace/ — the parts of the workspace that live outside every repo

Claude Code runs from /mnt/5_hdd/felhom.eu/git, which is not a git repository. Three things that shape every session live there or in ~/.claude/ and are therefore on one machine only:

Thing Live path Versioned where Installed by
workspace-root instructions <workspace>/CLAUDE.md documentation/runbooks/workspace-CLAUDE.md scripts/install_workspace.py
InstructionsLoaded hook ~/.claude/settings.json workspace/hooks/instructions-loaded.json scripts/install_workspace.py
auto-memory store <workspace>/.claude-memory/ not versioned — backed up dooplex-backup.service

Why the CLAUDE.md source is NOT in this directory

documentation/runbooks/workspace-CLAUDE.md is canonical and stays where it is. It already has a gate enforcing byte-identity with the live file (instructions_gate.py check 5), and it is the path every existing pointer names. Copying it here would create a third copy of a file whose whole problem is that copies drift — the installer reads the canonical path instead.

Why the memory store is backed up and not committed

It is auto-written: Claude writes it, so nobody reviews it before it lands. It may name hosts, paths and out-of-band secret locations that this project's secrets rule keeps out of committed files. A scan on 2026-08-06 found no credential values (535 keyword mentions across 104 files, one key: value-shaped hit that was prose, zero private-key blocks) — but "no secrets today" is not a property a directory keeps on its own when a machine writes to it unattended.

So it is protected by dooplex-backup.service's User Data component instead (CLAUDE_MEMORY_DIR in /opt/backup/scripts/backup-config.sh).

The exact change, recorded here because the file it was made in is not version-controlled:

# /opt/backup/scripts/backup-config.sh
export CLAUDE_MEMORY_DIR="/mnt/5_hdd/felhom.eu/git/.claude-memory"

# /opt/backup/scripts/backup-data.sh — restic takes multiple paths; an absent optional path is
# skipped with a printed reason, never a failure
local backup_paths=("${DATA_SOURCE_DIR}")
if [ -n "${CLAUDE_MEMORY_DIR:-}" ] && [ -d "${CLAUDE_MEMORY_DIR}" ]; then
    backup_paths+=("${CLAUDE_MEMORY_DIR}")
fi
restic -r "${RESTIC_REPO_DATA}" backup "${backup_paths[@]}" "${exclude_args[@]}" ...

/opt/backup/scripts/ is itself unversioned host state on DooPlex — no repo tracks it. That is a fresh instance of the very class this directory exists to close, found while closing it. Filed as a register item rather than fixed here: bringing a root-owned production backup script under version control (and deciding what installs it) is its own change, not a rider on this one.

One-time cost of the change, so it is not mistaken for a fault: adding a path to a restic path set invalidates the parent-snapshot match, so the first run after this edit logs no parent snapshot found, will read all files and re-reads the whole source (405 GiB). Chunk-level dedup means storage barely moves; subsequent runs find a parent and are incremental again.

Caveat, stated because it is easy to misread as safety: that backup's destination (/mnt/5_hdd/backup) is on the same physical disk as the store. It protects against accidental deletion, not against loss of sda1, and there is no off-site leg for the DooPlex backup set.