[Feature Request] PreToolUse/PostToolUse hooks lack access to live background task registry
Feature request
Related issues
## Summary
Feature request: PreToolUse/PostToolUse hooks have no way to observe a background Bash task's
completion, so custom tooling built on them can only learn a task finished by an explicit blockingTaskOutput call or by waiting for the next Stop event — both of which a normal working turn may
avoid for many tool calls in a row.
Desired state
as a suggested design, either of the following:
- a dedicated hook event fires when a background Bash task transitions to a terminal state
- the live background-task registry that
Stopalready receives (background_tasks
in its payload) is also included in the PreToolUse/PostToolUse payload, so tooling built on
those hooks can reconcile a task's real status without waiting for Stop or issuing an explicit
blocking wait.
Current state
A background Bash task's completion is only visible to the agent as an in-context notification
(the <task-notification> block delivered mid-turn) — this is not itself a hook event, so no hook
fires when it happens. Custom hook-based tooling that tracks a background task's status locally
(e.g. to warn if a turn is about to end while work is still live) has exactly two ways to learn a
task reached a terminal state: an explicit blocking TaskOutput(task_id=..., block=true) call, or
the next Stop event, whose payload is the only one of the three (PreToolUse/PostToolUse/Stop) that carries the live task registry.
Practical effect: if the agent doesn't proactively call TaskOutput on a task it already knows
(from the notification) is done, any PreToolUse/PostToolUse-based tooling keeps treating that
task as live for every subsequent tool call in the same turn, producing stale "still pending"
signals even though the task completed and the agent has already seen so.
Minimal reproduction
- Register a
PreToolUsehook script that reads a small local JSON marker file per
in-flight background task (created from an earlier PostToolUse observing a Bash tool call
with run_in_background: true).
- Launch a Bash tool call with
run_in_background: true. Let it run to completion — a
<task-notification> for it appears in the transcript mid-turn once it finishes.
- Without calling
TaskOutputon that task's ID, make another tool call in the same turn. - Observed: the
PreToolUsehook fires again with no signal that the task already completed —
its payload contains no live task-status registry, only whatever the hook script itself
persisted locally from step 1 (which nothing updated between steps 2 and 3).
- The same local marker only updates via an explicit
TaskOutput(block=true)call reconciling
against its response, or at the next Stop event, whose payload does include a live
background_tasks registry with each task's current status.
Diagnostics
Payload shape observed for each hook:
Stop: includesbackground_tasks— a list of{id, type, status, description, ...}for
every task tracked this session, live at the moment Stop fires.
PreToolUse/PostToolUse: no equivalent field. The only background-task-shaped data present
is whatever the specific tool call in question concerns (e.g. a Bash call's own
backgroundTaskId in its response, or a TaskOutput call's own resolved status) — never the
full live registry.
Regression and controls
- Fresh process/session: Reproduces — confirmed on a fresh session, not tied to session age or
compaction history.
- Last known good version: Unknown — this appears to be the payload shape's design, not a
regression from a prior version.
- Relevant control: Calling
TaskOutput(task_id=..., block=true)explicitly after a task
notification does correctly resolve the task's status (confirms the registry data exists and is
reachable via that one specific tool call — just not proactively via the hooks that would need
it to avoid a stale-state window).
Environment
- Product and version: Claude Code CLI 2.1.233
- OS and version: macOS 26.6.1 (build 25G76), Darwin 25.6.0, arm64
- Model / resolved model ID: Not model-specific — hook payload shape is independent of the active
model.
- Runtime context: Interactive terminal session (tmux-managed),
PreToolUse/PostToolUse/Stop
hooks configured via project-level Claude Code settings.
- Authentication/provider path: Claude subscription (OAuth), interactive CLI.