Hooks docs: stop_hook_active IS present on SubagentStop (docs say it isn't), and SubagentStop does fire for background subagents

Open Beginner friendly
#83,365 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-2 days
Newbie friendliness
72/100
Issue type
Documentation
Clarity
Mostly clear
Activity status
Quiet
Tech stack
shell
Domain
cli, documentation

Research direction

Start with the hooks documentation linked in the issue and compare the SubagentStop reference with the reported v2.1.220 behavior. Use the probe-settings.json setup and the supplied Claude Code command to verify the fields and background-subagent behavior. Done means the reference documents stop_hook_active, the guard idiom, and that additionalContext re-invokes the subagent without misleading wording.

Written by the indexing model from the issue text.

Description

area:hooks

Summary

Two measured contradictions between the hooks documentation and v2.1.220 behaviour, both affecting anyone writing a SubagentStop hook.

1. stop_hook_active IS present on SubagentStop

The hooks docs state, for stop_hook_active:

Not present on SubagentStop

Measured: it is present, and it is exactly the loop guard you'd want.

  • first SubagentStop fire for a subagent: field absent/null
  • every subsequent fire: stop_hook_active: true

Captured by a SubagentStop hook that logs jq -c '{ev:.hook_event_name, sha:.stop_hook_active}':

{"ev":"SubagentStop","agent":"general-purpose","sha":null}
{"ev":"SubagentStop","agent":"general-purpose","sha":true}
{"ev":"SubagentStop","agent":"general-purpose","sha":true}
... (7 more, all true)

This matters because the docs actively steer hook authors away from the correct guard. Following them, you write a marker-file/TTL workaround for a field that already exists, and the documented alternative (decision-based control) is the thing that causes runaway loops.

2. SubagentStop fires for background/Agent-tool subagents

#82249 reports that SubagentStop does not fire for subagents launched via the Agent tool in async/background mode. On 2.1.220 it does — verified with run_in_background: true, 9 fires observed. That issue may be fixable/closeable, or the docs should state the current behaviour.

Repro

Minimal --settings file with a logging SubagentStop hook, then:

claude -p "Use the Agent tool to dispatch one general-purpose subagent whose entire task is to reply with the single word FOO. Then reply DONE." \
  --settings ./probe-settings.json --model sonnet --effort high \
  --allowedTools Agent --permission-mode dontAsk

Requested

  • Correct the stop_hook_active row in the hooks reference, and show the guard idiom for SubagentStop ([ "$STOP_ACTIVE" = "true" ] && exit 0).
  • Document that hookSpecificOutput.additionalContext on SubagentStop re-invokes the subagent — the current wording ("non-error feedback that continues the conversation") does not make it obvious that "the conversation" is the subagent's, which makes it very easy to author an amplifying loop.

Environment

Claude Code 2.1.220, macOS 15 (Darwin 25.5.0), Sonnet 5 and Opus 5 both reproduce.

Dominant language
TypeScript
Stars
147k
Forks
24k
Avg merge
8h 14m
Merged PRs (30d)
18

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from anthropics/claude-code

All issues in anthropics/claude-code

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.