[FEATURE] Mods API: let a nested Claude Code session read its parent's session id and plugin state
Preflight Checklist
- [x] I have searched existing requests and this feature hasn't been requested yet
- [x] This is a single feature request (not multiple features)
Problem Statement
When the model runs claude -p "..." through Bash, the child session starts with empty plugin state. A guard mod in the parent cannot hand its open blocks to the child. The child's copy of the mod cannot learn that it has a parent.
Claude Code 2.1.296 (macOS) describes $.state as "Named values held by the host for the session, each with a version". Its reader has no session parameter:
get: <P extends keyof PluginState & string, K extends keyof PluginState[P] & string>(ref: StateRef<P, K>) => Promise<StateRead<StateValue<P, K>>>;
$.session has id() and no parent.
Proposed Solution
- Record the parent session id for every Claude Code process that a session's tools start: the
claudeCLI, npx-launched Claude Code, and Agent SDK launches. The carrier must not change the child's own behavior (see #67603). $.session.parent(): Promise<{ sessionId: string } | undefined>.$.state.get(ref, { session: 'parent' }): read only, own keys, while the parent runs. The engine verifies the parent, so a forged variable cannot read another session's state.
Alternative Solutions
- The parent mod can export state with
$.env.setfor the child's$.env.get. Every Bash child and MCP server then sees the blocked paths. A large value risksE2BIG.env -idrops it. - The Bash shell carries the undocumented
CLAUDE_CODE_SESSION_ID. InheritedCLAUDE_CODE_*variables have broken nested sessions before (#96959). - A hidden
--parent-session-idflag ("for analytics correlation") reaches teammate panes only. Mods cannot read it.
Priority
Medium - Would be very helpful
Feature Category
Developer tools/SDK
Use Case Example
Arrester (github.com/dot-agi/arrester) blocks detours after a hook, rule or classifier refusal. Its README lists a known limit: a nested claude command "does not inherit the open blocks". With this API, the child's Arrester reads the parent's open blocks at session.start.
Additional Context
Related, narrower: #99920 (id after a fork), #78303 (headless signal), #42656 (/branch parent id).