Files
claude-mds/TODO.md
T
pastilhas eec6a4962e install.sh: clone anywhere, run one command
A manifest declares repo path -> target, and the script walks it. Symlinks, not
copies, so an installed file edits the repo and one commit reaches every other
machine. Idempotent — a correct link is a no-op, safe after every pull. A real
file where a link should go is moved to .bak-<timestamp> and reported, because
on a new machine that may be the only copy of something written by hand.

Conditional targets are what make it portable: officer.dev/CLAUDE.md and the
officer-chat-events hook both name ~/officer-dev/platform, so a laptop with no
Officer install gets neither instead of getting a document that lies.

mask-secret is a command now rather than a path only true on this machine, and
user/CLAUDE.md says so. It is a generated wrapper, not a symlink, and that is
forced: mask-secret.py resolves its own path to find mask-hooks.d, so a symlink
would reach back into the repo and run every machine's hooks. The wrapper sets
MASK_HOOKS_DIR to the ones this machine installed and still runs the script from
the repo, so no code is copied.

Verified against a scratch HOME: re-run is all ok, the hand-written file
survives as .bak, and a machine without Officer skips both conditional lines.
2026-08-21 00:24:22 +00:00

4.4 KiB

TODO

Bootstrap installer — BUILT 2026-08-20

install.sh plus manifest. Clone the repo, run one command, every file lands where the tooling expects it. See README.md.

Everything the plan asked for is in: a manifest rather than paths in shell, symlinks rather than copies, idempotent, conditional targets, backups instead of silent clobber, --dry-run.

Verified on this machine and against a scratch HOME: a re-run is all ok, a real file in the way is moved to .bak-<timestamp> and survives, and a machine with no ~/officer-dev/platform skips both the workspace file and its hook.

mask-secret is a command now, on ~/.local/bin, and user/CLAUDE.md names it instead of the hardcoded path that was only ever true here. It is a generated wrapper, not a symlink, and that is forced: mask-secret.py finds hooks at Path(__file__).resolve().parent/mask-hooks.d, and .resolve() follows a symlink back into the repo — which carries every machine's hooks, not this one's. The wrapper sets MASK_HOOKS_DIR and still executes the script from the repo, so no code is copied.

Still open

  • Bootstrapping the bootstrap. The machine needs git, an SSH key for Gitea, and the repo URL before any of this runs. A one-line curl | sh would close it, and may be deliberately not worth having.
  • settings.json and hooks. Not managed here yet. The repo is named for the docs but already carries tools/, so the line is already crossed; the question is whether per-machine settings can be expressed as one file plus conditions, or whether they are genuinely per-machine.
  • Which files are universal. officer.dev/ is the only machine-specific one so far. The platform-appstore/ set is a candidate and was never folded in.
  • PATH. install.sh warns when ~/.local/bin is missing from PATH but does not edit a shell profile. Editing someone's .zshrc from an installer is a bigger intrusion than the warning.

Prior art to discuss: akitaonrails/ai-memory

https://github.com/akitaonrails/ai-memory — read 2026-08-13. Solves a superset of this: cross-vendor long-term memory so you can quit Claude Code mid-task and continue in Codex without re-explaining. A Rust binary plus a data dir, served over MCP, with install-mcp and install-hooks subcommands.

Worth stealing even if we never run it:

  • _global scope. A reserved project that is unioned into every query — standing personal rules, tech choices, style. Exactly what user/CLAUDE.md is. Confirms the split we already made.
  • Page categories: _rules/, decisions/, procedures/, gotchas/. Better than one growing file. Our user/CLAUDE.md is six sections and will not stay readable at twenty.
  • Authority-aware retrieval. Maintained rules outrank episodic session evidence, but do not become absolute. A good answer to "the doc says X but the code does Y" — which bit us today with the stale pm2 rule.
  • .ai-memory.toml marker file in a repo ancestor to pin which workspace/project a directory belongs to. Directly relevant to our manifest's "only if this path exists" condition — a marker is more explicit than a path test.
  • bootstrap seeds pages from git log, README, docs/, module headers. The thing we would want when adding a new machine or repo.

His position, stated up front: not a fan of MCP, and never was. So this is a source of ideas, not a thing to adopt. Do not open tomorrow by proposing we install it. Harvest the taxonomy and the concepts, build our own on plain files.

The real decision: it is a running service (daemon, SQLite, FTS5, embeddings, MCP, hooks). Ours is plain files and symlinks, readable with cat, and works when nothing is installed. That simplicity is a feature, especially given today's "code on disk is not what is running here" problem. Options: adopt it, borrow the taxonomy only, or stay flat and revisit when the flat file gets unreadable.

Open questions

  • Which files are genuinely universal vs this-machine-only? Right now officer.dev/CLAUDE.md is the only machine-specific one, but the platform-appstore/ set is a candidate and was never folded in.
  • Should settings.json / hooks be managed here too, or only .md files? The repo is named for the docs but already carries tools/.
  • Bootstrapping the bootstrap: the machine needs git and the repo URL before any of this runs. Worth a one-line curl | sh, or deliberately not.