AgentDefinition: opt-in project settings inheritance for subagent sessions (closes subagent hook bypass)
Tested on: Claude Code v2.1.172 (released 2026-06-10)
Distinct from: v2.1.172's pre-warmed-worker settings-leak fix — that change isolates background agents from other projects' .mcp.json approvals on a reused worker. This request is the opposite direction: opt-in inheritance of the parent project's .claude/settings.json hooks into teammate subagent sessions within the same project. The v2.1.172 changelog and the May 2026 comment on #30703 (against v2.1.150) confirm the per-agent hooks-inheritance gap is unaddressed as of v2.1.172.
---
Summary
Hooks configured at the project level (.claude/settings.json PreToolUse / PostToolUse) silently do not fire inside subagent sessions spawned via the Agent tool or AgentDefinition. The subagent process runs in an isolated temporary directory, loads no project-scoped settings, and CLAUDE_PROJECT_DIR is unset at the spawn boundary. The result is that every tool call inside a subagent bypasses the project's deny-first PreToolUse classifier and produces no PostToolUse audit entry.
This issue proposes an opt-in addition to AgentDefinition — projectDir, or equivalently inheritProjectSettings — that causes the subagent session to load the parent project's .claude/settings.json before any tool dispatch.
Direct evidence of the gap is in this comment chain and reproduces on claude-code 2.1.x. Related prior reports: #27153, #27655, #30260, #30703. The same configuration-not-consulted class of issue produced CVE-2025-59536 (severity 8.7) in #32376; this is a feature request, not a security report, but the class of bug is the same and the resolution shape (load the configuration that the runtime currently ignores) is analogous.
Evidence
1. The SDK types already accommodate the fix
@anthropic-ai/claude-agent-sdk already exposes BaseHookInput.agent_id (carrying the subagent identifier), SubagentStartHookInput, and SubagentStopHookInput. These types exist precisely so subagent lifecycle events can be observed. What is missing is the one settings-propagation step that would cause PreToolUse / PostToolUse hooks defined in the parent project's .claude/settings.json to load and run during a subagent session.
In other words: the fix is one settings-propagation hop, not an architectural redesign.
2. Reproduction (minimal)
- Create a project with
.claude/settings.jsoncontaining aPreToolUsehook that writes a line to/tmp/observed.logand exits 0. - From inside a Claude Code session in that project, ask the assistant to spawn an
Agentsubagent that runs any tool (e.g.Readon a file in the project). - Observe
/tmp/observed.log. The parent-session tool calls appear; the subagent-session tool calls do not.
3. Net effect on safety boundaries
For projects that use .claude/settings.json to enforce a deny-first classifier, the subagent surface is invisible to the classifier and to any append-only audit log driven by PostToolUse. Subagents whose AgentDefinition.tools list is explicit (e.g. [Read] only) cannot be enforced from the parent project's side, because the parent project's enforcement layer is the hook system that does not fire.
Proposed API
Primary proposal — AgentDefinition.projectDir
interface AgentDefinition {
// ... existing fields ...
projectDir?: string; // absolute path; when set, subagent loads `<projectDir>/.claude/settings.json` before any tool dispatch
}
Behaviour when set: the subagent process resolves <projectDir>/.claude/settings.json, loads its PreToolUse / PostToolUse (and any other hook keys) into the subagent's hook registry, sets CLAUDE_PROJECT_DIR=<projectDir> in the subagent environment, and proceeds. Default: unset — preserves current behaviour exactly.
Alternative — AgentDefinition.inheritProjectSettings: boolean
If projectDir is felt to be too coupled to filesystem semantics, a boolean opt-in that inherits the parent session's resolved project settings (whichever directory the parent was launched from) is acceptable. The contract is the same: opt-in, default off, no change to existing subagent behaviour, no change to permission model.
(A per-subagent hooks array inside AgentDefinition was considered and is not part of this request. It would duplicate the settings-file schema and increase maintenance surface for negligible benefit beyond the projectDir path above.)
Backward compatibility
- Opt-in. Default off. Existing subagent definitions get exactly the current behaviour.
- No change to the permission model (
permissionMode,allowedTools,disallowedTools). - No change to the SDK's public types beyond the new optional field.
- No change to the hook input schemas (
BaseHookInput.agent_idalready carries the disambiguator).
Production-impact paragraph
I'm operating a deny-first PreToolUse classifier in a regulated environment where every tool call must produce an audit entry. The subagent bypass forces us to disable subagents entirely until upstream gains opt-in settings propagation. Specifically, our PreToolUse hook denies a deterministic list of destructive and self-modifying patterns (UNCONDITIONAL_BLOCK_PATTERNS), and our PostToolUse hook writes every tool call to an append-only audit log. Because subagent sessions load no project settings, neither hook fires for any subagent tool call — destructive operations, credential reads, and self-modifications would all be invisible to the safety boundary. We are not in a position to ship a workflow that relies on subagents while this gap exists.
Current workaround
Our deterministic classifier now lists the Agent tool name in its UNCONDITIONAL_BLOCK_PATTERNS and denies any subagent spawn at PreToolUse with reason UNCONDITIONAL_BLOCK: subagent_disabled. This restores the deny-first floor at the cost of giving up subagents entirely. We will lift the block the moment opt-in settings propagation ships upstream.
Proposed acceptance test
Re-run the reproduction in §Evidence #2 with projectDir set on the AgentDefinition. The expected result is that /tmp/observed.log records at least one line per subagent tool call. A passing run of that test is what we'd consider the feature shipped.
Related issues (for cross-link after filing)
- #27153
- #27655
- #30260
- #30703
(CVE-2025-59536 / #32376 is mentioned in §Summary for class-of-bug context only; do not cross-link a feature request to a closed security issue.)
Out of scope
- Inheriting settings by default. Default-off is correct.
- A per-subagent arbitrary hooks array (would duplicate settings schema).
- Fixes to the four cross-linked issues. Those are linked for context.
Author
@jackalai — operator of an agentic harness on claude-code. Reachable via GitHub or the contact email on profile.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗