[BUG] Hooks not loading from settings.json - /hooks shows "No hooks configured yet" despite valid configuration

Status Fixed / completed
Maintainer reply ✓ Yes — dicksontsai
Activity 12 comments · opened Nov 13, 2025 · closed Jan 29, 2026
💡 Likely answer: A maintainer (dicksontsai, collaborator) responded on this thread — see the highlighted reply below.

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

Hooks defined in ~/.claude/settings.json are not being loaded by Claude Code. The /hooks command shows "No hooks configured yet" despite having valid hook configurations in the settings file, and debug logs confirm that Claude Code is finding 0 hook matchers when it should be loading the
configured hooks.

Environment

  • Claude Code Version: 2.0.37
  • Platform: macOS (Darwin 24.6.0)
  • Installation: npm-global

Configuration

My ~/.claude/settings.json contains the following hooks configuration:

  {
    "hooks": {
      "Stop": [
        {
          "hooks": [
            {
              "type": "command",
              "command": "afplay -v 5 /System/Library/Sounds/Funk.aiff"
            }
          ]
        }
      ],
      "Notification": [
        {
          "hooks": [
            {
              "type": "command",
              "command": "afplay -v 5 /System/Library/Sounds/Pop.aiff"
            }
          ]
        }
      ]
    },
    "alwaysThinkingEnabled": false,
    "feedbackSurveyState": {
      "lastShownTime": 1754057465609
    },
    "mcpServers": {
    },
    "permissions": {
      "allow": [
        "Bash(python*)",
        "Bash(python3:*)",
        "Bash(gh_issue_create:*)",
        "Bash(find:*)",
        "Bash(pbcopy)",
        "Bash(open_http*)",
        "Bash(git:*)",
        "Bash(gh:*)",
        "Bash(uvicorn:*)",
        "Bash(chmod:*)",
        "Bash(echo:*)",
        "Bash(pkill:*)",
        "Bash(pytest:*)",
        "Bash(docker-compose:*)",
        "Bash(docker:*)",
        "Bash(env)",
        "Bash(pip_install:*)",
        "Bash(cat:*)",
        "Bash(awk:*)"
      ],
      "deny": [],
      "ask": []
    }
  }

The JSON is valid (verified with python3 -m json.tool).

Steps to Reproduce

  1. Create hooks configuration in ~/.claude/settings.json as shown above
  2. Start Claude Code with debug mode: claude --debug
  3. Run the /hooks command
  4. Complete a task to trigger the Stop hook

What Should Happen?

Expected Behavior

  • The /hooks command should display the configured Stop and Notification hooks
  • The Stop hook should execute (playing a sound) when Claude finishes responding
  • Debug logs should show hooks being loaded from settings

Actual Behavior

  • The /hooks command shows "No hooks configured yet"
  • The Stop hook never executes (no sound plays)
  • Debug logs show: [DEBUG] Found 0 hook matchers in settings

Debug Log Evidence


  From the debug log at ~/.claude/debug/d46cbf9a-6474-4717-881d-05bc05025a37.txt:

  [DEBUG] Watching for changes in setting files /Users/boris/.claude/settings.json...
  ...
  [DEBUG] Getting matching hook commands for SessionStart with query: startup
  [DEBUG] Found 0 hook matchers in settings
  [DEBUG] Matched 0 unique hooks for query "startup" (0 before deduplication)
  ...
  [DEBUG] Getting matching hook commands for SubagentStop with query: undefined
  [DEBUG] Found 0 hook matchers in settings
  [DEBUG] Matched 0 unique hooks for query "no match query" (0 before deduplication)

The debug log explicitly shows that Claude Code is watching the settings.json file but finding 0 hook matchers despite the hooks being defined in the file.

Additional Context

  • The hooks configuration structure follows the documentation at https://code.claude.com/docs/en/hooks.md
  • There is no project-level .claude/settings.json that could be overriding the global settings
  • The settings.json file is being monitored (shown in debug logs)
  • Other settings from the same file (mcpServers, permissions) are loading correctly
  • The hook commands work when executed manually (e.g., afplay -v 5 /System/Library/Sounds/Funk.aiff plays sound successfully)

Error Messages/Logs

From the debug log at ~/.claude/debug/d46cbf9a-6474-4717-881d-05bc05025a37.txt:

  [DEBUG] Watching for changes in setting files /Users/boris/.claude/settings.json...
  ...
  [DEBUG] Getting matching hook commands for SessionStart with query: startup
  [DEBUG] Found 0 hook matchers in settings
  [DEBUG] Matched 0 unique hooks for query "startup" (0 before deduplication)
  ...
  [DEBUG] Getting matching hook commands for SubagentStop with query: undefined
  [DEBUG] Found 0 hook matchers in settings
  [DEBUG] Matched 0 unique hooks for query "no match query" (0 before deduplication)

Steps to Reproduce

  1. update the settings with my config
  2. start a new claude session
  3. run a command

Claude Model

Sonnet (default)

Is this a regression?

Yes, this worked in a previous version

Last Working Version

_No response_

Claude Code Version

2.0.37 (Claude Code)

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

iTerm2

Additional Information

_No response_

View original on GitHub ↗

12 Comments

Tsuchiya2 · 9 months ago

I am experiencing the same issue as well.

Environment

  • Claude Code Version: 2.0.37
  • Platform: macOS 26.1 (25B78)
  • Installation Method: Homebrew

---

Original settings.json

{
  "permissions": {
    "allow": [
      "mcp__chrome-devtools__list_pages",
      "mcp__chrome-devtools__navigate_page",
      "mcp__chrome-devtools__take_snapshot",
      "mcp__chrome-devtools__fill",
      "mcp__chrome-devtools__click",
      "Bash(docker compose exec:*)",
      "Bash(docker-compose exec:*)"
    ],
    "deny": [
      "Bash(git add*)",
      "Bash(git commit*)",
      "Bash(git push*)"
    ],
    "ask": []
  },
  "enableAllProjectMcpServers": true,
  "enabledMcpjsonServers": [
    "chrome-devtools"
  ],
  "hooks": {
    "Notification": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "bash .claude/scripts/notification.sh 'Input needed / 入力が必要です' WarblerSong"
          }
        ]
      }
    ],
    "Stop": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "bash .claude/scripts/notification.sh 'Task completed / タスクが完了しました' CatMeow"
          }
        ]
      }
    ]
  }
}

---

Updated version I tried (no effect)

{
  "permissions": {
    "allow": [
      "mcp__chrome-devtools__list_pages",
      "mcp__chrome-devtools__navigate_page",
      "mcp__chrome-devtools__take_snapshot",
      "mcp__chrome-devtools__fill",
      "mcp__chrome-devtools__click",
      "Bash(docker compose exec:*)",
      "Bash(docker-compose exec:*)"
    ],
    "deny": [
      "Bash(git add*)",
      "Bash(git commit*)",
      "Bash(git push*)"
    ],
    "ask": []
  },
  "enableAllProjectMcpServers": true,
  "enabledMcpjsonServers": ["chrome-devtools"],
  "hooks": {
    "Notification": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "bash .claude/scripts/notification.sh \"Input needed / 入力が必要です\" WarblerSong"
          }
        ]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "*",
        "hooks": [
          {
            "type": "command",
            "command": "bash .claude/scripts/notification.sh \"Task completed / タスク終了\" CatMeow"
          }
        ]
      }
    ]
  }
}

---

Result

Even after:

  • changing the matcher ("""*")
  • switching from Stop to PostToolUse
  • adjusting quoting/escaping
  • verifying shell scripts manually

…the hooks are still not triggered, and no sound plays.

Other settings in the same file (permissions, sandbox, mcpServers) load correctly, so only hooks appear to be affected.

This behavior worked in previous versions of Claude Code, so this may be a regression.

kevincraig · 9 months ago

Comment for GitHub Issue #11544

Confirmed: Same Issue in v2.0.37

We're experiencing the identical issue with hooks not loading in Claude Code v2.0.37 on macOS.

Environment

  • Version: Claude Code v2.0.37
  • Model: Sonnet 4.5 · Claude Enterprise
  • Platform: macOS (Darwin 24.4.0)
  • Hook Types Tested: SessionStart, UserPromptSubmit

What We Tried

  1. Project-level hooks in .claude/settings.json:

``json
{
"description": "...",
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "ls -l"
}
]
}
]
}
}
``

  1. Global user hooks in ~/.claude/settings.json (same structure)
  1. Created hooks via /hooks UI - UI saves to settings.json but hooks still don't load
  1. Verified JSON syntax with python3 -m json.tool - all valid
  1. Tested with and without matchers for SessionStart events
  1. Tried both absolute paths and $CLAUDE_PROJECT_DIR - no difference

Debug Output

Consistent across all attempts:

[DEBUG] Getting matching hook commands for SessionStart with query: clear
[DEBUG] Found 0 hook matchers in settings
[DEBUG] Matched 0 unique hooks for query "clear" (0 before deduplication)
[DEBUG] Hooks: Found 0 total hooks in registry

The hooks are in the settings file, JSON is valid, but Claude Code reports "0 hook matchers" every time.

Use Case

We were building a coordination system to share messages between Claude instances working on different repos (backend/frontend). SessionStart hooks would automatically check for messages from other instances at startup. Without hooks, we have to manually run slash commands each time.

Impact

Without working hooks, we can't:

  • Auto-check for coordination messages at session start
  • Automatically validate code before tool execution (PreToolUse)
  • Run cleanup tasks when sessions end (Stop)

Hooks are documented extensively but fundamentally broken in this version.

---

Happy to provide more debug logs or test configurations if helpful for debugging.

sankar-param · 9 months ago

Confirmed: Issue in 2.0.46

I can confirm that this issue exists in version 2.0.46 as well.

Environment:

  • Claude Code version: 2.0.46
  • Platform: MacOS 15.5
  • Install Method : Brew

Claude
The settings file in .claude/settings.json looks as:

{
  "hooks": [
    {
      "event": "PostToolUse",
      "matcher": {
        "toolName": ["Edit", "Write"]
      },
      "command": "bash .claude/hooks/post-edit-docker-check.sh ${filePath}"
    }
  ]
}

On running claude in debug mode, the following logs are printed in the log file

2025-11-19T16:07:27.852Z [DEBUG] Getting matching hook commands for PreToolUse with query: Bash
2025-11-19T16:07:27.852Z [DEBUG] Found 0 hook matchers in settings
2025-11-19T16:07:27.852Z [DEBUG] Matched 0 unique hooks for query "Bash" (0 before deduplication)
2025-11-19T16:07:28.143Z [DEBUG] Getting matching hook commands for PostToolUse with query: Bash
2025-11-19T16:07:28.143Z [DEBUG] Found 0 hook matchers in settings
2025-11-19T16:07:28.143Z [DEBUG] Matched 0 unique hooks for query "Bash" (0 before deduplication)

The shell script mentioned in the "command" executes fine standalone.

lorenzoridolfi · 9 months ago

Same problem here in version 2.0.53. It seems that Anthropics believes it is doing a favor to the customers by providing support (badly).

crsmithdev · 9 months ago

Also experiencing this. SessionStart hook defined in ~/.claude/settings.json with valid JSON syntax (validated with python -m json.tool). Hook script is executable and works when run manually, but appears to not execute automatically on session start.

No errors shown, no indication hook was attempted. Output completely absent from context.

Environment: WSL2, Claude Code latest version

github-actions[bot] · 8 months ago

This issue has been inactive for 30 days. If the issue is still occurring, please comment to let us know. Otherwise, this issue will be automatically closed in 30 days for housekeeping purposes.

damianpolan · 7 months ago

Same issue for me.

Summonair · 7 months ago

same issue here, why is this closed?!?

dicksontsai collaborator · 7 months ago

There was a small bug we fixed about setting the proper current working directory before loading in hooks, but I think this issue is more general than that bug. Taking a closer look.

Max-Makhrov · 7 months ago

Confirmed: Issue in 2.1.15 (VS Code Extension)

Hooks defined in .claude/settings.local.json are not being loaded.

Environment

  • Claude Code Version: 2.1.15
  • Platform: Windows 11 (VS Code Extension)
  • Settings Location: .claude/settings.local.json (project-level)

Configuration

{
  "hooks": {
    "SessionStart": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "prompt",
            "prompt": "STOP. Before responding, you MUST:\n1. Read CLAUDE.md checklist\n2. Identify which rules apply\n3. Read those rule files\n4. Only then proceed\n\nDo NOT skip this process."
          },
          {
            "type": "command",
            "command": "echo 'REMINDER: Check CLAUDE.md checklist before proceeding' >&2 && exit 0"
          }
        ]
      }
    ],
    "PreToolUse": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "prompt",
            "prompt": "Follow CLAUDE.MD as your highest priority before any other action."
          },
          {
            "type": "command",
            "command": "echo 'REMINDER: Check CLAUDE.md checklist before proceeding' >&2 && exit 0"
          }
        ]
      }
    ],
    "UserPromptSubmit": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "prompt",
            "prompt": "Follow CLAUDE.MD above all!"
          },
          {
            "type": "command",
            "command": "echo 'REMINDER: Check CLAUDE.md checklist before proceeding' >&2 && exit 0"
          }
        ]
      }
    ]
  }
}
lyuro · 7 months ago

Same issue on Windows.

  • Claude Code extension: v2.1.21
  • Platform: Windows 11 Pro (VS Code extension)
  • Settings location: Project-level .claude/settings.json

Hooks work in CLI (claude in terminal), but not in VS Code extension UI.

<details>
<summary>settings.json</summary>

{
"language": "Japanese",
"outputStyle": "Explanatory",
"permissions": {
"defaultMode": "bypassPermissions"
},
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "node .claude/hooks/check-branch.js"
}
]
},
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "node .claude/hooks/git-safety.js"
}
]
}
],
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "node .claude/hooks/auto-review.js"
},
{
"type": "command",
"command": "node .claude/hooks/check-internal-link.js"
},
{
"type": "command",
"command": "node .claude/hooks/sync-config.js"
}
]
}
]
}
##}

</details>

github-actions[bot] · 6 months ago

This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.