-
Notifications
You must be signed in to change notification settings - Fork 0
home folder claude requirements
Status: research / decided
Date: 2026-06-22
Decision: Surface everything joinable (option 3) via targeted rw bind-mounts, with the
one format-parsing step (history.jsonl merge) quarantined as a guarded, disable-able teardown.
Run the container working dir at the same absolute path as the host (path mirroring) — this
deletes the slug-remap hazard and keeps surfaced history host-coherent (see Hazard A).
Isolated stacks do not mount host ~/.claude wholesale (no transparent-style mirror). But we
still want a project's history — conversation transcripts, file-rewind backups, subagent runs,
per-project memory — to persist to the host's global Claude store so it survives throwaway
containers and shows up alongside non-containerised work. The task: identify the exact subpaths
to bind-mount, and the keying hazards that make a naive mount wrong.
Top-level dirs/files, classified by whether they hold per-project history vs config/cache:
| Path | Kind | Keyed by | Surface? |
|---|---|---|---|
projects/<slug>/ |
History — transcripts (<uuid>.jsonl) + memory/
|
project path slug | Yes |
file-history/<uuid>/ |
History — pre-edit file snapshots (<hash>@v1/@v2), powers rewind/undo |
session UUID | Yes |
tasks/<uuid>/ |
History — subagent/Task run records | session UUID | Yes |
session-env/<uuid>/ |
History — sessionstart-hook-*.sh env captures |
session UUID | Yes |
todos/<uuid>… |
History — per-session todo lists (empty on this box, session-keyed by design) | session UUID | Yes |
history.jsonl |
History — every prompt typed; each line has "project" + "sessionId"
|
global append, project field | Yes, guarded |
plans/*.md |
History — plan-mode artifacts, named by random slug | no on-disk key (project only in content) | Deferred — see Ambiguous |
shell-snapshots/snapshot-zsh-<ts>-<rand>.sh |
History-ish — shell env snapshots | timestamp, not session | No (can't map cleanly) |
sessions/<number>.json |
Session group state | numeric id (terminal/tab group) | No |
agents/ commands/ skills/ rules/ hooks/ plugins/ |
Config | — | No |
cache/ .search_cache/ paste-cache/ downloads/ stats-cache.json debug/ ide/ chrome/ backups/ context-mode/ sandbox/ |
Cache / runtime | — | No |
.credentials.json settings*.json |
Secrets / config | — | No (credentials handled by existing auth-seed layer) |
Only projects/<slug>/ is keyed directly by project path. Everything else historical is keyed
by session UUID, generated at session start inside the container. The UUID→project mapping
lives in two places:
- the
.jsonlfilenames underprojects/<slug>/(filename = session UUID), and -
history.jsonllines ("project"+"sessionId").
The slug is derived from the absolute cwd. Evidence — both already exist on this host:
projects/-home-mcrowe-Programming-Personal-code-container/ ← host runs (cwd /home/mcrowe/…)
projects/-container-mcrowe-Programming-Personal-code-container/ ← container (cwd /container/mcrowe/…)
Critically, the path leak is not just the slug — every transcript line embeds the cwd-rooted
absolute path, and so do file-history references. Confirmed on this host:
host slug transcript: "cwd":"/home/mcrowe/Programming/Personal/code-container"
"file_path":"/home/mcrowe/Programming/Personal/code-container/Dockerfile"
container slug transcript: "cwd":"/container/mcrowe/Programming/Personal/code-container"
If the container runs at a different path (/container/mcrowe/…), the surfaced history is
internally consistent but host-invalid: clickable file_path:line refs resolve to a
non-existent /container/…, rewind blobs key to paths the host can't act on, and a later host
session sees its projects/ dir split across two slugs.
Decision: mirror the path. Run the container working dir at the same absolute path as the
host (/home/mcrowe/Programming/Personal/code-container inside, byte-for-byte). This:
- deletes the remap entirely — the
projects/mount becomes plain same-path → same-path, with no dependency on CC's path→slug algorithm; - keeps every recorded path host-coherent;
- makes the DooD pattern clean — container
PWD== hostPWD, so-v $PWD:$PWDworks with no translation (satisfies §15's host-absolute-path rule directly); - coalesces transparent + isolated runs of the same project into one history — which is the goal ("this project's history, regardless of how it ran").
Isolation is about config (skills/MCP/memory/profile), not the working-dir path; mirroring the
path leaks no host config, so the isolation guarantee is intact. Only ~/.claude config stays
synthetic — not the project path. The current -container-mcrowe-… behaviour is therefore a
change to make, not the target state.
file-history/, tasks/, session-env/, todos/ are flat <uuid>/ at top level. You can't
pre-create a per-project mount (UUID unknown until the session starts), so you mount the parent
dir whole. This is collision-free (everything is UUID-namespaced; new sessions just add dirs).
Cost: the container can read other projects' UUID dirs — a read-side visibility leak of file-backup
blobs, not config or secrets. Accepted.
Never rw-bind it (same whole-file-rewrite race we already rejected for .claude.json). Surface it
by append-merging lines filtered on "project" at teardown.
Brittleness is not "more mounts." A bind-mount makes zero assumptions about dir contents: if a
future Claude Code release renames tasks/, the mount becomes an inert no-op and the new dir goes
uncaptured — silent degradation, not container failure. So the four UUID-keyed mounts are
effectively free in fragility terms.
The only genuinely brittle piece is the history.jsonl append-merge, because it parses an
undocumented line schema. That risk is one isolated component.
Two fragilities are shared by options 2 and 3 equally, so they don't favour the smaller option: the slug-remap (depends on CC's path→slug algorithm) and the UUID-keying convention.
Net: take the full surface, quarantine the one parsing step.
-
Run the container at the host project path (mirroring), then mount the project dir same-path → same-path — no slug remap:
--workdir /home/mcrowe/Programming/Personal/code-container \ -v $HOST_CLAUDE/projects/-home-mcrowe-…-code-container \ :$CONTAINER_CLAUDE/projects/-home-mcrowe-…-code-container:rwSlug is identical both sides. Surfaces transcripts + per-project
memory/. (DooD rule satisfied — source is a host absolute path, and containerPWD== hostPWD.) -
Mount the four UUID-keyed parent dirs rw (fail-safe, collision-free):
file-history/,tasks/,session-env/,todos/. -
history.jsonl= guarded, disable-able teardown step. Append only lines whose"project"matches the project, wrapped so a parse failure logs a warning and no-ops rather than corrupting the host file. Ship it disabled until the format is confirmed; a CC schema change can then only break this one feature, not the container. -
Make the mount set data-driven — a list/map in config, not inline
-vflags — so a future CC layout change is a one-line manifest edit, not a code change. -
Add a §18 oracle assertion — after a throwaway session, assert the host now has
file-history/<new-uuid>/andprojects/<slug>/<new-uuid>.jsonl. Silent upstream renames then surface as a failing test (red CI) instead of silent data loss.
-
plans/*.md— plan-mode artifacts carry no on-disk project key (random-slug filenames; project only referenced in content). Surfacing would require content inspection or mtime↔session correlation. Deferred. -
shell-snapshots/(timestamp-keyed) andsessions/<number>.json(terminal-group-keyed) — not cleanly mappable to a project. Not surfaced.
-
fdskim of~/.claudetop two levels (dirs + root files). - Confirmed session-UUID keying of
file-history/,session-env/,tasks/by sampling entries. - Confirmed
projects/<slug>/<uuid>.jsonlfilename = session UUID (carriessessionId). - Confirmed
history.jsonlline schema carries"project"+"sessionId". - Confirmed dual-slug evidence (
-home-mcrowe-…and-container-mcrowe-…) inprojects/. -
todos/empty on this host but session-keyed by design (noted, not assumed populated).
Start Here
Guides
- Recipe authoring
- Service authoring
- Stacks
- Extending stacks (proposed)
- Recipe catalog
- System prompt & rules (proposed)
- Secrets
- AWS SSO
- Pulumi (host login forwarding)
- Egress & exposing services
- Container filesystem
- Git hooks
- Troubleshooting
- Pin management (harnessed update)
Codebase Map
Planning & Roadmap
- open work: GitHub Issues
Research & Prompts
- research/ (home-folder requirements per harness, browse in-repo)
- prompts/ (reusable prompt templates, browse in-repo)