claude-code - 💡(How to fix) Fix [BUG] WorktreeCreate hook stdin payload doesn't match documentation — Workflow runtime sends 'name', docs say 'worktree_name' + 'base_path' + 'source_ref'

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

The hooks documentation (code.claude.com/docs hooks reference, WorktreeCreate section) specifies this stdin payload, with the hook expected to construct the path from base_path + worktree_name and honor source_ref:

{
  "session_id": "...",
  "transcript_path": "...",
  "cwd": "...",
  "hook_event_name": "WorktreeCreate",
  "worktree_name": "feat-auth",
  "source_ref": "main",
  "base_path": "<project>/.worktrees"
}

What the Workflow runtime (agents spawned with opts.isolation: 'worktree' from a Workflow script) actually delivers on stdin in 2.1.165 is:

{ session_id, transcript_path, cwd, hook_event_name, name }

i.e. the worktree name arrives under name (not worktree_name), and base_path and source_ref are absent entirely. A hook written against the documented schema fails on every Workflow-isolated agent; the agent then dies pre-launch and the workflow's parallel() slot resolves to null.

(Older third-party hooks in the wild were written against an apparently earlier shape that included an explicit worktree_path — that field isn't sent anymore either, so there appear to be at least three payload generations across versions/entry-points.)

Root Cause

The hooks documentation (code.claude.com/docs hooks reference, WorktreeCreate section) specifies this stdin payload, with the hook expected to construct the path from base_path + worktree_name and honor source_ref:

{
  "session_id": "...",
  "transcript_path": "...",
  "cwd": "...",
  "hook_event_name": "WorktreeCreate",
  "worktree_name": "feat-auth",
  "source_ref": "main",
  "base_path": "<project>/.worktrees"
}

What the Workflow runtime (agents spawned with opts.isolation: 'worktree' from a Workflow script) actually delivers on stdin in 2.1.165 is:

{ session_id, transcript_path, cwd, hook_event_name, name }

i.e. the worktree name arrives under name (not worktree_name), and base_path and source_ref are absent entirely. A hook written against the documented schema fails on every Workflow-isolated agent; the agent then dies pre-launch and the workflow's parallel() slot resolves to null.

(Older third-party hooks in the wild were written against an apparently earlier shape that included an explicit worktree_path — that field isn't sent anymore either, so there appear to be at least three payload generations across versions/entry-points.)

Fix Action

Fix / Workaround

Suggested fix

Either send the documented fields (worktree_name, base_path, source_ref) from the Workflow runtime path, or update the docs to enumerate the real per-entry-point payloads. Given #36205/#39281/#29716/#57209 show Worktree hook dispatch differs per entry point, a single documented schema that all entry points actually conform to would resolve the whole family.

Related

  • #37611, #36205, #39281, #29716, #57209 — Worktree hook dispatch inconsistencies across entry points
  • Companion report: #65645 (Workflow-agent worktrees never cleaned up)

Code Example

{
  "session_id": "...",
  "transcript_path": "...",
  "cwd": "...",
  "hook_event_name": "WorktreeCreate",
  "worktree_name": "feat-auth",
  "source_ref": "main",
  "base_path": "<project>/.worktrees"
}

---

{ session_id, transcript_path, cwd, hook_event_name, name }

---

// minimal repro hook
const fs = require('fs');
const data = JSON.parse(fs.readFileSync(0, 'utf8') || '{}');
if (!data.worktree_name || !data.base_path) {
  process.stderr.write('got keys: ' + Object.keys(data).join(', ') + '\n');
  process.exit(1);
}

---

parallel[0] failed: WorktreeCreate hook failed: ... : got keys: session_id, transcript_path, cwd, hook_event_name, name
RAW_BUFFERClick to expand / collapse

Environment

  • Claude Code: 2.1.165
  • Platform: Windows 11 Home (10.0.26200)
  • git: 2.45.1.windows.1
  • Hook: user-level WorktreeCreate command hook in ~/.claude/settings.json

Summary

The hooks documentation (code.claude.com/docs hooks reference, WorktreeCreate section) specifies this stdin payload, with the hook expected to construct the path from base_path + worktree_name and honor source_ref:

{
  "session_id": "...",
  "transcript_path": "...",
  "cwd": "...",
  "hook_event_name": "WorktreeCreate",
  "worktree_name": "feat-auth",
  "source_ref": "main",
  "base_path": "<project>/.worktrees"
}

What the Workflow runtime (agents spawned with opts.isolation: 'worktree' from a Workflow script) actually delivers on stdin in 2.1.165 is:

{ session_id, transcript_path, cwd, hook_event_name, name }

i.e. the worktree name arrives under name (not worktree_name), and base_path and source_ref are absent entirely. A hook written against the documented schema fails on every Workflow-isolated agent; the agent then dies pre-launch and the workflow's parallel() slot resolves to null.

(Older third-party hooks in the wild were written against an apparently earlier shape that included an explicit worktree_path — that field isn't sent anymore either, so there appear to be at least three payload generations across versions/entry-points.)

Reproduction

  1. Register a WorktreeCreate hook whose failure message echoes the keys it received:
// minimal repro hook
const fs = require('fs');
const data = JSON.parse(fs.readFileSync(0, 'utf8') || '{}');
if (!data.worktree_name || !data.base_path) {
  process.stderr.write('got keys: ' + Object.keys(data).join(', ') + '\n');
  process.exit(1);
}
  1. Run any Workflow script that spawns an agent with { isolation: 'worktree' }.

Expected

Payload matches the documented schema (worktree_name, base_path, source_ref), or the docs describe the per-entry-point payloads that are actually sent.

Actual

Workflow fails with (verbatim from the workflow failure log):

parallel[0] failed: WorktreeCreate hook failed: ... : got keys: session_id, transcript_path, cwd, hook_event_name, name

Impact

  • Any WorktreeCreate hook written from the documentation breaks Workflow worktree isolation completely (all isolated agents fail pre-launch).
  • Without base_path, the hook must hard-code knowledge that workflow worktrees live under <cwd>/.claude/worktrees/.
  • Without source_ref, the hook cannot honor the documented worktree.baseRef semantics ("fresh" vs "head") and has to guess; for agent isolation, HEAD is the only sensible default, but that's an inference, not a contract.

Suggested fix

Either send the documented fields (worktree_name, base_path, source_ref) from the Workflow runtime path, or update the docs to enumerate the real per-entry-point payloads. Given #36205/#39281/#29716/#57209 show Worktree hook dispatch differs per entry point, a single documented schema that all entry points actually conform to would resolve the whole family.

Related

  • #37611, #36205, #39281, #29716, #57209 — Worktree hook dispatch inconsistencies across entry points
  • Companion report: #65645 (Workflow-agent worktrees never cleaned up)

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING