[FEATURE] Expose project root to Task subagents (CLAUDE_PROJECT_DIR or equivalent)
Problem Statement
Subagents spawned via the Task tool have no reliable way to determine the project root directory.
CLAUDE_PROJECT_DIRis documented as available to hook processes, but it is empty in subagent environments (verified by runningenv | grep CLAUDEinside a Task subagent).- Subagents inherit
PWDfrom wherever the parent agent happens to be at invocation time. In monorepos or projects with nested directories, the parent agent is oftencd'd into a subdirectory likeapps/web/orservices/backend/, so the subagent starts there too. - This means any subagent that needs to read/write project-root-relative files (e.g.,
.claude/audit-prompt.md,docs/plans/*.md) must reinvent project root discovery.
This is the same root cause behind several existing issues:
- #12748 — Task tool lacks
cwdparameter - #25140 —
memory: projectresolves path relative to subagent's perceived root instead of git root - #25569 — subagent environment doesn't inherit main session's configuration
Proposed Solution
Minimal: Set CLAUDE_PROJECT_DIR (or a new dedicated variable like CLAUDE_PROJECT_ROOT) in the subagent's environment, matching what hooks already receive. The value should be the same project root the main agent was launched in.
This would allow subagents to:
ROOT="$CLAUDE_PROJECT_DIR"
cat "$ROOT/.claude/audit-prompt.md"
For subagents without Bash access (using only Read/Write/Glob/Grep), the variable could be exposed as part of the subagent's system context (e.g., in the environment description that already mentions "Primary working directory").
Complementary (aligns with #12748): Also support a cwd parameter on the Task tool so the caller can explicitly set the subagent's working directory. But even with cwd, an env var for the original project root is still valuable — cwd controls where the agent starts, while the project root is a stable reference point.
Alternative Solutions
Current workarounds, all unsatisfying:
| Workaround | Downside |
|---|---|
| git rev-parse --show-toplevel in subagent | Requires Bash access; fails in non-git projects |
| Caller passes root path in the prompt message | Relies on caller remembering; fragile and error-prone |
| Glob for ../.git, ../../.git upward | Slow, unreliable, hacky |
| SubagentStart hook injecting additionalContext | Undocumented for this purpose; one more moving part |
We currently use a combination of all four depending on the subagent's available tools, which is exactly the kind of complexity this feature would eliminate.
Use Case Example
We run a plan-audit system with custom subagents:
- audit subagent needs to read
$ROOT/.claude/audit-prompt.mdand write$ROOT/.claude/.audit-not-passed - plan-writer subagent (Read/Glob/Grep/Write only, no Bash) needs to read
$ROOT/.claude/plan-files.txtand write$ROOT/.claude/audit-prompt.md - Main agent works in
apps/web/→ spawns plan-writer → plan-writer's CWD isapps/web/→ it readsapps/web/.claude/plan-files.txt(wrong file or nonexistent) instead of$ROOT/.claude/plan-files.txt
This has caused repeated real-world failures where subagents silently read stale files from subdirectories or fail to find files at all.
Additional Context
- Hooks already receive
CLAUDE_PROJECT_DIR(docs). Subagents not receiving it appears to be an oversight rather than an intentional design choice. - The subagent environment already injects
CLAUDECODE=1andCLAUDE_CODE_ENTRYPOINT=cli, so the mechanism to set env vars exists. - This would benefit anyone building custom subagent workflows via the
agents/directory, not just our specific use case.
This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗