[FEATURE] Expose project root to Task subagents (CLAUDE_PROJECT_DIR or equivalent)

Resolved 💬 4 comments Opened Feb 17, 2026 by ZihaoZhou Closed Mar 19, 2026

Problem Statement

Subagents spawned via the Task tool have no reliable way to determine the project root directory.

  • CLAUDE_PROJECT_DIR is documented as available to hook processes, but it is empty in subagent environments (verified by running env | grep CLAUDE inside a Task subagent).
  • Subagents inherit PWD from wherever the parent agent happens to be at invocation time. In monorepos or projects with nested directories, the parent agent is often cd'd into a subdirectory like apps/web/ or services/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 cwd parameter
  • #25140 — memory: project resolves 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:

  1. audit subagent needs to read $ROOT/.claude/audit-prompt.md and write $ROOT/.claude/.audit-not-passed
  2. plan-writer subagent (Read/Glob/Grep/Write only, no Bash) needs to read $ROOT/.claude/plan-files.txt and write $ROOT/.claude/audit-prompt.md
  3. Main agent works in apps/web/ → spawns plan-writer → plan-writer's CWD is apps/web/ → it reads apps/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=1 and CLAUDE_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.

View original on GitHub ↗

This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗