Clone
1
RFC-Hook-Efficiency-Improvements
Leo Miranda edited this page 2026-01-29 04:18:10 +00:00

RFC: Hook Efficiency Improvements

Status: Proposal
Created: 2026-01-28
Author: Claude Code Analysis
Priority: Medium
Estimated Effort: 2-3 sprints


Executive Summary

Analysis of the 16 hooks across 12 plugins revealed significant inefficiencies in trigger timing, matcher precision, and redundant operations. This RFC proposes changes to reduce session startup latency, minimize per-edit overhead, and eliminate duplicate logic.


Current State

Hook Inventory

Plugin Event Matcher Script Lines
projman SessionStart - startup-check.sh 119
pr-review SessionStart - startup-check.sh 31
claude-config-maintainer SessionStart - enforce-rules.sh 69
data-platform SessionStart - startup-check.sh 55
viz-platform SessionStart - inline echo 1
cmdb-assistant SessionStart - startup-check.sh 67
contract-validator SessionStart - auto-validate.sh 196
doc-guardian PostToolUse Write|Edit|MultiEdit notify.sh 75
code-sentinel PreToolUse Write|Edit|MultiEdit security-check.sh 63
data-platform PostToolUse Edit|Write schema-diff-check.sh 139
contract-validator PostToolUse Edit|Write breaking-change-check.sh 175
project-hygiene PostToolUse Write|Edit cleanup.sh 29
cmdb-assistant PreToolUse NetBox MCP tools validate-input.sh 80
git-flow PreToolUse Bash branch-check.sh 103
git-flow PreToolUse Bash commit-msg-check.sh 75
clarity-assist UserPromptSubmit - vagueness-check.sh 217

Total: 16 hooks, ~1,493 lines of shell code

Performance Impact

Per session startup:

  • 7 bash processes spawned
  • 3 Python invocations
  • 4 HTTP calls (Gitea API, NetBox API)
  • Estimated 200-500ms added latency

Per file edit:

  • 4 bash processes spawned (PostToolUse hooks)
  • 1 bash process spawned (PreToolUse - code-sentinel)
  • Multiple find and git commands
  • Each hook independently parses JSON stdin

Issues Identified

Issue 1: SessionStart Hook Overload

Problem: 7 hooks run on every session, regardless of whether the user will use that plugin.

Affected plugins:

  • projman
  • pr-review
  • claude-config-maintainer
  • data-platform
  • viz-platform
  • cmdb-assistant
  • contract-validator

Specific concerns:

  • projman makes HTTP calls to Gitea API to check open issues
  • cmdb-assistant makes HTTP calls to NetBox API
  • data-platform spawns Python and attempts PostgreSQL connection
  • contract-validator computes MD5 hashes of all plugin files
  • viz-platform just echoes "loaded" - zero value

Issue 2: Duplicate Logic Across Hooks

Problem: Multiple hooks implement the same checks.

Check Implemented by
MCP venv exists projman, pr-review, data-platform
Git remote vs .env mismatch projman, pr-review
JSON stdin parsing 8 different hooks
File path extraction from JSON 8 different hooks

Issue 3: Overly Broad Matchers

Problem: Some hooks trigger far more often than needed.

Hook Matcher Problem
git-flow/branch-check.sh Bash Triggers on every bash command
git-flow/commit-msg-check.sh Bash Triggers on every bash command
project-hygiene/cleanup.sh Write|Edit Runs find on entire project every edit
data-platform/schema-diff-check.sh Edit|Write Checks every file, then pattern-matches

Issue 4: clarity-assist Always-On

Problem: vagueness-check.sh (217 lines) runs on every user prompt.

  • Parses prompt
  • Runs multiple regex matches
  • Uses bc for floating-point calculations
  • Adds latency to every message

Current behavior: Opt-out (runs unless CLARITY_ASSIST_AUTO_SUGGEST=false)
Recommended: Opt-in (disabled unless explicitly enabled)

Issue 5: No Shared Utilities

Problem: Each hook implements its own:

  • JSON parsing
  • File path extraction
  • Prefix output formatting
  • Early exit conditions

Proposed Changes

Change 1: Consolidate SessionStart into Single Dispatcher

Create: scripts/hooks/session-dispatcher.sh

#!/bin/bash
# Single entry point for all SessionStart checks
# Runs common checks once, dispatches to plugins only when relevant

# Common checks (run once)
check_marketplace_health() { ... }
check_mcp_venvs() { ... }
check_git_remote() { ... }

# Plugin-specific checks (conditional)
if is_projman_project; then
    source_plugin_check "projman"
fi

Benefits:

  • Single process instead of 7
  • Common checks run once
  • Plugin checks only run if relevant

Files to modify:

  • Create scripts/hooks/session-dispatcher.sh
  • Create scripts/hooks/lib/common.sh (shared functions)
  • Update all plugin hooks.json to remove SessionStart
  • Add single SessionStart hook at marketplace level

Change 2: Add Path-Based Filtering to PostToolUse Hooks

Current: Hooks spawn, parse stdin, check path, usually exit.

Proposed: Check path relevance before detailed processing.

# At top of each PostToolUse hook
FILE_PATH=$(echo "$INPUT" | grep -o '"file_path"[[:space:]]*:[[:space:]]*"[^"]*"' | ...)

# Immediate exit for irrelevant paths
case "$FILE_PATH" in
    */node_modules/*|*/.git/*|*/venv/*|*/__pycache__/*)
        exit 0 ;;
esac

Affected hooks:

  • doc-guardian/notify.sh
  • data-platform/schema-diff-check.sh
  • contract-validator/breaking-change-check.sh
  • project-hygiene/cleanup.sh

Change 3: Smarter git-flow Bash Hooks

Current: Both hooks trigger on every Bash command.

Option A: Early command check before full parsing

# Quick check - if not git command, exit immediately
if ! echo "$INPUT" | grep -q '"command".*git'; then
    exit 0
fi

Option B: Combine into single hook

# Single git-flow hook that handles both branch and commit validation

Files to modify:

  • plugins/git-flow/hooks/branch-check.sh
  • plugins/git-flow/hooks/commit-msg-check.sh
  • Optionally merge into plugins/git-flow/hooks/git-validator.sh

Change 4: Remove viz-platform SessionStart Hook

Current:

{
  "event": "SessionStart",
  "type": "command",
  "command": "echo 'viz-platform plugin loaded'"
}

Proposed: Delete entirely. Provides zero value.

Files to modify:

  • plugins/viz-platform/hooks/hooks.json - remove the hook

Change 5: Make clarity-assist Opt-In

Current: Enabled by default, check CLARITY_ASSIST_AUTO_SUGGEST=false to disable.

Proposed: Disabled by default, check CLARITY_ASSIST_AUTO_SUGGEST=true to enable.

# Change from:
AUTO_SUGGEST="${CLARITY_ASSIST_AUTO_SUGGEST:-true}"

# To:
AUTO_SUGGEST="${CLARITY_ASSIST_AUTO_SUGGEST:-false}"

Files to modify:

  • plugins/clarity-assist/hooks/vagueness-check.sh (line 11)
  • plugins/clarity-assist/README.md (document opt-in)

Change 6: Create Shared Hook Library

Create: scripts/hooks/lib/common.sh

#!/bin/bash
# Shared utilities for all hooks

# Parse file_path from JSON stdin
extract_file_path() {
    echo "$1" | grep -o '"file_path"[[:space:]]*:[[:space:]]*"[^"]*"' | \
        head -1 | sed 's/.*"file_path"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/'
}

# Parse command from JSON stdin
extract_command() {
    echo "$1" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('command',''))" 2>/dev/null
}

# Standard prefix output
hook_output() {
    local prefix="$1"
    shift
    echo "[$prefix] $*"
}

# Check if path is in ignorable location
is_ignored_path() {
    case "$1" in
        */node_modules/*|*/.git/*|*/venv/*|*/__pycache__/*|*/.venv/*)
            return 0 ;;
    esac
    return 1
}

Benefits:

  • Consistent behavior across hooks
  • Single place to fix bugs
  • Reduced code duplication

Change 7: Optimize project-hygiene Cleanup

Current: Runs find across entire project on every edit.

Proposed:

  1. Only run cleanup after significant operations (not every edit)
  2. Use more targeted paths
  3. Add cooldown period (don't run if ran in last 5 minutes)
# Add cooldown
LAST_RUN_FILE="/tmp/project-hygiene-last-run"
if [[ -f "$LAST_RUN_FILE" ]]; then
    LAST_RUN=$(cat "$LAST_RUN_FILE")
    NOW=$(date +%s)
    if (( NOW - LAST_RUN < 300 )); then
        exit 0  # Skip if ran in last 5 minutes
    fi
fi

Files to modify:

  • plugins/project-hygiene/hooks/cleanup.sh

Implementation Order

Phase 1: Quick Wins (Low effort, high impact)

  1. Remove viz-platform SessionStart hook
  2. Make clarity-assist opt-in
  3. Add early exit to git-flow hooks

Phase 2: Optimizations (Medium effort)

  1. Add path filtering to PostToolUse hooks
  2. Add cooldown to project-hygiene
  3. Create shared hook library

Phase 3: Architecture (Higher effort)

  1. Consolidate SessionStart into dispatcher
  2. Refactor all hooks to use shared library

Testing Plan

Before changes

  • Measure session startup time (10 runs, average)
  • Measure time to complete 10 file edits
  • Count hook invocations via logging

After each phase

  • Re-measure all metrics
  • Verify no functionality lost
  • Test on both dev machine and Raspberry Pi (hotport)

Expected improvements

  • SessionStart: 200-500ms → 50-100ms (4-5x faster)
  • Per-edit overhead: 100-200ms → 20-50ms (4x faster)
  • Process spawns: 7 SessionStart + 5 per-edit → 1 SessionStart + 2-3 per-edit

Risks and Mitigations

Risk Mitigation
Breaking existing functionality Comprehensive test plan, phase rollout
Shared library versioning Keep library in marketplace root, plugins reference via relative path
User config migration (clarity-assist) Document in CHANGELOG, mention in release notes

Open Questions

  1. Should we support a hooks.json path matcher natively? (Would require Claude Code changes)
  2. Should SessionStart hooks be lazy-loaded on first plugin command instead?
  3. Is the shared library approach compatible with plugins being installed independently?

References

  • Analysis performed: 2026-01-28
  • Total hooks analyzed: 16
  • Total shell code: ~1,493 lines
  • Plugins affected: 12

Changelog

Date Change
2026-01-28 Initial RFC created