Where do Claude Code hooks go? File locations and scope
Claude Code hooks go under the hooks key in a settings file: ~/.claude/settings.json for all your projects, .claude/settings.json for one project and your team, or .claude/settings.local.json for one project and only you. Plugins, skills and subagents can define hooks too. A hook in a standalone file doesn't load.
Every place a hook can live
| Location | Scope | Shareable |
|---|---|---|
~/.claude/settings.json | All your projects | No, local to your machine |
.claude/settings.json | One project | Yes, commit it to the repo |
.claude/settings.local.json | One project | No, gitignored when Claude Code saves a setting to it |
| Managed policy settings | Your organization | Yes, controlled by an admin |
Plugin hooks/hooks.json | While the plugin is enabled | Yes, bundled with the plugin |
| Skill frontmatter | The rest of the session once the skill is invoked | Yes, in the skill file |
| Subagent frontmatter | While that subagent runs | Yes, in the subagent file |
What a hook looks like in settings.json
Add a hooks key at the top level. Each event name is a key inside that one object, so if the file already has a hooks key, add your event beside the existing ones rather than replacing the block. This one shows a Mac notification when Claude needs you and formats files after edits:
{
"hooks": {
"Notification": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "osascript -e 'display notification \"Claude Code needs your attention\" with title \"Claude Code\"'"
}
]
}
],
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"
}
]
}
]
}
}Where the hook script goes
The JSON has to be in a settings file, but the script it runs can be anywhere. The docs' examples keep project scripts in .claude/hooks/ and point at them with ${CLAUDE_PROJECT_DIR}, the project root where the session started:
"command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/check-style.sh"Use that form or an absolute path to avoid a command not found error, and make the script executable with chmod +x.
How the files combine
- Hooks add up. Hook entries merge across settings levels. User, project and local settings add their own without removing anyone else's, including managed ones.
disableAllHooksfollows normal precedence. Afalsein a project's.claude/settings.jsonoverrides atruein your user settings. Only managed settings can turn off managed hooks.- Trust comes first. In an interactive session, Claude Code holds back hooks from every settings file, your own included, until you accept the workspace trust dialog for the folder. A
-por SDK session never shows the dialog and treats the folder as trusted, so committed hooks run. Review a repo's.claude/settings before scriptingclaude -pover code you didn't write. - Cloud sessions don't read your local
~/.claude/settings.json.
Other settings resolve differently from hooks. See which settings.json wins for the rest.
Check that the hook loaded
- Run
/hooks. It lists every hook registered for the session, grouped by event. - If yours is missing, check that it's under the
hookskey, that the JSON has no trailing commas or comments, and thatmatcheris a single string. An array there marks the entry invalid inclaude doctor. - If it's listed but doesn't fire, check the matcher. Use
|between tool names, as in"Edit|Write". Matchers are case-sensitive, and a misspelled tool name fails silently. - Start with
claude --debugto see each event, the matchers checked, and the hook's exit code and output.
A hook defined in a skill's frontmatter doesn't show in /hooks until that skill has been invoked in the session.
When to use a hook
Use a hook for anything that must happen every time. CLAUDE.md instructions are context that Claude tries to follow; a hook runs as a command at a fixed point whatever Claude decides. See why Claude Code ignores CLAUDE.md for how to tell which one a rule needs.
Rulebook, the Mac app we are building, lists the hook events and matcher counts in each settings file and has a switch for disableAllHooks. Editing the hooks themselves happens in its raw JSON view.
Questions
- Can I put Claude Code hooks in their own file?
- Not on their own. A hook in a standalone file doesn't load; hooks go under the hooks key in a settings file. The script a hook runs can live anywhere, and .claude/hooks/ is the path the docs use in their examples. Plugins are the exception, with hooks/hooks.json.
- Should a hook go in settings.json or settings.local.json?
- Use .claude/settings.json for a hook the whole team should run, since you commit it with the repo. Use .claude/settings.local.json for one only you need in that project, and ~/.claude/settings.json for one you want in every project.
- Do hooks in different settings files override each other?
- No. Hook entries merge across settings levels. User, project and local settings each add their own hooks. To turn them off, set disableAllHooks to true, which can't turn off managed hooks unless it's set in managed settings.
- Why isn't my Claude Code hook running?
- Run /hooks. If the hook isn't listed, check that it's under the hooks key, that the JSON is valid, and that matcher is a single string rather than an array. If it's listed but doesn't fire, the matcher is the usual cause: matchers are case-sensitive.
- Do I need to restart Claude Code after adding a hook?
- Normally no. Claude Code watches settings files and applies hook changes to the running session. If the hook doesn't appear in /hooks after a few seconds, restart the session.
Rulebook for Mac
Rulebook is a native Mac app we are building for these files. It shows every CLAUDE.md and settings.json level side by side, lets you drag a rule from one file to another, and edits permissions without hand-written JSON. See the features.
Rulebook is in development and not available yet.
Email us about the launchRelated guides
- Where does Claude Code look for CLAUDE.md files?
- Which Claude Code settings.json wins? File locations and precedence
- How to stop Claude Code asking permission for every command
- How long should CLAUDE.md be? Trimming a CLAUDE.md that Claude ignores
- Does Claude Code read AGENTS.md? CLAUDE.md vs AGENTS.md and .cursorrules
- Why is Claude Code ignoring my CLAUDE.md?
- Where are Claude Code skills stored, and how are they found?
- How to share CLAUDE.md across projects or a team
- How to import other files into CLAUDE.md