hook_progress JSONL entries lack hook identity (plugin name, resolved command)

Resolved 💬 3 comments Opened Mar 14, 2026 by kylesnowschwartz Closed Apr 13, 2026

Problem

hook_progress entries in session JSONL transcripts don't identify which hook or plugin produced them. The data object contains only hookEvent, hookName, and command:

{
  "type": "progress",
  "data": {
    "type": "hook_progress",
    "hookEvent": "PostToolUse",
    "hookName": "PostToolUse:Read",
    "command": "callback"
  },
  "toolUseID": "toolu_01HHr3..."
}

For callback-type hooks, command is the literal string "callback" — there's nothing to distinguish one PostToolUse callback from another. For shell hooks, command contains unresolved ${CLAUDE_PLUGIN_ROOT} variables, so the plugin is not identifiable without cross-referencing installed_plugins.json and probing file paths.

The debug log (~/.claude/debug/*.txt) has the same gap — callback hooks get no per-hook identity in outcome lines.

Impact

Anyone building tooling to analyze hook execution (session viewers, debugging tools, performance profiling) hits a wall: callback hooks are completely opaque, and shell hooks require guesswork to attribute to a plugin.

Concrete example: with 5 PostToolUse matchers registered across 3 plugins, the JSONL shows 5 identical "command": "callback" entries per tool call. No way to tell which plugin each came from, whether one is slow, or which one modified the input.

Proposed solution

Add identifying fields to hook_progress entries:

{
  "data": {
    "type": "hook_progress",
    "hookEvent": "PostToolUse",
    "hookName": "PostToolUse:Read",
    "command": "callback",
    "pluginName": "envato-handy-hooks",
    "resolvedCommand": "/Users/me/.claude/plugins/cache/envato-claude/envato-handy-hooks/1.0.0/hooks/entrypoints/post_tool_use.rb"
  }
}

Even just pluginName would solve the attribution problem. resolvedCommand (with ${CLAUDE_PLUGIN_ROOT} expanded) would help for shell hooks too.

Related issues

  • #32624 — SessionStart hooks all show as generic SessionStart:startup says: with no plugin attribution
  • #33610 — Plugin init failures reported as generic "hook error" with no identification
  • #14859 — Hook events lack agent hierarchy information
  • #33674 — Hook stderr silently swallowed, making debugging impossible
  • #31250 — Hooks fail silently with no observable trace

These all share a common root cause: hook execution produces insufficient identifying metadata for debugging and observability.

Context

Discovered while building a hook execution viewer for tail-claude (a TUI for reading Claude Code session transcripts). The JSONL data is rich enough to show timing, grouping, and turn correlation, but hook identity is the missing piece that would make the view genuinely useful for debugging.

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗