Skip to content
Back to skills

Plans Completed

ASecurity

Claude Code hooks have grown organically to 8 hook commands across 5 event types, with inconsistent safety practices. A manual audit uncovered: silent error swallowing (`|| true` without logging), `set -e` in bash hooks (fatal in hooks), missing `log_hook_error()` calls, and no codified best practices. When new hooks are added, there is no automated check that they follow established patterns.

  • 26 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 2, 2026
ai-agentspythongoshellbashgitapiperformancedocumentation

Works with

  • claude code
  • api
  • mcp

Security analysis

A100/100

Pro scans all 19 files and shows the line behind each finding

Scanned September 2, 2026

npx -y skills add tomcounsell/ai --skill plans-completed --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Plans Completed?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Plans Completed
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tomcounsell-plans-completed/badge)](https://www.skillsdirectory.com/skills/tomcounsell-plans-completed)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
status: Planning
type: feature
appetite: Medium
owner: Valor
created: 2026-04-02
tracking: https://github.com/tomcounsell/ai/issues/630
last_comment_id:
---

# Audit Hooks Skill

## Problem

Claude Code hooks have grown organically to 8 hook commands across 5 event types, with inconsistent safety practices. A manual audit uncovered: silent error swallowing (`|| true` without logging), `set -e` in bash hooks (fatal in hooks), missing `log_hook_error()` calls, and no codified best practices. When new hooks are added, there is no automated check that they follow established patterns.

**Current behavior:**
- No single reference document for hook safety patterns
- The existing `scripts/update/hooks.py` only audits SKILL.md frontmatter for `uv run` and missing scripts — it does not audit the actual hook scripts in `.claude/hooks/` or `settings.json` for safety, error logging, or timeout correctness
- `docs/features/hooks-session-logging.md` is marked "Superseded" but still exists, creating stale documentation
- Hook errors in `logs/hooks.log` are parseable by reflections but there is no dedicated reflections step that audits hook health

**Desired outcome:**
A `/audit-hooks` skill that codifies best practices, runs a comprehensive audit of settings.json and hook scripts, produces a structured report, and integrates with daily reflections for ongoing monitoring.

## Prior Art

- **Issue #42**: Standardize all commands and skills — closed, set precedent for skill structure
- **PR #525**: Wire Claude Code hooks to subconscious memory system — initial hook wiring, established `|| true` pattern
- **PR #603**: Fix hook session ID resolution via bridge-level registry — hook infrastructure fix
- **PR #327**: Remove dead SDLC stage-tracking code from hook files — previous hook cleanup
- **PR #195**: SDLC user-level hooks — original hook infrastructure
- **Issue #627**: Memory recall hook 344ms import tax — performance issue in PostToolUse hook discovered during the same audit session that created this issue

## Data Flow

1. **Entry point**: User runs `/audit-hooks` in Claude Code
2. **Skill SKILL.md**: Claude reads instructions and executes audit checks
3. **settings.json parse**: Extract all hook commands, matchers, timeouts, `|| true` presence
4. **Hook script inspection**: For each command, read the target script and check safety patterns
5. **BEST_PRACTICES.md comparison**: Each finding is classified against the codified rules
6. **Output**: Structured report with PASS/WARN/FAIL per hook, grouped by severity

For the reflections integration:
1. **Entry point**: Daily reflections run at 6:00 AM
2. **step_hooks_audit**: Scan `logs/hooks.log` for recent errors, validate settings.json consistency
3. **Findings**: Added to `state.findings["ai:hooks_audit"]` for inclusion in daily report

## Architectural Impact

- **New dependencies**: None — all checks use stdlib (json, pathlib, re)
- **Interface changes**: None — this is a new skill with no external API
- **Coupling**: Low — the skill reads settings.json and hook scripts but does not modify them
- **Data ownership**: No change — skill is read-only
- **Reversibility**: Trivial — delete the skill directory and reflections step

## Appetite

**Size:** Medium

**Team:** Solo dev, PM

**Interactions:**
- PM check-ins: 1 (scope alignment on best practices list)
- Review rounds: 1 (code review)

## Prerequisites

No prerequisites — this work uses only stdlib and reads existing project files.

## Solution

### Key Elements

- **SKILL.md**: Prompt-only audit skill (following `audit-models` pattern) that instructs Claude to run checks and produce a report
- **BEST_PRACTICES.md**: Codified hook safety patterns — the authoritative reference for this project's hook conventions
- **Reflections integration**: Lightweight `step_hooks_audit` in `scripts/reflections.py` that scans `logs/hooks.log` and validates settings.json consistency

### Flow

**User invokes `/audit-hooks`** → Claude reads SKILL.md → Parses settings.json → Inspects each hook script → Compares against BEST_PRACTICES.md → Produces structured report → User decides what to fix

**Daily reflections** → `step_hooks_audit` → Scan hooks.log for errors → Validate settings.json → Add findings to daily report

### Technical Approach

- The skill is prompt-only (`disable-model-invocation: true`, `allowed-tools: Read, Grep, Glob, Bash`) — Claude executes the audit checks, not a Python script
- BEST_PRACTICES.md is a standalone reference document read by both the skill and humans
- The reflections step is a lightweight Python function (no subprocess spawning) that:
  1. Calls `extract_structured_errors()` on `logs/hooks.log`
  2. Parses `.claude/settings.json` to check `|| true` correctness and file existence
  3. Reports findings via `state.findings`
- Feature doc `docs/features/hooks-best-practices.md` replaces the stale `hooks-session-logging.md`

## Failure Path Test Strategy

### Exception Handling Coverage
- The reflections `step_hooks_audit` must wrap all file I/O in try/except and log warnings rather than crashing the reflections run
- No exception handlers in existing code are modified by this work

### Empty/Invalid Input Handling
- The reflections step must handle: missing `logs/hooks.log` (no errors to report), malformed `settings.json` (log warning and skip), empty hook command strings
- The skill itself is prompt-only — Claude handles edge cases naturally

### Error State Rendering
- The skill produces a text report — error states are rendered as FAIL entries in the report table
- The reflections step adds findings to the daily report — no separate error rendering needed

## Test Impact

No existing tests affected — this is a greenfield feature adding a new skill, a new reflections step, and new documentation. No existing behavior or interfaces are modified.

## Rabbit Holes

- **Auto-fix mode**: Tempting to have the skill automatically patch hooks, but too risky for v1. Report-only is safer; the human decides what to fix.
- **Import weight profiling**: Measuring actual import times requires subprocess timing which is fragile and environment-dependent. Flag heavy imports heuristically (known slow modules) rather than measuring.
- **Cross-repo hook audit**: The skill will be hardlinked to `~/.claude/skills/`, but auditing hooks in other repos requires project-specific paths. Keep v1 focused on the ai repo's hooks; cross-repo is a future enhancement.
- **Hook execution tracing**: Runtime tracing of hook execution would be valuable but is a separate observability feature, not an audit.

## Risks

### Risk 1: Best practices become stale
**Impact:** New hook patterns emerge that aren't covered by BEST_PRACTICES.md, leading to false confidence.
**Mitigation:** The reflections step catches errors from `hooks.log` regardless of whether best practices are up to date. BEST_PRACTICES.md is a living document updated when new patterns are established.

### Risk 2: Reflections step adds latency
**Impact:** Daily reflections run takes longer.
**Mitigation:** The step only does file I/O (read hooks.log, parse settings.json) — no subprocess spawning, no API calls. Expected to add <1s.

## Race Conditions

No race conditions identified — the skill is read-only and the reflections step reads files that are only written by hook processes (which run during Claude Code sessions, not during the 6 AM reflections window).

## No-Gos (Out of Scope)

- Auto-fix mode (report-only in v1)
- Runtime import profiling (heuristic check only)
- Cross-repo hook auditing (ai repo only)
- Hook execution tracing / timing observability
- Modifying any existing hook scripts (this skill audits, it does not fix)

## Update System

The `/update` skill (`scripts/update/hardlinks.py`) already syncs `.claude/skills/` to `~/.claude/skills/` via hardlinks. The new `.claude/skills/audit-hooks/` directory will be picked up automatically — no changes to the update script or skill are needed.

No new dependencies or config files to propagate. No migration steps required.

## Agent Integration

No agent integration required — this is a Claude Code skill invoked directly by the human via `/audit-hooks`. It does not need MCP server exposure, bridge integration, or `.mcp.json` changes. The reflections integration runs as a step within the existing `scripts/reflections.py` process.

## Documentation

### Feature Documentation
- [ ] Create `docs/features/hooks-best-practices.md` describing the audit skill and best practices (replaces stale `hooks-session-logging.md`)
- [ ] Update `docs/features/README.md` index: replace `hooks-session-logging.md` row with `hooks-best-practices.md`
- [ ] Delete `docs/features/hooks-session-logging.md` (marked Superseded, content is outdated)

### Inline Documentation
- [ ] Docstring on `step_hooks_audit` in reflections.py
- [ ] Comments in BEST_PRACTICES.md explaining the rationale for each rule

## Success Criteria

- [ ] `.claude/skills/audit-hooks/SKILL.md` exists with frontmatter and audit instructions
- [ ] `.claude/skills/audit-hooks/BEST_PRACTICES.md` codifies all hook safety patterns
- [ ] Running `/audit-hooks` produces a structured report covering: settings.json consistency, `|| true` correctness, error logging coverage, import weight flags, deployment readiness
- [ ] `docs/features/hooks-best-practices.md` replaces stale `hooks-session-logging.md`
- [ ] `docs/features/README.md` index updated with new doc entry
- [ ] Reflections `step_hooks_audit` scans `logs/hooks.log` and validates settings.json consistency
- [ ] `/update` propagates the new skill to all machines via hardlink sync (no changes needed — automatic)
- [ ] Tests pass (`/do-test`)
- [ ] Documentation updated (`/do-docs`)

## Team Orchestration

### Team Members

- **Builder (skill)**
  - Name: skill-builder
  - Role: Create the audit-hooks skill (SKILL.md + BEST_PRACTICES.md)
  - Agent Type: builder
  - Resume: true

- **Builder (reflections)**
  - Name: reflections-builder
  - Role: Add step_hooks_audit to reflections.py
  - Agent Type: builder
  - Resume: true

- **Builder (docs)**
  - Name: docs-builder
  - Role: Create feature doc, update README index, delete stale doc
  - Agent Type: documentarian
  - Resume: true

- **Validator (all)**
  - Name: final-validator
  - Role: Verify all success criteria
  - Agent Type: validator
  - Resume: true

## Step by Step Tasks

### 1. Create BEST_PRACTICES.md
- **Task ID**: build-best-practices
- **Depends On**: none
- **Assigned To**: skill-builder
- **Agent Type**: builder
- **Parallel**: true
- Create `.claude/skills/audit-hooks/BEST_PRACTICES.md` codifying these rules:
  - Stop hooks MUST have `|| true` (failing stop hook blocks session exit)
  - Advisory hooks MUST have `|| true` (logging, memory, calendar, SDLC tracking hooks must never block)
  - Validator hooks MUST NOT have `|| true` (they exist to block; `|| true` defeats the purpose)
  - All `|| true` hooks MUST call `log_hook_error()` on failure (silent failure is invisible failure)
  - Bash hooks MUST use `set +e` (not `set -e` which causes hooks to exit on any subcommand failure)
  - Bash hooks MUST NOT use bare `exec` (prevents error recovery and logging)
  - Shell hooks MUST prefer venv binaries (`$CLAUDE_PROJECT_DIR/.venv/bin/` before system PATH)
  - Python hooks MUST minimize imports (lazy-import heavy modules; keep baseline <50ms)
  - Hook timeouts MUST match expected workload (5s simple, 10-15s API calls)
  - Each rule should include: rationale, good example, bad example

### 2. Create SKILL.md
- **Task ID**: build-skill
- **Depends On**: build-best-practices
- **Assigned To**: skill-builder
- **Agent Type**: builder
- **Parallel**: false
- Create `.claude/skills/audit-hooks/SKILL.md` with frontmatter (`disable-model-invocation: true`, `allowed-tools: Read, Grep, Glob, Bash`)
- Follow the `audit-models` skill pattern: structured checks, severity levels, report format
- The skill should instruct Claude to:
  1. Read `.claude/settings.json` and extract all hook entries
  2. For each hook: check `|| true` correctness (advisory vs validator), timeout appropriateness, matcher specificity
  3. For each Python hook script: check for `try/except` + `log_hook_error()` at `__main__`, no bare `sys.exit(1)` in advisory hooks, flag known-heavy imports
  4. For each bash hook script: check `set +e`, no bare `exec`, error logging to hooks.log, venv-first binary resolution
  5. Check deployment readiness: all referenced scripts exist and are importable
  6. Produce structured report with PASS/WARN/FAIL per hook

### 3. Add reflections step
- **Task ID**: build-reflections
- **Depends On**: none
- **Assigned To**: reflections-builder
- **Agent Type**: builder
- **Parallel**: true
- Add `step_hooks_audit` to `scripts/reflections.py`:
  - Register in the steps list (after `skills_audit`, before `redis_ttl_cleanup`)
  - Scan `logs/hooks.log` using `extract_structured_errors()` for errors in the last 24h
  - Parse `.claude/settings.json`: verify every hook command's target script exists, check `|| true` on Stop/SubagentStop hooks
  - Add findings to `state.findings["ai:hooks_audit"]`
  - Log summary: "Hooks audit: N errors in last 24h, M settings issues"
- Add unit test `tests/unit/test_hooks_audit_reflections.py` verifying the step handles missing files gracefully

### 4. Create feature documentation
- **Task ID**: build-docs
- **Depends On**: build-best-practices, build-skill
- **Assigned To**: docs-builder
- **Agent Type**: documentarian
- **Parallel**: false
- Create `docs/features/hooks-best-practices.md` describing:
  - The audit skill and how to run it
  - Summary of best practices (with link to full BEST_PRACTICES.md)
  - How the reflections integration works
  - How hooks are deployed via `/update`
- Update `docs/features/README.md`: replace `hooks-session-logging.md` row with `hooks-best-practices.md`
- Delete `docs/features/hooks-session-logging.md`

### 5. Final Validation
- **Task ID**: validate-all
- **Depends On**: build-skill, build-reflections, build-docs
- **Assigned To**: final-validator
- **Agent Type**: validator
- **Parallel**: false
- Verify `.claude/skills/audit-hooks/SKILL.md` and `BEST_PRACTICES.md` exist with correct frontmatter
- Verify `docs/features/hooks-best-practices.md` exists and `hooks-session-logging.md` is deleted
- Verify `docs/features/README.md` has updated entry
- Verify `step_hooks_audit` is registered in reflections step list
- Run `pytest tests/unit/test_hooks_audit_reflections.py -x`
- Run all success criteria checks

## Verification

| Check | Command | Expected |
|-------|---------|----------|
| Skill exists | `test -f .claude/skills/audit-hooks/SKILL.md` | exit code 0 |
| Best practices exists | `test -f .claude/skills/audit-hooks/BEST_PRACTICES.md` | exit code 0 |
| Feature doc exists | `test -f docs/features/hooks-best-practices.md` | exit code 0 |
| Stale doc removed | `test ! -f docs/features/hooks-session-logging.md` | exit code 0 |
| README updated | `grep -c "hooks-best-practices" docs/features/README.md` | output > 0 |
| Reflections step registered | `grep -c "hooks_audit" scripts/reflections.py` | output > 0 |
| Unit tests pass | `pytest tests/unit/test_hooks_audit_reflections.py -x -q` | exit code 0 |
| Lint clean | `python -m ruff check .claude/skills/audit-hooks/ scripts/reflections.py` | exit code 0 |
| Format clean | `python -m ruff format --check scripts/reflections.py` | exit code 0 |

## Critique Results

<!-- Populated by /do-plan-critique (war room). Leave empty until critique is run. -->

---

## Open Questions

1. Should the best practices document include a version number or changelog, or is git history sufficient for tracking changes to the rules?
2. The issue mentions an import weight check flagging imports >100ms — should we use a fixed list of known-heavy modules (e.g., anthropic, openai, pandas) or attempt actual timing? The plan assumes heuristic (fixed list) to avoid environment-dependent timing fragility.

Files in this skill

  • 440-session-watchdog-observer-fixes.md21.1 KB
  • 476_test_reliability.md3.4 KB
  • 488_consolidate_sdlc_stage_tracking.md10.4 KB
  • 542-utc-timestamp-normalization.md17.7 KB
  • README.md1.9 KB
  • action-intent-emoji-reactions.md44.1 KB
  • add-sustainability-row-to-legacy-artifact-guard.md27.2 KB
  • agent-message-delivery-tool-call-routing.md39.6 KB
  • agent-session-field-cleanup.md17.1 KB
  • agent-session-index-corruption.md15.3 KB
  • agent-session-job-rename.md23.2 KB
  • agent-session-model-audit.md20.4 KB
  • agent-session-schema-diet.md41.1 KB
  • agent_browser_to_byob_skill_migration.md60.5 KB
  • agent_judgment_catchup.md29.3 KB
  • agent_session_field_cleanup.md25.2 KB
  • agent_session_keyfield_rename.md15.8 KB
  • agent_session_role_generalization.md25 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…