Skip to content

fix: restore automatic plan approval on Claude Code 2.1.199+#235

Draft
blimmer wants to merge 2 commits into
mainfrom
fix/claude-exit-plan-approve-updated-input
Draft

fix: restore automatic plan approval on Claude Code 2.1.199+#235
blimmer wants to merge 2 commits into
mainfrom
fix/claude-exit-plan-approve-updated-input

Conversation

@blimmer

@blimmer blimmer commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Summary

Claude Code 2.1.199 added a guard that silently drops a PermissionRequest hook's allow for ExitPlanMode unless the decision includes updatedInput, so approving a plan in the browser left the terminal stuck on Claude Code's own approval prompt. The approve envelope now echoes the event's tool_input back verbatim as updatedInput, and the hook schema parses tool_input loosely so fields we don't model (like planFilePath) survive the round trip. I verified both sides against the real TUIs: approve works again on 2.1.201, and 2.1.198 behaves the same as before, so this ships without a version gate. Closes #234; the upstream report is anthropics/claude-code#74256.

Review focus

We now rely on undocumented behavior (the guard keys on whether updatedInput is present) and we echo back fields we never validate. The loose parse is deliberate: the SDK's own ExitPlanModeInput type is an open object ([k: string]: unknown), and a closed schema would strip whatever field Claude Code adds next, which is exactly the class of breakage this PR fixes. Still, consider whether echoing unvalidated fields could bite us if Claude Code ever puts something large or sensitive in that object.

Commits

  • c5c93c4 — fix: echo tool_input as updatedInput so Claude Code >=2.1.199 honors plan approval
  • 1953246 — test: add a claudeHookPayload factory for Claude hook tests

…plan approval

Claude Code 2.1.199 added a guard that silently discards an ExitPlanMode
allow decision unless it carries updatedInput, so approving a plan in the
browser left the session blocked on the terminal's own approval prompt.
Echo the hook event's tool_input back verbatim in the allow envelope, and
parse tool_input as a loose object so fields like planFilePath survive the
round-trip. Verified against Claude Code 2.1.198 (no behavior change) and
2.1.201 (approval works again).

Upstream: anthropics/claude-code#74256
@blimmer blimmer force-pushed the fix/claude-exit-plan-approve-updated-input branch from a1e6fea to c5c93c4 Compare July 4, 2026 19:47
Valid hook events now come from a fishery factory (matching the existing
codexStopHookPayload one) instead of seven hand-rolled literals. Malformed
payload tests keep inline literals since they intentionally violate the type.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: Approving a plan no longer starts implementation on Claude Code >=2.1.199

1 participant