Surfaced by the #667 live smoke (merged in docs/specs/2026-08-13-agent-control-channel-design.md, section "Smoke Test: claude approve/deny of a HELD peer message (2026-08-17)").
Symptom
A claude process launched from a shell that is itself running inside a Claude Code session comes up believing it is a child of the launching session. Observed on Claude Code 2.1.233:
- it registers its
.sock and inbox .key under ~/.claude/sessions/
- but it never writes its
<pid>.json registry entry
- its transcript banner reads:
Transcript saving is off — inherited CLAUDE_CODE_CHILD_SESSION marker
Cause
nohup claude ... & (or any spawn) inherits the parent session's environment, including:
CLAUDE_CODE_CHILD_SESSION, CLAUDE_CODE_MESSAGING_SOCKET, CLAUDE_CODE_MESSAGING_TOKEN, CLAUDE_CODE_SESSION_ID, CLAUDE_PID
The child sees the child-session marker and skips its own registration.
Fix that worked
Spawn with a sanitized environment:
env -i HOME="$HOME" PATH="$PATH" TERM="$TERM" CLAUDE_CODE_HARBOR_KITE=1 claude ...
After which registration behaved normally.
Why this matters for squadrant
The daemon itself is not directly exposed — squadrantd spawns crews from its own Node process, not from inside a Claude Code session. Verified, not assumed.
But any path that shells out to claude from within another Claude Code session hits this silently:
- a crew spawning a crew
- a hook that invokes
claude
- a plugin or script run from a captain/crew pane
- anything a user runs by hand from inside a session
The failure is silent: no error, the session appears to work, but it is invisible to ~/.claude/sessions/ — which is exactly the registry #667 slice 1's ClaudePeerRegistrySource reads for liveness. An unregistered session is permanently unknown to that source.
Suggested handling
- Audit any code path that launches
claude for inherited CLAUDE_CODE_* and strip it explicitly.
- Consider a shared spawn helper that always clears the marker set, so this cannot be reintroduced per-call-site.
- Document the trap for anyone writing tooling around
claude.
Surfaced by the #667 live smoke (merged in
docs/specs/2026-08-13-agent-control-channel-design.md, section "Smoke Test: claude approve/deny of a HELD peer message (2026-08-17)").Symptom
A
claudeprocess launched from a shell that is itself running inside a Claude Code session comes up believing it is a child of the launching session. Observed on Claude Code 2.1.233:.sockand inbox.keyunder~/.claude/sessions/<pid>.jsonregistry entryTranscript saving is off — inherited CLAUDE_CODE_CHILD_SESSION markerCause
nohup claude ... &(or any spawn) inherits the parent session's environment, including:CLAUDE_CODE_CHILD_SESSION,CLAUDE_CODE_MESSAGING_SOCKET,CLAUDE_CODE_MESSAGING_TOKEN,CLAUDE_CODE_SESSION_ID,CLAUDE_PIDThe child sees the child-session marker and skips its own registration.
Fix that worked
Spawn with a sanitized environment:
After which registration behaved normally.
Why this matters for squadrant
The daemon itself is not directly exposed —
squadrantdspawns crews from its own Node process, not from inside a Claude Code session. Verified, not assumed.But any path that shells out to
claudefrom within another Claude Code session hits this silently:claudeThe failure is silent: no error, the session appears to work, but it is invisible to
~/.claude/sessions/— which is exactly the registry #667 slice 1'sClaudePeerRegistrySourcereads for liveness. An unregistered session is permanentlyunknownto that source.Suggested handling
claudefor inheritedCLAUDE_CODE_*and strip it explicitly.claude.