Skip to content

Hook stderr output shows raw command path as prefix, leaking implementation details #41226

Description

@iroha924

Description

When a hook writes to stderr (e.g., exit 2 for DENY/block), Claude Code displays the message with the full command as a prefix:

Stop hook error: [node /path/to/hook.mjs stop]: Custom message here.

The [node /path/to/hook.mjs stop] prefix is an implementation detail that provides no value to users. For plugin hooks, it exposes internal paths like ${CLAUDE_PLUGIN_ROOT}/dist/hook.mjs.

Expected behavior

Show only the hook's stderr message, optionally with a human-readable hook identifier:

Stop hook: Custom message here.

Or use the plugin name if available:

my-plugin (Stop): Custom message here.

Reproduction

  1. Create a minimal hook that exits with code 2:
{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "echo 'Please fix errors before finishing.' >&2 && exit 2",
            "timeout": 5
          }
        ]
      }
    ]
  }
}
  1. Start a session and let Claude attempt to stop
  2. Observe the output:
Stop hook error: [echo 'Please fix errors before finishing.' >&2 && exit 2]: Please fix errors before finishing.

The full command is shown as a prefix, and the intentional block is labeled "error".

Additional context

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions