Session & Worktree Internals
Contributor reference for the session layer: Claude conversation resume, worktree creation, scratch-session cleanup, and MCP forwarding. Users want the corresponding guides (Session Resume, Git Worktrees, Scratch Sessions, MCP Servers).
Claude conversation resume
aoe persists each Claude Code session’s conversation id so a session resumes the same transcript across restarts. The flow: aoe generates a UUID, launches claude --session-id <uuid>, records it, and relaunches with claude --resume <uuid>.
Two mechanisms keep the recorded id current as Claude rotates it (on /clear, --fork-session, --continue):
- Hook sidecar (primary). aoe installs
SessionStartandUserPromptSubmithooks in~/.claude/settings.json. They extractsession_idfrom Claude’s stdin and write it atomically to/tmp/aoe-hooks-<euid>/<instance-id>/session_id(per-user host base, issue #1844). The poller reads this before scanning, so rotations are caught within ~1 poll tick (~2s). The sidecar is host-only. - Filesystem-scan fallback. If the sidecar is absent, stale (>5 min), or invalid, the poller scans
~/.claude/projects/<project>/for the most recent.jsonl. Siblings sharing a project path are disambiguated via the tmux envAOE_CAPTURED_SESSION_ID. For Docker sessions the scan runs in-container viadocker exec(5s cap).
resume_intent is decoupled from the poller’s observed id so a peer CLI write isn’t undone and a daemon restart can’t resurrect a cleared value. The post-launch persist of the new id plus the one-shot Cleared auto-promote land in a single atomic flock, preserving a concurrent peer write during the launch window.
Worktree creation
git worktree add only checks out tracked files; it does not copy node_modules, .venv, or target/, so creation is cheap and network IO (git fetch, git submodule update) dominates almost every slow run. For multi-repo workspaces, the per-repo create_worktree calls run concurrently via std::thread::scope. See Git Worktrees for the bare-repo layout aoe auto-detects.
Scratch-session cleanup
Scratch sessions store their working dir under the app data dir (not /tmp) so it survives reboots and stays inside the namespace the daemon sweeps. Delete-time cleanup runs only when the session’s scratch flag is true AND the path lives under the scratch root: a tampered project_path pointing at, say, /etc is left alone. This invariant is what makes the orphan sweep safe to run unattended.
MCP server forwarding
Native agent MCP configs are re-read live at session start, so edits apply on the next session; aoe only reads these files, never writes them. Precedence is per-server, not whole-file, and overrides are logged. Project-local .mcp.json from a repo must sit behind the same repo-trust gate as lifecycle hooks (an untrusted clone could otherwise launch commands on session open); per-profile and project-local source layers are tracked as higher layers.