Summary
Convert home/.claude/CLAUDE.md (and home/IDENTITY.md, which it symlinks to) from tracked operator files into per-operator local files, with home/.claude/CLAUDE.md.example as the tracked template. make install bootstraps the operator's local copy from the example on a fresh install.
Why
Currently home/.claude/CLAUDE.md and home/IDENTITY.md are tracked in the repo, which means operator-specific content (personal voice rules, individual preferences, working-discipline anecdotes) ends up in version control across every operator's checkout. The fix is the same .example-then-bootstrap pattern already used for home/.claude/MEMORY.md.example, applied to the rule surface.
This is the first phase of #396; subsequent phases gate the memory subsystem on MEMORY_ENABLED, drive write routing from a runtime context flag, and migrate existing MEMORY.md content to Qdrant.
Scope
- Draft
home/.claude/CLAUDE.md.example containing only universal content: hard rules (no source modification, no EnterPlanMode, symlink target convention), public-facing content rules, the conditional memory write rule that routes new facts to either the API or MEMORY.md based on a runtime [Memory subsystem: ...] line, behavioral rules, and the full API reference block (scheduling, send-message, send-file, memory, external services).
git rm --cached home/.claude/CLAUDE.md home/IDENTITY.md. Update .gitignore so both stay untracked and the new .example is tracked.
- Extend
install.py so make install on a fresh clone:
- Copies
home/.claude/CLAUDE.md.example to home/IDENTITY.md when the operator has no IDENTITY.md yet.
- Recreates
home/.claude/CLAUDE.md as a symlink to ../IDENTITY.md when missing or pointing elsewhere.
- Skips both steps idempotently when the operator's setup is already valid.
- Refresh
home/.claude/MEMORY.md.example with a brief role description and starter section headings, since the file's effective role shifts (it becomes the seed file for new operators and the migration source when memory is enabled).
Out of scope
- Gating
home/.claude/CLAUDE.md injection or any other code path on memory.is_enabled(). Tracked under a sibling sub-issue.
- One-time MEMORY.md to Qdrant migration tooling. Tracked under a sibling sub-issue.
- Mode-switch verification harness. Tracked under a sibling sub-issue.
- Per-operator MEMORY.md triage (rule blocks vs fact blocks). Operator-side, not a code change.
Acceptance
git ls-files home/.claude/CLAUDE.md home/IDENTITY.md returns empty.
git ls-files home/.claude/CLAUDE.md.example returns the new path.
home/.claude/CLAUDE.md.example contains zero operator-specific content (no personal names, OS usernames, internal workflow vocabulary, or operator-history anecdotes).
make install on a fresh clone leaves the operator with a writable home/IDENTITY.md and a working home/.claude/CLAUDE.md symlink pointing at it.
- Re-running
make install is a no-op when the operator's setup is already valid.
Refs #396.
Summary
Convert
home/.claude/CLAUDE.md(andhome/IDENTITY.md, which it symlinks to) from tracked operator files into per-operator local files, withhome/.claude/CLAUDE.md.exampleas the tracked template.make installbootstraps the operator's local copy from the example on a fresh install.Why
Currently
home/.claude/CLAUDE.mdandhome/IDENTITY.mdare tracked in the repo, which means operator-specific content (personal voice rules, individual preferences, working-discipline anecdotes) ends up in version control across every operator's checkout. The fix is the same.example-then-bootstrap pattern already used forhome/.claude/MEMORY.md.example, applied to the rule surface.This is the first phase of #396; subsequent phases gate the memory subsystem on
MEMORY_ENABLED, drive write routing from a runtime context flag, and migrate existing MEMORY.md content to Qdrant.Scope
home/.claude/CLAUDE.md.examplecontaining only universal content: hard rules (no source modification, noEnterPlanMode, symlink target convention), public-facing content rules, the conditional memory write rule that routes new facts to either the API or MEMORY.md based on a runtime[Memory subsystem: ...]line, behavioral rules, and the full API reference block (scheduling, send-message, send-file, memory, external services).git rm --cached home/.claude/CLAUDE.md home/IDENTITY.md. Update.gitignoreso both stay untracked and the new.exampleis tracked.install.pysomake installon a fresh clone:home/.claude/CLAUDE.md.exampletohome/IDENTITY.mdwhen the operator has noIDENTITY.mdyet.home/.claude/CLAUDE.mdas a symlink to../IDENTITY.mdwhen missing or pointing elsewhere.home/.claude/MEMORY.md.examplewith a brief role description and starter section headings, since the file's effective role shifts (it becomes the seed file for new operators and the migration source when memory is enabled).Out of scope
home/.claude/CLAUDE.mdinjection or any other code path onmemory.is_enabled(). Tracked under a sibling sub-issue.Acceptance
git ls-files home/.claude/CLAUDE.md home/IDENTITY.mdreturns empty.git ls-files home/.claude/CLAUDE.md.examplereturns the new path.home/.claude/CLAUDE.md.examplecontains zero operator-specific content (no personal names, OS usernames, internal workflow vocabulary, or operator-history anecdotes).make installon a fresh clone leaves the operator with a writablehome/IDENTITY.mdand a workinghome/.claude/CLAUDE.mdsymlink pointing at it.make installis a no-op when the operator's setup is already valid.Refs #396.