Skip to content
Development
Hook

Hooks

What claude-code-config runs automatically, and when. A hook is a command Claude Code fires at a fixed moment, without you asking for it.

From plugin
claude-code-config
2.1k4 commands2 hooks

Where it lives

  • hooks/enforce-package-manager.shGitHub
    Read the script
    #!/bin/bash
    set -euo pipefail
    # EXAMPLE: PreToolUse hook — blocks npm in projects that use pnpm.
    # Adapt for any "use X not Y" convention (e.g., yarn vs npm, uv vs pip).
    CMD=$(jq -r '.tool_input.command // empty')
    [[ -z "$CMD" ]] && exit 0
    
    # Only enforce if this project uses pnpm
    [[ ! -f "${CLAUDE_PROJECT_DIR}/pnpm-lock.yaml" ]] && exit 0
    
    if echo "$CMD" | grep -qE '^npm\s'; then
      echo "BLOCKED: This project uses pnpm, not npm. Use pnpm instead." >&2
      exit 2
    fi
    exit 0
    
  • hooks/log-gam.shGitHub
    Read the script
    #!/bin/bash
    set -euo pipefail
    # EXAMPLE: PostToolUse hook — logs GAM (Google Apps Manager) write operations
    # to JSONL. Adapt the verb patterns for any CLI tool where you want an audit
    # trail of mutations. See README.md for wiring instructions.
    INPUT=$(cat)
    COMMAND=$(echo "${INPUT}" | jq -r '.tool_input.command // empty')
    
    [[ -z "${COMMAND}" ]] && exit 0
    [[ "${COMMAND}" != *'gam7/gam '* ]] && exit 0
    
    # Verb lists verified against GamCommands.txt v7.33.00
    READ_PATTERN='(print|show|info|get|list|report|check|version|help)'
    WRITE_PATTERN='(create|add|update|delete|remove|suspend|unsuspend|wipe|sync|move|transfer|trash|purge|enable|disable|deprovision)'
    
    GAM_ARGS="${COMMAND#*gam7/gam }"
    FIRST_WORD="${GAM_ARGS%% *}"
    
    # Skip read operations
    echo "${FIRST_WORD}" | grep -qiE "^${READ_PATTERN}$" && exit 0
    
    # Match write verb
    ACTION=$(echo "${GAM_ARGS}" | grep -oiE "(^|[[:space:]])${WRITE_PATTERN}([[:space:]]|$)" \
      | head -1 | tr -d ' ' || true)
    [[ -z "${ACTION}" ]] && exit 0
    
    # Log the mutation
    EXIT_CODE=$(echo "${INPUT}" | jq -r '.tool_result.exit_code // 0')
    [[ "${EXIT_CODE}" == "0" ]] && STATUS="success" || STATUS="failed"
    LOG_FILE="${CLAUDE_PROJECT_DIR}/google/.changelog-raw.jsonl"
    mkdir -p "$(dirname "${LOG_FILE}")"
    
    jq -nc \
      --arg ts "$(date -u +"%Y-%m-%dT%H:%M:%SZ")" \
      --arg action "${ACTION}" \
      --arg command "${COMMAND}" \
      --arg status "${STATUS}" \
      '{timestamp: $ts, action: $action, command: $command, status: $status}' \
      >> "${LOG_FILE}"
    
    # Remind the operator
    if [[ "${STATUS}" == "success" ]]; then
      echo "GAM MUTATION: ${ACTION} — logged to ${LOG_FILE}"
    fi
    exit 0
    

Read the script before you install anything that runs on your machine. This is the one part of a plugin that acts without being asked.

Ships withclaude-code-config

Opinionated defaults, documentation, and workflows for Claude Code at Trail of Bits. Covers sandboxing, permissions, hooks, skills, MCP servers, and usage patterns we've found effective across security audits, development, and research.

Get the whole plugin
Stats
2,059
Stars
153
Forks
Maintained
Maintenance
Shell
Language
4mo ago
Last commit
6mo ago
Created

Repo: trailofbits/claude-code-config