/insights report generates non-functional hook code with 4 errors against official docs

Resolved 💬 2 comments Opened Feb 5, 2026 by ACT900 Closed Mar 6, 2026

Description

The /insights report's features_to_try section for "Hooks" generates an example hook configuration that has 4 structural errors compared to the official Claude Code hooks documentation (https://code.claude.com/docs/en/hooks).

Generated code (from /insights report)

{
  "hooks": {
    "pre_tool_use": [
      {
        "matcher": "Bash",
        "command": "if echo \"$INPUT\" | grep -q 'npm '; then echo 'ERROR: Use pnpm, not npm!' && exit 1; fi"
      }
    ]
  }
}

Issues found

| # | Issue | Generated (Wrong) | Official Docs (Correct) |
|---|-------|--------------------|------------------------|
| 1 | Event name casing | "pre_tool_use" (snake_case) | "PreToolUse" (PascalCase) |
| 2 | Hook structure | Flat { "matcher", "command" } | Nested { "matcher", "hooks": [{ "type": "command", "command" }] } |
| 3 | Exit code for blocking | exit 1 (non-blocking — action proceeds) | exit 2 (blocks the action) |
| 4 | Input method | echo "$INPUT" (undefined env var) | INPUT=$(cat) + jq (stdin JSON) |

Impact

If a user copies this code directly into their .claude/settings.json:

  1. The hook would not be recognized (wrong event name casing)
  2. Even if the event name were fixed, the structure is invalid (missing hooks array and type field)
  3. Even if structure were fixed, $INPUT is empty so grep would never match anything
  4. Even if input were fixed, exit 1 doesn't block — the npm command would still execute

The hook is completely non-functional in every dimension. None of the 4 components (event name, structure, input, exit code) are correct.

What the correct code should look like

Per the official hooks reference:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "bash .claude/hooks/block-npm.sh",
            "timeout": 5
          }
        ]
      }
    ]
  }
}

With the script:

#!/bin/bash
set -euo pipefail

input=$(cat)
command=$(echo "$input" | jq -r '.tool_input.command // empty')

if echo "$command" | grep -qE '(^|&&\s*|;\s*|\|\s*)npm '; then
  echo "BLOCKED: Use pnpm, not npm!" >&2
  exit 2
fi

exit 0

Expected behavior

Generated hook examples in the /insights report should follow the official configuration schema documented at https://code.claude.com/docs/en/hooks and https://code.claude.com/docs/en/hooks-guide.

Environment

  • Claude Code CLI
  • /insights report generated 2026-02-06
  • Linux (Ubuntu)

View original on GitHub ↗

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