tool_use_id missing from hook payloads in headless/bypassPermissions mode
Description
When running Claude Code in headless mode with --permission-mode bypassPermissions, the tool_use_id field is missing from PreToolUse and PostToolUse hook payloads. This field is documented as a standard field and is present in interactive mode.
Steps to Reproduce
- Configure a hook in
.claude/settings.json:
{
"hooks": {
"PreToolUse": [{
"matcher": "*",
"hooks": [{
"type": "command",
"command": "/path/to/hook.sh",
"timeout": 5
}]
}]
}
}
- Run Claude Code in headless mode:
claude -p "List files in current directory" --permission-mode bypassPermissions
- Observe the hook payload -
tool_use_idis missing
Expected Behavior
Hook payload should include tool_use_id as documented:
{
"session_id": "abc123-...",
"tool_use_id": "toolu_01ABC123...",
"tool_name": "Bash",
"tool_input": {...}
}
Actual Behavior
In headless/bypassPermissions mode, tool_use_id is missing:
{
"session_id": "abc123-...",
"tool_name": "Bash",
"tool_input": {...}
}
Note: In interactive mode, tool_use_id IS correctly included (e.g., "toolu_015kC3i7UPieqAdSvNaXFGda").
Impact
This breaks correlation between PreToolUse and PostToolUse events for telemetry/observability systems that rely on tool_use_id to match tool start/end events.
Workaround
Generate a UUID server-side if missing, and correlate PostToolUse with PreToolUse by matching session_id + tool_name + finding the most recent unfinished tool call.
Environment
- Claude Code version: Latest (as of Jan 2026)
- OS: macOS
- Permission mode:
bypassPermissions
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗