Using Subagent Hooks for Validation in Claude Code: A Complete Security Guide

Subagent hooks in Claude Code are shell scripts that automatically intercept user prompts and tool executions, blocking dangerous operations by exiting with non-zero status while permitting safe workflows to proceed.

Claude Code extends the standard Claude AI model with subagents—lightweight, isolated assistants that operate in dedicated context windows. A critical component of this ecosystem is the hook system located in the 06-hooks/ directory of the luongnv89/claude-howto repository. These hooks enable automated validation, security scanning, and policy enforcement before any subagent action is finalized.

What Are Subagent Hooks?

Subagent hooks are shell scripts that Claude Code executes automatically when specific events occur during a subagent session. The system parses hook declarations from a subagent's YAML front-matter and registers them to run at precise lifecycle moments. If a hook exits with a non-zero status code, Claude Code blocks the associated operation entirely; if it exits with status 0, the workflow continues (potentially with logged warnings).

Hooks run in a sandboxed Bash environment and can read from stdin or process command-line arguments depending on the event type. This architecture allows you to implement validation logic without modifying the core Claude Code runtime.

The Hook-Driven Validation Workflow

Claude Code supports several event types for hook registration, each targeting different stages of subagent execution:

UserPromptSubmit Hooks

The UserPromptSubmit event fires immediately after a user submits a prompt to Claude Code. This hook receives the entire prompt via stdin, making it ideal for dangerous command detection and production deployment guards.

According to the source code in 06-hooks/validate-prompt.sh, this hook implements three critical checks:

  • Dangerous pattern matching—blocks strings like rm -rf /, drop database, or dd if= (case-insensitive)
  • Production deployment guard—requires a .deployment-approved flag file when prompts mention both deploy/push and production
  • Refactor sanity check—warns when refactoring is requested without an accompanying tests/ directory

PostToolUse:Write Hooks

The PostToolUse:Write event triggers after a subagent uses the Write tool to create or modify a file. The hook receives the file path as its first command-line argument ($1), enabling post-write security scanning.

As implemented in 06-hooks/security-scan.sh, this hook:

  • Greps for common secret patterns (passwords, API keys, AWS keys, private key delimiters)
  • Optionally runs semgrep or trufflehog if installed for deeper static analysis
  • Emits warnings for findings but exits with status 0 to avoid blocking legitimate file operations

PreToolUse and PostToolUse Hooks

The PreToolUse event fires before any tool invocation (such as Bash), while PostToolUse runs after tool completion. These hooks support matcher patterns to target specific tools, enabling fine-grained policy enforcement like pre-flight Bash command validation or post-execution cleanup.

How Validation Hooks Work Under the Hood

The validate-prompt.sh script in the 06-hooks/ directory demonstrates the validation pattern. When Claude Code invokes this hook, it streams the user prompt to the script's stdin. The script then performs regex-based pattern matching against a blacklist of dangerous operations.

If any check fails, the script prints a descriptive error message to stderr and exits with status 1. Claude Code detects this non-zero exit code and aborts the operation, presenting the error to the user. If all checks pass, the script exits 0 and the subagent proceeds with the request.

This mechanism provides a fail-closed security model—any hook crash or explicit rejection prevents potentially harmful actions from executing.

How Security Scan Hooks Work Under the Hood

The security-scan.sh script operates differently because it runs after the operation completes. When a subagent writes a file, Claude Code executes this hook with the absolute path as argument $1.

The script first performs lightweight grepping for high-entropy strings and known secret patterns. If semgrep or trufflehog binaries are detected in the PATH, it launches these tools for comprehensive secrets detection. Rather than blocking writes (which would disrupt legitimate development), this hook logs warnings to stdout and always exits 0, providing a safety net without interrupting the development flow.

Configuring Hooks in Subagent Front-Matter

Subagents declare hooks within their YAML front-matter under the hooks key. The configuration maps event names to command specifications using the type: command structure.

Basic Prompt Validation Subagent

This minimal configuration blocks dangerous commands before any action occurs:

---
name: prompt-validator
description: Blocks dangerous commands before any action.
tools: Read, Grep
hooks:
  UserPromptSubmit:
    - type: command
      command: "./06-hooks/validate-prompt.sh"
---
You are an assistant that only checks user prompts for safety. If the prompt passes,
proceed with the requested analysis; otherwise, refuse the request.

Pre-Tool Execution Guard

To validate Bash commands before execution, use the PreToolUse event with a matcher:

---
name: safe-bash-runner
description: Executes Bash scripts only after a custom safety scan.
tools: Bash
hooks:
  PreToolUse:
    - matcher: "Bash"
      hooks:
        - type: command
          command: "./scripts/my-bash-guard.sh"
---
You are a Bash executor. Before running any command, the guard script will verify
that the command does not contain forbidden patterns.

Comprehensive Security Subagent

For production environments, combine multiple hooks to create a defense-in-depth strategy:

---
name: security-assistant
description: Reviews changes, validates prompts, and scans written files.
tools: Read, Write, Grep, Bash
hooks:
  UserPromptSubmit:
    - type: command
      command: "./06-hooks/validate-prompt.sh"
  PostToolUse:Write:
    - type: command
      command: "./06-hooks/security-scan.sh"
---
You are a security specialist. Perform code reviews, ensure no secrets are leaked,
and only accept safe prompts. Use the provided tools to locate and fix issues.

Summary

  • Subagent hooks are shell scripts in 06-hooks/ that Claude Code executes at specific lifecycle events to enforce validation and security policies.
  • UserPromptSubmit hooks like validate-prompt.sh read from stdin and block dangerous operations by exiting with status 1.
  • PostToolUse:Write hooks like security-scan.sh receive file paths as arguments and scan for secrets while allowing operations to complete.
  • Hook declarations reside in subagent YAML front-matter under the hooks key, supporting event-specific matchers for granular control.
  • The system implements a fail-closed model where non-zero exit codes abort operations, ensuring unsafe prompts and unapproved deployments cannot proceed.

Frequently Asked Questions

How do I block specific dangerous commands in Claude Code subagents?

Create a UserPromptSubmit hook that reads from stdin and pattern-matches against forbidden strings. In 06-hooks/validate-prompt.sh, the script checks for patterns like rm -rf / and drop database, then exits with status 1 if detected. Claude Code will abort the prompt execution and display your error message to the user.

Can subagent hooks prevent accidental secret commits?

Yes. The security-scan.sh hook in 06-hooks/security-scan.sh demonstrates this by scanning written files for API keys, passwords, and private keys. While it emits warnings for findings, you can modify the script to exit with status 1 when secrets are detected, causing Claude Code to reject the file write operation entirely.

What happens if a hook script crashes or returns an error?

Claude Code treats any non-zero exit status as a blocking failure. If validate-prompt.sh crashes or explicitly exits with status 1, the associated operation (prompt submission or tool use) is immediately aborted. This fail-closed behavior ensures that validation failures or script errors cannot inadvertently permit dangerous actions.

Where should I store custom hook scripts for my subagents?

Store reusable hooks in the 06-hooks/ directory of your repository, as shown in the luongnv89/claude-howto project. Reference them from subagent front-matter using relative paths like ./06-hooks/validate-prompt.sh. For project-specific validation logic, create additional directories (e.g., ./scripts/) and reference those paths in your hook configurations.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →