AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Cc Hooks

skill-costa-marcello-skillkit-cc-hooks · by costa-marcello

Creates and improves event-driven hooks for Claude Code automation. Use when building, debugging, or refactoring PreToolUse guards, PostToolUse formatters, Stop hooks for testing, SessionStart environment setup, agent-based verification gates, or integrating Claude Code with CI/CD pipelines.

No reviews yet
0 installs
25 views
0.0% view→install

Install

$ agentstack add skill-costa-marcello-skillkit-cc-hooks

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets Used
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-costa-marcello-skillkit-cc-hooks)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
3mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Cc Hooks? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Claude Code Hooks -- Reference

This skill provides the definitive reference for creating and improving Claude Code hooks -- event-driven scripts that respond to lifecycle events.

When to use:

  • Building or improving event-driven automation for Claude Code
  • Creating or refactoring PreToolUse guards to block dangerous commands
  • Debugging hooks that fail silently or produce unexpected results
  • Implementing PostToolUse formatters, linters, or auditors
  • Adding Stop hooks for testing or notifications
  • Setting up SessionStart/SessionEnd for environment management
  • Integrating Claude Code with CI/CD pipelines (headless mode)

Quick Reference

| Event | Decision Control | Hook Types | Use Case | |-------|-----------------|------------|----------| | SessionStart | No | command | Initialise environment, set CLAUDE_ENV_FILE | | UserPromptSubmit | No | command, prompt | Preprocess/validate input | | PreToolUse | allow/deny/ask + updatedInput | command, prompt | Validate, block dangerous commands | | PermissionRequest | allow/deny/ask | command, prompt | Auto-allow/deny permissions | | PostToolUse | block | command, prompt | Format, audit, notify | | PostToolUseFailure | block | command, prompt | Capture failures, add guidance | | Notification | No | command | Alert integrations | | SubagentStart | No | command | Inspect subagent metadata | | SubagentStop | block | command, prompt, agent | Verify subagent completion | | Stop | block | command, prompt, agent | Run tests, summarise | | TeammateIdle | exit code 2 only | command | Enforce quality gates before idle | | TaskCompleted | exit code 2 only | command | Block task completion if criteria not met | | PreCompact | No | command | Preserve critical context (matchers: manual, auto) | | SessionEnd | No | command | Cleanup, save state (matchers: clear, logout, prompt_input_exit) |

Hook Structure

.claude/hooks/
├── pre-tool-validate.sh
├── post-tool-format.sh
├── post-tool-audit.sh
├── stop-run-tests.sh
└── session-start-init.sh

Configuration

settings.json

{ "hooks": {
  "PostToolUse": [{ "matcher": "Edit|Write", "hooks": [
    { "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/post-tool-format.sh" }
  ]}],
  "PreToolUse": [{ "matcher": "Bash", "hooks": [
    { "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/pre-tool-validate.sh" }
  ]}],
  "Stop": [{ "hooks": [
    { "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/stop-run-tests.sh" }
  ]}]
}}

Execution Model

Hooks receive a JSON payload via stdin (treat it as untrusted input) and run with your user permissions (outside the Bash tool sandbox). Default timeout is 60s per hook command. All matching hooks run in parallel. Identical commands are deduplicated.

Hook Input (stdin)

{ "hook_event_name": "PreToolUse", "tool_name": "Bash", "tool_input": { "command": "ls -la" } }

Environment Variables (shell)

| Variable | Description | |----------|-------------| | CLAUDE_PROJECT_DIR | Absolute project root where Claude Code started | | CLAUDE_PLUGIN_ROOT | Plugin root (plugin hooks only) | | CLAUDE_CODE_REMOTE | "true" in remote/web environments; empty/local otherwise | | CLAUDE_ENV_FILE | File path to persist export ... lines (available in SessionStart; check docs for Setup support) |


Exit Codes

| Code | Meaning | Notes | |------|---------|------| | 0 | Success | JSON written to stdout is parsed for structured control | | 2 | Blocking error | stderr becomes the message; JSON in stdout is ignored | | Other | Non-blocking error | Execution continues; stderr is visible in verbose mode |

Stdout injection note: for UserPromptSubmit, SessionStart, and Setup, non-JSON stdout (exit 0) is injected into Claude's context. Most other events show stdout only in verbose mode.


Decision Control + Input Modification

PreToolUse hooks can allow/deny/ask and optionally modify the tool input via updatedInput.

Hook Output Schema

{ "hookSpecificOutput": {
  "hookEventName": "PreToolUse",
  "permissionDecision": "allow",
  "permissionDecisionReason": "Reason shown to user (and to Claude on deny)",
  "updatedInput": { "command": "echo 'modified'" },
  "additionalContext": "Extra context added before tool runs"
}}

Older decision/reason fields are deprecated. Use the hookSpecificOutput.* fields.

Redirect Sensitive File Edits

Input: PreToolUse event for an Edit targeting package-lock.json. Output: Redirect the edit to /dev/null with an allow decision.

#!/bin/bash
set -euo pipefail

INPUT="$(cat)"
FILE_PATH="$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')"

# Redirect package-lock.json edits to /dev/null
if [[ "$FILE_PATH" == *"package-lock.json" ]]; then
  UPDATED_INPUT="$(echo "$INPUT" | jq -c '.tool_input | .file_path = "/dev/null"')"
  jq -cn --argjson updatedInput "$UPDATED_INPUT" '{
    hookSpecificOutput: {
      hookEventName: "PreToolUse",
      permissionDecision: "allow",
      permissionDecisionReason: "Redirected write to /dev/null",
      updatedInput: $updatedInput
    }
  }'
  exit 0
fi

echo '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow"}}'

Strip Sensitive Files from Git Add

Input: PreToolUse event for a Bash command starting with git add that includes .env files. Output: Modified command with .env references removed.

#!/bin/bash
set -euo pipefail

INPUT="$(cat)"
TOOL_NAME="$(echo "$INPUT" | jq -r '.tool_name')"
CMD="$(echo "$INPUT" | jq -r '.tool_input.command // empty')"

if [[ "$TOOL_NAME" == "Bash" && "$CMD" =~ ^git[[:space:]]+add ]]; then
  # Remove .env files from staging
  SAFE_CMD="$(echo "$CMD" | sed 's/\.env[^ ]*//g')"
  if [[ "$SAFE_CMD" != "$CMD" ]]; then
    echo '{}' | jq -cn --arg cmd "$SAFE_CMD" '{
      hookSpecificOutput: {
        hookEventName: "PreToolUse",
        permissionDecision: "allow",
        permissionDecisionReason: "Removed .env from git add",
        updatedInput: { command: $cmd }
      }
    }'
    exit 0
  fi
fi

echo '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow"}}'

Prompt-Based Stop Hook

Input: Stop event with task context. Output: LLM evaluates whether all tasks are complete.

{ "hooks": { "Stop": [{ "hooks": [{ "type": "prompt", "prompt": "Evaluate whether Claude should stop. Context JSON: $ARGUMENTS. Return {\"ok\": true} if all tasks are complete, otherwise {\"ok\": false, \"reason\": \"what remains\"}.", "timeout": 30 }] }] }}

Response schema:

  • Allow: {"ok": true}
  • Block: {"ok": false, "reason": "Explanation shown to Claude"}

PostToolUse Audit Logger

Input: PostToolUse event after any file write. Output: Append a JSON line to an audit log (non-blocking).

#!/bin/bash
set -euo pipefail

INPUT="$(cat)"
TOOL_NAME="$(echo "$INPUT" | jq -r '.tool_name')"
FILE_PATH="$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')"
TIMESTAMP="$(date -u +%Y-%m-%dT%H:%M:%SZ)"

if [[ -n "$FILE_PATH" ]]; then
  echo "{\"timestamp\":\"$TIMESTAMP\",\"tool\":\"$TOOL_NAME\",\"file\":\"$FILE_PATH\"}" \
    >> "$CLAUDE_PROJECT_DIR/.claude/edit-audit.jsonl"
fi

exit 0

Settings matcher: "matcher": "Edit|Write" with "async": true.

SessionStart Environment Setup

Input: SessionStart event at session launch. Output: Write environment variables to CLAUDE_ENV_FILE so they persist across Bash calls.

#!/bin/bash
set -euo pipefail

cd "$CLAUDE_PROJECT_DIR"

# Persist environment variables for the session
if [[ -n "${CLAUDE_ENV_FILE:-}" ]]; then
  echo "export PROJECT_NAME=$(basename "$CLAUDE_PROJECT_DIR")" >> "$CLAUDE_ENV_FILE"
  echo "export NODE_ENV=development" >> "$CLAUDE_ENV_FILE"
fi

# Inject context into Claude's conversation
echo "=== Session Context ==="
git branch --show-current 2>/dev/null || echo "Not a git repo"
echo "Node: $(node --version 2>/dev/null || echo 'not installed')"

exit 0

Stdout is injected into Claude's context. CLAUDE_ENV_FILE exports persist across all Bash commands in the session.


Prompt-Based Hooks

For complex decisions, use LLM-evaluated hooks (type: "prompt") instead of bash scripts. They are most useful for Stop and SubagentStop decisions.

Default to command hooks for fast, deterministic checks. Use prompt hooks only when the decision requires natural language reasoning:

{ "Stop": [{ "hooks": [
  { "type": "command", "command": ".claude/hooks/quick-check.sh" },
  { "type": "prompt", "prompt": "Verify code quality meets standards" }
]}] }

Matchers

Matchers filter which tool triggers the hook:

  • Exact match: Write matches only the Write tool
  • Regex: Edit|Write or Notebook.*
  • MCP tools: mcp__github__.* or mcp____ (regex patterns)
  • Match all: * (also works with "" or omitted matcher)
  • Event-specific matchers: PreCompact supports manual/auto; SessionEnd supports clear/logout/prompt_input_exit

Security Best Practices

All hook templates already demonstrate set -euo pipefail, quoted variables, and absolute paths. Beyond those defaults, check for:

  • No eval with untrusted input (stdin JSON is attacker-controlled)
  • Target

References

  • [references/hook-templates.md](references/hook-templates.md) -- 15 ready-to-use templates: pre-tool validation, post-tool formatting, security audit, stop hooks, session start/end, context re-injection, async test runner, session state persistence, MCP audit logging, infinite loop guard, desktop notifications, bash logging, protected files, sprint context, session archiving
  • [references/input-output-schemas.md](references/input-output-schemas.md) -- Per-event JSON schemas (stdin input and stdout output) for all 14 hook events, plus tool-specific tool_input fields for Bash, Write, Edit, Read, Grep, Glob, and MCP tools
  • [references/command-vs-prompt.md](references/command-vs-prompt.md) -- Decision tree for choosing between command, prompt, and agent hook types. Performance comparison, prompt authoring guidance, and combining strategies
  • [references/tool-names.md](references/tool-names.md) -- Complete tool name reference (19+ built-in tools, MCP naming convention), advanced matcher patterns (anchored, negative lookahead, case-insensitive), and common matcher mistakes
  • [references/troubleshooting.md](references/troubleshooting.md) -- Step-by-step diagnostics for hooks not triggering, command failures, prompt issues, infinite loops, output visibility, timeouts, environment variables, and common pitfalls

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.