Audit Claude Code agents, skills, and commands for quality and production readiness. Use when evaluating skill quality, checking production readiness scores, or comparing agents against best-practice templates.
日本語の概要は準備中です。原文の説明を表示しています。
Audit Claude Code and Codex hooks for validity, safety, and correctness across settings.json, hooks.json, config.toml, plugin, and skill or agent frontmatter hooks. Resolves each command, checks event names, handler types, matchers, exit-code and JSON decision strategy, and timeouts against each host's documented rules, then reviews hooks one by one. Use when setting up hooks, debugging a hook that never fires, never blocks, or hangs the agent, or doing a periodic hooks hygiene pass. Not for writing a new hook from scratch.
インストール方法を見るインストールする前に、エージェントに与えられる指示の中身を確認できます。
Discover every Claude Code and Codex hook in scope, validate each one against the filesystem and the host's documented hook semantics, then run an interactive session to confirm or improve them.
The goal is not just to score; it is to leave every hook working, correctly scoped, and safe to run.
Sources of truth: the official Claude Code hooks reference (https://code.claude.com/docs/en/hooks) and the Codex hooks documentation (https://developers.openai.com/codex/hooks). When a rule below and the live documentation disagree, the documentation wins; report the disagreement instead of scoring against stale text.
| Argument | Audit |
|---|---|
| none | Every Claude Code and Codex location listed below that exists |
claude or codex | That host only |
| a file path | That file only (settings JSON, hooks.json, config.toml, skill or agent file) |
audit-only, or the user asks for no changes | Steps 1-4 and 6 only: list each proposed change instead of asking or editing, and omit the user-feedback lines from the report |
Audit each host with its own rules. Never score a Codex hook against Claude Code semantics or the reverse.
When a ctxharness doctor --format json report generated during this task is available, reconcile against it: every hook-layer finding it reports must appear in the audit, and every extra finding needs file:line evidence.
| Event | When it fires | Exit 2 effect |
|---|---|---|
SessionStart | Session begins or resumes | Stderr to user only |
Setup | --init-only, or --init / --maintenance in -p mode | Ignored |
UserPromptSubmit | Prompt submitted, before processing | Blocks and erases the prompt |
UserPromptExpansion | A typed command expands into a prompt | Blocks the expansion |
PreToolUse | Before a tool call executes | Blocks the tool call |
PermissionRequest | A tool call needs a permission decision | Not honored: deny through the JSON decision object |
PermissionDenied | Auto mode denies a tool call | Ignored (only hookSpecificOutput.retry is read) |
PostToolUse | After a tool call succeeds | Stderr to Claude; the tool already ran |
PostToolUseFailure | After a tool call fails | Stderr to Claude |
PostToolBatch | After a full batch of parallel tool calls | Stops the agentic loop |
Notification | Claude Code sends a notification | Ignored |
MessageDisplay | While assistant text is displayed | Original text displayed |
SubagentStart | A subagent is spawned | Stderr to user only |
SubagentStop | A subagent finishes | Prevents the subagent from stopping |
TaskCreated | A task is being created | Rolls back the creation |
TaskCompleted | A task is being marked completed | Prevents completion |
Stop | Claude finishes responding | Prevents stopping, continues the turn |
StopFailure | The turn ends on an API error | Ignored (except terminalSequence) |
TeammateIdle | An agent team teammate is about to go idle | Keeps the teammate working |
InstructionsLoaded | A CLAUDE.md or .claude/rules/*.md file loads | Ignored |
ConfigChange | A configuration file changes mid-session | Blocks the change (except policy_settings) |
CwdChanged | The working directory changes | Stderr to user only |
DirectoryAdded | A directory is added via /add-dir or SDK register_repo_root | Stderr to debug log; already added |
FileChanged | A watched file changes on disk | Stderr to user only |
WorktreeCreate | A worktree is being created | Any non-zero exit fails creation |
WorktreeRemove | A worktree is being removed | Any non-zero exit fails removal if the directory remains |
PreCompact | Before compaction | Blocks compaction |
PostCompact | After compaction | Stderr to user only |
PreModelSwitch | Before a requested model switch | Blocks the switch |
PostModelSwitch | After the session model changes | Stderr to user only |
Elicitation | An MCP server requests user input | Denies the elicitation |
ElicitationResult | After the user answers an elicitation | Blocks the response (becomes decline) |
SessionEnd | Session terminates | Stderr to user only |
permissionDecision: "allow".hookSpecificOutput.permissionDecision: "deny" (PreToolUse, PreModelSwitch), hookSpecificOutput.decision.behavior: "deny" (PermissionRequest), top-level decision: "block" (UserPromptSubmit, UserPromptExpansion, PostToolUse, PostToolUseFailure, PostToolBatch, Stop, SubagentStop, ConfigChange, PreCompact, TaskCreated, PreModelSwitch).UserPromptSubmit, UserPromptExpansion, SessionStart, and PostModelSwitch; elsewhere it goes to the debug log.A policy hook is correctly built when it uses either exit 2 or a JSON decision supported by its event. Exit 1 alone is the defect.
| Handler | Default |
|---|---|
command, http, mcp_tool | 600 |
same, on UserPromptSubmit, PreModelSwitch, PostModelSwitch | 30 |
same, on MessageDisplay | 10 |
prompt | 30 |
agent | 60 |
SessionEnd | 1.5 total budget; a per-hook timeout raises it to the highest configured value, up to 60. Plugin hook timeouts do not raise it. CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS overrides it |
A timed-out command, http, or mcp_tool hook on PreToolUse does not block the tool call; on PreModelSwitch it blocks the switch. timeout is not enforced on a running async: true hook; it is enforced with asyncRewake.
| Handler type | Allowed on |
|---|---|
command, mcp_tool | Every event |
http | Every event except SessionStart and Setup |
prompt | PermissionDenied, PostToolBatch, PostToolUse, PostToolUseFailure, PreToolUse, Stop, SubagentStop, TaskCompleted, TaskCreated, TeammateIdle, UserPromptExpansion, UserPromptSubmit, PermissionRequest |
agent (experimental) | Same as prompt, except PermissionRequest, where an agent hook is skipped |
On PermissionDenied, prompt and agent hooks run but their output is discarded.
| Field | Applies to | Notes |
|---|---|---|
type | all | command, http, mcp_tool, prompt, agent |
if | all | One permission rule, such as Bash(git *). Evaluated only on PreToolUse, PostToolUse, PostToolUseFailure, PermissionRequest, PermissionDenied; on any other event the hook never runs. Best-effort filter, not an enforcement mechanism |
timeout | all | Seconds |
statusMessage | all | Spinner text |
once | all | Honored only in skill frontmatter; ignored in settings files and agent frontmatter |
command | command | Shell string, or the executable when args is set |
args | command | Exec form: no shell, each element one argument. Preferred when referencing ${CLAUDE_PROJECT_DIR} or ${CLAUDE_PLUGIN_ROOT} |
shell | command | bash or powershell; ignored when args is set |
async | command | Runs in the background; cannot block or decide |
asyncRewake | command | Background, and wakes Claude when the process exits 2 |
url, headers, allowedEnvVars | http | Blocks only through a 2xx JSON body; status codes alone never block |
server, tool, input | mcp_tool | Uses an already connected server |
prompt, model | prompt, agent | $ARGUMENTS receives the hook input |
| Matcher value | Evaluated as |
|---|---|
"*", "", or omitted | Match all |
Only letters, digits, _, -, spaces, ,, | | Exact string, or a list separated by | or , (hyphens need v2.1.195+) |
| Any other character | Unanchored JavaScript regex (Edit.* also matches NotebookEdit; anchor with ^...$) |
FileChanged and StopFailure use a narrower exact set (letters, digits, _, |). Each event filters a different field:
| Event | Matcher filters |
|---|---|
PreToolUse, PostToolUse, PostToolUseFailure, PermissionRequest, PermissionDenied | tool name (Bash, Edit|Write, mcp__server__.*) |
SessionStart | startup, resume, clear, compact, fork |
Setup | init, maintenance |
SessionEnd | clear, resume, logout, prompt_input_exit, other |
Notification | notification type |
SubagentStart, SubagentStop | agent type |
PreCompact, PostCompact | manual, auto |
PreModelSwitch, PostModelSwitch | canonical target model name |
ConfigChange | configuration source |
DirectoryAdded | slash_command, register_repo_root |
FileChanged | literal filenames to watch |
StopFailure | error type |
InstructionsLoaded | load reason |
UserPromptExpansion | command name |
Elicitation, ElicitationResult | MCP server name |
No matcher support (a matcher is silently ignored): UserPromptSubmit, PostToolBatch, Stop, TeammateIdle, TaskCreated, TaskCompleted, WorktreeCreate, WorktreeRemove, CwdChanged, MessageDisplay.
PermissionRequest hooks also run in sessions that cannot show a prompt, such as background subagents in -p mode; if no hook decides, the call is denied.PreToolUse decisions resolve as deny > defer > ask > allow. The documentation does not define which updatedInput wins when several hooks rewrite the same call.Stop and SubagentStop continuations, through decision: "block" or additionalContext, are bounded by the stop_hook_active input and an 8-consecutive-continuation cap.read, fzf, gum, any TUI) cannot get input. Use terminalSequence in JSON output for notifications.| Location | Scope | Notes |
|---|---|---|
| Managed policy settings | Organization | Cannot be disabled by user, project, or local disableAllHooks |
~/.claude/settings.json | User | Not read by cloud sessions |
.claude/settings.json | Project, committed | |
.claude/settings.local.json | Project, personal | |
Plugin hooks/hooks.json | While the plugin is enabled | |
Skill frontmatter hooks: | Rest of the session once the skill is invoked | once: true honored here only |
Subagent frontmatter hooks: | While that subagent runs | Stop becomes SubagentStop. Project subagent hooks run only after workspace trust is accepted, including in -p |
~/.claude/settings.local.json is not a documented settings location. If it exists, report it as undocumented and do not score its hooks as active.
Also record, from the effective settings:
disableAllHooks: true disables every non-managed hook; only a managed-level value disables managed hooks.allowManagedHooksOnly blocks user, project, local, and plugin hooks (plugins force-enabled in managed enabledPlugins are exempt).allowedHttpHookUrls and httpHookAllowedEnvVars restrict HTTP hooks from every source.-p and SDK sessions treat the folder as trusted.| Location | Notes |
|---|---|
~/.codex/hooks.json | User |
~/.codex/config.toml inline [hooks] | User |
<repo>/.codex/hooks.json, <repo>/.codex/config.toml | Loaded only when the project .codex/ layer is trusted |
Plugin hooks/hooks.json, or a hooks entry in .codex-plugin/plugin.json | Manifest paths must stay inside the plugin root |
Managed requirements.toml [hooks] | Trusted by policy; allow_managed_hooks_only = true skips user, project, session, and plugin hooks |
Every source loads; higher layers do not replace lower ones. A layer holding both hooks.json and inline [hooks] is merged with a startup warning: flag it and recommend one representation per layer. [features] hooks = false turns hooks off (codex_hooks is a deprecated alias).
Every non-managed hook, plugin hooks included, must be reviewed and trusted in /hooks before it runs. Trust is recorded against the hook's current hash, so an edited hook is skipped until trusted again. When auditing, report that a changed hook needs review; do not assume it runs. The /hooks browser is the authoritative view of trust. Current Codex builds also persist it under [hooks.state] in config.toml, which is undocumented: report what you observe there without printing hash values, and never treat [hooks.state] as an event. --dangerously-bypass-hook-trust bypasses the check for one invocation only: flag any automation that relies on it.
Check how codex is launched before reading trust state as runtime behavior: type codex and which -a codex. A terminal integration can put a wrapper first on PATH that adds --dangerously-bypass-hook-trust and -c hooks... overrides to every invocation; Codex then lists the flag among its startup warnings. Observed with cmux, whose wrapper skips the injection when CMUX_CODEX_HOOKS_DISABLED=1. Under such a wrapper every hook runs without review: report that trust findings do not describe what runs.
| Event | Matcher filters |
|---|---|
PreToolUse, PostToolUse, PermissionRequest | tool name (Bash, apply_patch, MCP names; Edit or Write also match apply_patch) |
SessionStart | startup, resume, clear, compact |
SessionEnd | currently only other |
PreCompact, PostCompact | manual, auto |
SubagentStart, SubagentStop | subagent type |
UserPromptSubmit, Stop, Interrupt | not supported (matcher ignored) |
Codex matchers are regex strings. Interrupt and SessionEnd do not run for subagents.
command and mcp_tool handlers run. prompt and agent handlers are parsed and skipped: flag them as dead configuration.timeout is in seconds, default 600. SessionEnd and Interrupt default to 1 and allow at most 3.statusMessage, async, additionalContextLimit (default 2,500 tokens; 0 passes everything and can flood the context), commandWindows / command_windows.cwd. For repo-local scripts, resolve from the git root rather than a relative .codex/hooks/... path.PreToolUse ignores plain-text stdout. It blocks with permissionDecision: "deny", legacy decision: "block", or exit 2 with the reason on stderr. It rewrites a call with permissionDecision: "allow" plus updatedInput (a string command for Bash and apply_patch, the replacement arguments for MCP tools), the same shape Claude Code uses. permissionDecision: "ask", continue, stopReason, and suppressOutput are not supported there: Codex marks the hook run as failed and continues the tool call. Flag any Codex policy hook that relies on them.async) hooks cannot block, approve, or rewrite; at most eight run concurrently; SessionEnd always runs synchronously.SessionEnd does not support MCP tool hooks.SessionStart hook printing two JSON objects ({"async": true, ...} then a metrics object) fails with hook returned invalid session start JSON output, and a Stop hook printing {"metrics": ...} fails with hook returned invalid stop hook JSON output. Read the hooks file that the plugin's .codex-plugin/plugin.json names, which can differ from hooks/hooks.json (for example hooks/codex-hooks.json), run each plugin hook once with a sample payload for its event, and parse stdout against that event's contract. Recommend disabling the plugin in Codex when several of its events fail.| # | Criterion | Max | What is checked |
|---|---|---|---|
| 1 | event and handler type | 1 | The event exists for this host, and the handler type is allowed on it (a Claude agent hook on PermissionRequest or a Codex prompt hook scores 0) |
| 2 | matcher | 2 | No matcher on an event without matcher support, or a matcher using that event's documented values (1); not a match-all or broad regex on a tool event paired with a slow command (1) |
| 3 | command | 3 | Non-empty (1); the script or binary resolves on disk, after substituting ${CLAUDE_PROJECT_DIR}, ${CLAUDE_PLUGIN_ROOT}, or the git root (1); the script is executable, or it is passed to an interpreter (bash script.sh, python3 script.py) or run in exec form with a resolvable executable (1) |
| 4 | timeout | 2 | The effective timeout (explicit or documented default) fits the event: interactive-path hooks (PreToolUse, PermissionRequest, UserPromptSubmit, PreModelSwitch, Stop) under 30 s or backed by an internal timeout guard (1); no explicit value that exceeds a documented cap or budget, such as a Codex SessionEnd above 3 or a Claude SessionEnd above 60 (1) |
| 5 | blocking awareness | 2 | For a hook meant to enforce a policy: blocks through exit 2 or a JSON decision supported by the event and host, not exit 1 (1); no interactive command, no reliance on a timeout to block PreToolUse, no unsupported Codex output field (1) |
| Bonus | hygiene | +1 | No redundant copy of the same handler within one scope, and $CLAUDE_PROJECT_DIR or a git-root path instead of a hardcoded project-local absolute path |
Thresholds:
Observational hooks (logging, context injection, formatting, events that cannot block): skip criterion 5 and score on 8 pts max. Flag with 🔵. Decide "meant to enforce a policy" from the script and the user's answer, not from the event name alone.
List the locations that exist for each host in scope. Claude Code:
ls ~/.claude/settings.json .claude/settings.json .claude/settings.local.json 2>/dev/null
ls ~/.claude/settings.local.json 2>/dev/null && echo "undocumented location"
Codex:
ls ~/.codex/hooks.json ~/.codex/config.toml .codex/hooks.json .codex/config.toml 2>/dev/null
type codex; which -a codex # a wrapper first on PATH can inject hooks and bypass trust
Plugins are part of the default scope because their hooks run while the plugin is enabled. For Claude Code, take enabled plugins from enabledPlugins in the effective settings and the installed version of each from ~/.claude/plugins/installed_plugins.json; the plugin cache may hold several versions and temporary checkouts, so read only the installed one. List every plugin hook; score them only when the user asks, since the user does not own that code. For Codex, read plugin hooks/hooks.json or the hooks entry of .codex-plugin/plugin.json.
Also read hooks: blocks in .claude/skills/**/SKILL.md and .claude/agents/**/*.md, following symlinked skill directories. Managed settings and requirements.toml are read-only for this audit: report them, never edit them.
Note which hooks an external installer owns (for example a tool with an install-hooks or upgrade command). Such an installer can restore its entries after a manual cleanup, so recommend a change through that tool, or record the drift risk next to the proposal.
Build a flat list of hook records:
host: claude or codexsource_file and scopeevent_type, matcher (or absent)type and its type-specific fields (command, args, url, server/tool, prompt)timeout (seconds, explicit or default), async, asyncRewake, if, onceIf no hooks are found in any location, report it and stop.
Done when: every existing location is listed with its host and scope, and each hook has a record (or the audit stopped with "no hooks found").
Split a shell-form command into shell words before resolving it. A first-word split with awk is wrong: it keeps quotes and splits "$CLAUDE_PROJECT_DIR"/.claude/hooks/x.sh into two words. Use a shell-word parser:
python3 - "$command" "$PROJECT_ROOT" <<'EOF'
import os, shlex, shutil, sys
cmd, root = sys.argv[1], sys.argv[2]
words = shlex.split(cmd.split(';')[-1].split('&&')[-1])
words = [os.path.expanduser(w.replace('${CLAUDE_PROJECT_DIR}', root).replace('$CLAUDE_PROJECT_DIR', root)) for w in words]
while words and (words[0] == 'env' or '=' in words[0].split('/')[0]):
words.pop(0) # skip env and VAR=value prefixes
exe = words[0] if words else ''
path = exe if '/' in exe else (shutil.which(exe) or '')
print('executable', exe, 'found' if path and os.path.exists(path) else 'not found', 'x' if path and os.access(path, os.X_OK) else '-')
if os.path.basename(exe) in {'bash', 'sh', 'zsh', 'node', 'python3', 'python', 'deno', 'bun'}:
script = next((w for w in words[1:] if not w.startswith('-')), '')
print('script', script, 'found' if os.path.isfile(script) else 'not found', 'readable' if os.access(script, os.R_OK) else '-')
EOF
args (exec form), command is resolved on PATH or as a path; args elements are literal.bash script.sh, node script.js, python3 script.py, check that the script exists and is readable; it does not need chmod +x.${CLAUDE_PROJECT_DIR} with the project root and $(git rev-parse --show-toplevel) with the repository root before testing.export PATH=...; tool ..., resolve the last command that does the work, and note the chain.PATH now proves only the current shell's PATH, not the environment the host gives hooks. Mark it resolved, and say that the runtime PATH is not verified.Flag:
chmod +xcwd, which variesread, fzf, gum, TUI): hooks have no controlling terminalDone when: every command hook is marked found or not found, executable or not, with the resolved path.
For hooks on events that can block (see the tables above) whose command is a local script:
permissionDecision: "deny", decision.behavior: "deny", decision: "block"): ✅, whatever the exit codePermissionRequest (Claude Code): ⚠️ not honored; use the decision objectpermissionDecision: "ask" or continue: false on PreToolUse: ⚠️ unsupported, the tool call continuescurl, sleep, network calls) without an internal timeout guard in hooks on the interactive path.timeout, check whether it runs detached (( ... ) & with disown, nohup, setsid). Detached work outlives the hook, so a short timeout is correct there; report the detached work instead.--version or --help), classify the blocking strategy as UNKNOWN, and propose a behavior canary (a sample payload on stdin, then the exit code and stdout).codex subcommand in place of a claude one), run both on the same sample payload from more than one working directory, including a scratch repository outside your usual projects, and compare each output with the host's contract. The output can depend on the directory: with rtk 0.50.0, rtk hook claude returned updatedInput with permissionDecision: "allow" in one repository and without the decision in a scratch repository, which Codex rejects (PreToolUse hook returned updatedInput without permissionDecision:allow); rtk hook codex returned the decision in both. A Claude-named handler under Codex is not a defect only when its output fits the Codex contract in every directory tested.Hook failed lines and, for a checkpointing tool, the records written per edit. Report the host version and the exact failure messages.Done when: every script-backed hook on a blocking event has one of the classifications above, or UNKNOWN with a proposed canary, and every host-specific variant verdict cites the directories it was tested in.
if on a non-tool event (the hook never runs).once outside skill frontmatter (ignored).async: true combined with a decision field (no effect).PreToolUse hooks on the same matcher returning updatedInput (winner undocumented).stop_hook_active.hooks.json and inline [hooks]; hooks awaiting trust review. When both representations run the same tool on the same event, even through different command strings (a wrapper script and the binary it calls), report a real double run, and name the installer that owns each entry.headers or env. Report the file and line with the value redacted, and recommend moving the value out of the source and rotating it.Done when: each finding is attached to a hook record, or the list is explicitly empty.
Process hooks one by one. Do not batch and skip the interaction.
For each hook:
Show:
Hook: PreToolUse → Bash [claude, project settings]
type: command
command: ${CLAUDE_PROJECT_DIR}/.claude/hooks/confirm-git-push.sh
timeout: (none, default 600s)
Script: found (executable ✅)
Blocking strategy: JSON permissionDecision "deny" ✅
Ask three questions:
For lifecycle hooks (no matcher):
Show:
Hook: SessionEnd [claude, user settings]
type: command
command: ~/.claude/hooks/session-summary.sh
timeout: (none, 1.5s SessionEnd budget)
Script: found (executable ✅)
Ask:
If the user provides changes during the interaction: apply them using Edit, confirm each change, then move to the next hook. Never edit managed settings or requirements.toml. After editing a Codex hook, remind the user that it must be trusted again in /hooks.
Done when: every hook has the user's three answers (or two for lifecycle hooks) and every agreed edit is applied and confirmed.
After all hooks are reviewed:
# Hooks Audit: [project or global]
Date: [today] | Scanned: N hooks across M files (Claude Code: X, Codex: Y)
## Summary
| Status | Count |
|--------|-------|
| ✅ Good (≥80%) | N |
| ⚠️ Needs work (50-79%) | N |
| ❌ Fix (<50%) | N |
| 🔵 Observational | N |
| ✅ User confirmed useful | N |
| ⚠️ User flagged for update | N |
| 🗑️ User marked as stale | N |
---
## Per-Hook Results
### PreToolUse → Bash [claude, user settings] (7/10 ⚠️)
type: command
command: `~/.claude/hooks/confirm-git-push.sh`
timeout: (none, default 600s)
| Criterion | Score | Notes |
|-----------|-------|-------|
| event and handler type | ✅ 1/1 | PreToolUse, command |
| matcher | ✅ 2/2 | scoped to Bash |
| command | ✅ 3/3 | found, executable |
| timeout | ⚠️ 1/2 | 600s default on the interactive path, script calls the network without a guard |
| blocking awareness | ⚠️ 0/2 | block path exits 1 without JSON: the tool call proceeds |
**Priority fixes:**
1. Replace `exit 1` with `exit 2`, or print a `permissionDecision: "deny"` JSON object
2. Add `"timeout": 10` or an internal timeout around the network call
User feedback: ✅ scope correct
Content: exit strategy fixed ✅
---
### PostToolUse → Edit|Write [claude, user settings] (8/8 ✅) 🔵
type: command
command: `~/.claude/hooks/anti-ai-markers.sh`
timeout: 2
Observational hook: exit 2 would only show stderr to Claude. All applicable criteria pass. User confirmed still useful.
---
Done when: the report lists every scanned hook with its score and criterion notes.
## What Changed This Session
confirm-git-push.sh hook:
- Exit strategy changed to exit 2
- Added timeout: 10
session-summary.sh hook:
- User confirmed useful, no changes
rtk-baseline.sh hook (codex):
- Edited; needs re-trust in /hooks
- User flagged as stale (awaiting explicit deletion confirmation)
---
N hooks audited · N edits applied · N flagged as stale · N redundant copies · N awaiting Codex trust review
For any hook the user marked as stale: ask for explicit confirmation before removing it. Never delete without a clear "yes, remove it".
Done when: the summary line counts match the per-hook results and no deletion happened without explicit confirmation.
rtk hook claude): skip script-level checks, verify the binary is on PATHbash -c '...' inline: parse the inner script for interactive commands and exit logicexit 1 in a policy hook without JSON: ⚠️ non-blocking, the action proceedstimeout: 0: flag as likely invalidPreToolCall): ❌, report the exact string and suggest the documented name for that hostPostToolUseFailure, PreModelSwitch) or the reverse (Interrupt in Claude settings): ❌ never fires on that hostchmod +xasync: true with decision or permissionDecision: ⚠️ no effectasyncRewake: true: background, wakes Claude on exit 2 with stderr (or stdout); use it instead of async when a background failure must reach Claudeprompt or agent hook: no command to resolve; check that prompt is present and that the event allows the typePermissionRequest in -p or background subagents (Claude Code): hooks still run; if none decides, the call is denied. Do not recommend migrating to PreToolUse for that reasonif on a non-tool event: the hook never runs; remove if or change the eventstop_hook_active check: continuations stop at the 8-consecutive cap; read the field and exit 0 when it is true${CLAUDE_PROJECT_DIR}/... (Claude Code, exec form preferred) or a git-root-based path (Codex)/hooks (read-only browser showing each hook's source) and run with --debug. Codex: open /hooks to see sources, pending trust reviews, and disabled hooksまだレビューはありません。使ってみた感想をお寄せください。
概要と使いどころ
Audit Claude Code agents, skills, and commands for quality and production readiness. Use when evaluating skill quality, checking production readiness scores, or comparing agents against best-practice templates.
日本語の概要は準備中です。原文の説明を表示しています。
Codebase health audit scoring 7 categories with progression plan
日本語の概要は準備中です。原文の説明を表示しています。
Autonomous improvement loop: scan codebase metrics, scaffold experiment files, run agent-driven iterations until metric improves
日本語の概要は準備中です。原文の説明を表示しています。
Generate bounded independent candidates, score them against a frozen rubric, and verify the selected result with a proof log.
日本語の概要は準備中です。原文の説明を表示しています。
Post-deploy monitoring: watch production after a deploy and alert on regressions
日本語の概要は準備中です。原文の説明を表示しています。
Restore context after /clear by summarizing recent work and project state
日本語の概要は準備中です。原文の説明を表示しています。