Skip to content
Development
Skill

/hook-scope-guide

Select hook scope (plugin, project, global) by audience. Use when authoring a hook.

From plugin
claude-night-market
337200 skills59 agents162 commands1 MCP
Install
$ npx -y skills add athola/claude-night-market --skill hook-scope-guide --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/hook-scope-guide

Context preview

The summary Claude sees to decide when to auto-load this skill.

Select hook scope (plugin, project, global) by audience. Use when authoring a hook.

SKILL.md

hook-scope-guide.SKILL.md
name: hook-scope-guide
description: 'Select hook scope (plugin, project, global) by audience. Use when authoring a hook.'
category: hook-development

Hook Scope Decision Guide

Overview

This skill helps you choose the right location for Claude Code hooks based on their purpose, audience, and persistence needs.

When NOT To Use

  • Writing the hook itself (use `abstract:hook-authoring`)
  • Scoring an existing hook (use `abstract:hooks-eval`)

Important: Auto-Loading Behavior

> **`hooks/hooks.json` is automatically loaded** by Claude Code when the plugin is enabled. > Do NOT add `"hooks": "./hooks/hooks.json"` to your `plugin.json` - this causes duplicate load errors. > The `hooks` field in `plugin.json` is only needed for additional hook files beyond the standard `hooks/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**: `<plugin-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: $(jq -r '.tool_input.file_path')\" >> ${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": "cmd=$(jq -r '.tool_input.command // empty'); if [[ \"$cmd\" == *\"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): $(jq -r '.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):

1. **Enterprise policies** (organization-managed) 2. **Command-line arguments** (`claude --flag`) 3. **Local project settings** (`.claude/settings.local.json`) 4. **Shared project settings** (`.claude/settings.json`) 5. **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 plug
Read more
Ships withclaude-night-market

A plugin marketplace for Claude Code. Install only the plugins you need to run git workflows, code review, spec-driven development, and autonomous agents from inside your Claude Code session.

Get the whole plugin

Other skills on claude-night-market.