/install nm-abstract-hook-scope-guide
Night Market Skill — ported from claude-night-market/abstract. For the full experience with agents, hooks, and commands, install the Claude Code plugin.
Hook Scope Decision Guide
This skill helps you choose the right location for Claude Code hooks based on their purpose, audience, and persistence needs.
Important: Auto-Loading Behavior
hooks/hooks.jsonis automatically loaded by Claude Code when the plugin is enabled. Do NOT add"hooks": "./hooks/hooks.json"to yourplugin.json- this causes duplicate load errors. Thehooksfield inplugin.jsonis only needed for additional hook files beyond the standardhooks/hooks.json.
The Three Scopes
| Scope | Location | Audience | Committed? | Persistence |
|---|---|---|---|---|
| Plugin | hooks/hooks.json in plugin |
Plugin users | With plugin | When plugin enabled |
| Project | .claude/settings.json |
Team members | Yes (repo) | Per project |
| Global | ~/.claude/settings.json |
Only you | Never | All sessions |
Decision Framework
Question 1: Who needs this hook?
Only plugin users → Plugin hooks
- Hook is part of plugin's core functionality
- Users expect it when they enable your plugin
- Example: A YAML plugin validates YAML syntax on edit
All team members on this project → Project hooks
- Codebase-specific rules or protections
- Team conventions that should be enforced
- Example: Block modifications to
/src/production/configs
Only me, everywhere → Global hooks
- Personal preferences or workflow optimizations
- Cross-project utilities like logging
- Example: Log all bash commands to personal audit trail
Question 2: Should this be version controlled?
Yes, as part of a distributable plugin → Plugin hooks Yes, shared with team in repo → Project hooks No, keep private → Global hooks
Question 3: What's the persistence requirement?
Only when my plugin is active → Plugin hooks Always in this specific project → Project hooks Always, in every project I work on → Global hooks
Scope Details
Plugin Hooks
Location: \x3Cplugin-root>/hooks/hooks.json
When to use:
- The hook is intrinsic to your plugin's functionality
- It should automatically activate when users enable your plugin
- It only makes sense in the context of your plugin's features
Configuration:
{
"PreToolUse": [
{
"matcher": "Read",
"hooks": [{
"type": "command",
"command": "echo 'Plugin reading: $CLAUDE_TOOL_INPUT' >> ${CLAUDE_PLUGIN_ROOT}/log.txt"
}]
}
]
}
Note: Use string matchers (
"Read") not object matchers ({"toolName": "Read"}).
Key features:
- Use
${CLAUDE_PLUGIN_ROOT}for plugin-relative paths - Auto-merges when plugin is enabled
- Deactivates when plugin is disabled
Examples:
- Validation hook for a linting plugin
- Auto-formatting hook for a code style plugin
- Logging hook for a debugging plugin
Project Hooks
Location: .claude/settings.json (in project root)
When to use:
- Enforcing team-wide policies
- Protecting project-specific resources
- Codebase conventions that should survive across team members
- Rules that should be reviewed in PRs
Configuration:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [{
"type": "command",
"command": "if [[ \"$CLAUDE_TOOL_INPUT\" == *\"production\"* ]]; then echo 'BLOCKED: Production access requires approval'; exit 1; fi"
}]
}
]
}
}
Note: Use string matchers (
"Bash") not object matchers.
Key features:
- Committed to version control
- Shared across all team members
- Changes are visible in PRs (governance trail)
- Project-specific, not personal
Examples:
- Block modifications to production configs
- Require test commands before completion
- Warn about editing sensitive directories
- Enforce project naming conventions
Global Hooks
Location: ~/.claude/settings.json
When to use:
- Personal workflow preferences
- Cross-project utilities
- Organization-wide compliance you want everywhere
- Private rules that shouldn't be shared
Configuration:
{
"hooks": {
"PreToolUse": [
{
"hooks": [{
"type": "command",
"command": "echo \"$(date): $CLAUDE_TOOL_NAME\" >> ~/.claude/audit.log"
}]
}
]
}
}
Key features:
- Never committed to any repo
- Applies to ALL Claude Code sessions
- Personal to your user account
- Survives across projects
Examples:
- Personal audit logging
- Cross-project safety rules
- Custom notification integrations
- Development environment preferences
Loading Order & Precedence
Claude Code loads settings in this priority (highest first):
- Enterprise policies (organization-managed)
- Command-line arguments (
claude --flag) - Local project settings (
.claude/settings.local.json) - Shared project settings (
.claude/settings.json) - User settings (
~/.claude/settings.json)
Important: Multiple hooks from different scopes can respond to the same event. When they do, all matching hooks execute in parallel.
Quick Reference: Scope Selection
Is this hook part of a plugin's core functionality?
├─ YES → Plugin hooks (hooks/hooks.json in plugin)
└─ NO ↓
Should all team members on this project have this hook?
├─ YES → Project hooks (.claude/settings.json)
└─ NO ↓
Should this hook apply to all my Claude sessions?
├─ YES → Global hooks (~/.claude/settings.json)
└─ NO → Reconsider if you need a hook at all
Security Considerations
Plugin hooks:
- Audited as part of plugin installation
- Users consent when enabling plugin
- Scope limited to plugin's purpose
Project hooks:
- Visible to all team members
- Changes reviewed in PRs
- Should reflect team consensus
Global hooks:
- Execute with your credentials everywhere
- Can affect all projects unexpectedly
- Review security implications carefully
- Test thoroughly before adding
Common Patterns by Scope
Plugin Hook Patterns
- Validation: Check files match plugin's format
- Auto-completion: Suggest plugin-specific completions
- Logging: Track plugin-specific operations
Project Hook Patterns
- Protection: Block dangerous operations on sensitive paths
- Enforcement: Require tests, linting, or builds
- Conventions: Warn about style or naming violations
Global Hook Patterns
- Auditing: Log all operations for personal review
- Safety: Universal dangerous command detection
- Integration: Personal tool notifications
SessionStart Hook Enhancements (Claude Code 2.1.2+)
SessionStart hooks now receive additional input fields via stdin:
| Field | Type | Description |
|---|---|---|
session_id |
string | Unique session identifier |
source |
enum | "startup" | "resume" | "clear" | "compact" |
agent_type |
string | Agent name if --agent flag used, empty otherwise |
Agent-Aware Hooks
The agent_type field enables scope-appropriate context injection:
# Skip heavy context for review agents
input_data = json.loads(sys.stdin.read())
if input_data.get("agent_type") in ["code-reviewer", "quick-query"]:
print(json.dumps({"hookSpecificOutput": {"additionalContext": "Minimal"}}))
This is particularly useful for:
- Plugin hooks: Reduce overhead for lightweight agents
- Project hooks: Skip governance for review-only agents
- Global hooks: Customize logging verbosity per agent
Related Skills
- abstract:hook-authoring - For hook rule syntax and patterns
- abstract:validate-plugin - For validating plugin structure including hooks
References
- Make sure OpenClaw is installed (local or Docker)
- Run the install command in chat:
/install nm-abstract-hook-scope-guide - After installation, invoke the skill by name or use
/nm-abstract-hook-scope-guide - Provide required inputs per the skill's parameter spec and get structured output
What is Nm Abstract Hook Scope Guide?
Select hook scope (plugin, project, global) by audience. It is an AI Agent Skill for Claude Code / OpenClaw, with 31 downloads so far.
How do I install Nm Abstract Hook Scope Guide?
Run "/install nm-abstract-hook-scope-guide" in the OpenClaw or Claude Code chat to install it in one step — no extra setup required.
Is Nm Abstract Hook Scope Guide free?
Yes, Nm Abstract Hook Scope Guide is completely free, licensed under MIT-0. You can download, install and use it at no cost.
Which platforms does Nm Abstract Hook Scope Guide support?
Nm Abstract Hook Scope Guide is cross-platform and runs anywhere OpenClaw / Claude Code is available (cross-platform).
Who created Nm Abstract Hook Scope Guide?
It is built and maintained by athola (@athola); the current version is v1.0.0.