Skill v2.0.1
currentAutomated scan100/1004 files
name: hook-manager version: 2.0.1 description: >- List, enable, or disable individual core hooks and check their prerequisites. Use for "list hooks", "enable a hook", "disable a hook", "hook setup", "hooks config", or a [BOPEN-HOOKS-SETUP] directive. For the full harness view, use setup.
Hook Manager
Manage the hooks that ship with the core plugin across Claude Code, Codex, and Grok Build. The catalog source of truth is hooks/manifest.json in the installed plugin — read it live rather than trusting a memorized list:
cat "$(ls -d ~/.claude/plugins/cache/b-open-io/core/*/ | sort -V | tail -1)hooks/manifest.json"
Each entry carries name, event, matcher, tier, runtimes, summary, and description. Hooks register automatically when the plugin is installed; this skill controls which ones actually run.
The config file
Per-hook enable/disable lives in a JSON config. Resolution order (first file with an explicit true/false verdict for a hook wins):
$BOPEN_HOOKS_CONFIG— explicit override (tests, scripts)<project>/.claude/bopen-hooks.json— per-project (Claude)<project>/.grok/bopen-hooks.json— per-project (Grok)~/.claude/core/hooks-config.json— per-user (Claude)~/.grok/core/hooks-config.json— per-user (Grok)
{"version": 1,"hooks": {"bouncer": true,"damage-control": true,"publish-gate": true,"agent-browser-solo": true,"session-context": true,"hammertime": true,"browser-intent": true}}
A hook is disabled ONLY by an explicit false. Missing files, missing keys, or unparseable JSON all mean enabled — a broken config must never silently switch the guards off. Changes take effect on the next hook invocation; no restart is required.
First-time setup (the [BOPEN-HOOKS-SETUP] directive)
When session context carries [BOPEN-HOOKS-SETUP], the user has no config yet. Do not interrupt their task; offer setup at a natural pause. The flow:
- Read the manifest (command above) and present the hooks in two tiers via
AskUserQuestion (multiSelect):
- Guards (recommended on): entries with
tier: "guard"—
they prevent work loss, secret exposure, and unticketed publishes.
- Workflow (preference): entries with
tier: "workflow".
- Run the prerequisite checks below and fold findings into the
recommendation (e.g. agent-browser-solo without agent-browser installed silently falls back to native WebFetch — still safe to leave on).
- Write
~/.claude/core/hooks-config.json(Claude/Codex) or
~/.grok/core/hooks-config.json (Grok) with the full hooks map — include every hook with an explicit boolean, even the all-defaults case. Writing the file is what dismisses the setup notice permanently.
Enabling / disabling a hook
Edit the user config (or project config for repo-scoped changes) with the Read and Write tools — read, flip the boolean, write back. Create the file from the template above when it does not exist. Never edit files inside the plugin cache; updates overwrite them.
Expect a confirmation prompt on every config write: damage-control treats these files as ask-tier so guards can never be disarmed without the user's explicit yes (on Codex the write is denied outright — have the user edit the file themselves). This is by design; do not route around it.
Warn before disabling guards: bouncer stops git reset --hard-class work loss, damage-control enforces zero-access paths like .env, publish-gate blocks unticketed npm/on-chain publishes. Disabling them is the user's call, but say plainly what protection goes away.
Diagnosis
When a hook misbehaves or the user asks "why did X get blocked/skipped":
# Which config verdict applies to a hook?for f in "$BOPEN_HOOKS_CONFIG" ./.claude/bopen-hooks.json ./.grok/bopen-hooks.json ~/.claude/core/hooks-config.json ~/.grok/core/hooks-config.json; do[ -f "$f" ] && echo "$f: $(jq -r '.hooks["<name>"] // "no verdict"' "$f")"done# Prerequisitescommand -v jq || echo "jq missing — hooks skip JSON parsing without it"command -v agent-browser || echo "agent-browser missing — agent-browser-solo falls back to native WebFetch"[ -n "$LINEAR_API_KEY" ] || echo "LINEAR_API_KEY unset — publish-gate denies gated publishes"command -v python3 || echo "python3 missing — hammertime and JSON escaping degrade"
- Hard denies surface to the model as structured permission denials; on the
Codex runtime they arrive as stderr JSON with exit 2. Both are by design.
- hammertime also has its own controls —
Skill(core:hammertime)and
the hammertime:manage skill — for rule-level tuning beyond on/off.
- The definitive behavior reference for every hook is its script header in
the plugin's hooks/ directory; read it before guessing.
What this skill never does
- Never copies hook files into
~/.claude— hooks ship with the plugin and
update through claude plugin update core@b-open-io.
- Never edits
hooks/*.sh,claude-hooks.json, or anything in the plugin
cache.
- Never disables a guard hook without telling the user what it protected.