Config Hooks
Config hooks allow you to define hook behavior directly in configuration files, running shell commands in response to tool events.
📸 SCREENSHOT: config-hooks-action.png
Config hooks blocking a dangerous command
Overview
Config hooks:
- Defined in JSON configuration
- Run shell commands
- No code required
- Project-specific customization
- Quick validation logic
Basic Configuration
{ "hooks": { "preToolUse": [ { "matcher": "Bash", "command": "./scripts/validate-command.sh" } ] }}Hook Events
PreToolUse
Runs before tool execution:
{ "hooks": { "preToolUse": [ { "matcher": "Bash", "command": "./scripts/validate.sh $TOOL_ARGS" } ] }}PostToolUse
Runs after tool execution:
{ "hooks": { "postToolUse": [ { "matcher": "Write(*)", "command": "npm run lint --fix $TOOL_FILE" } ] }}Notification
Runs on events:
{ "hooks": { "notification": [ { "type": "error", "command": "./scripts/notify-slack.sh" } ] }}Stop
Runs when session stops:
{ "hooks": { "stop": [ { "command": "./scripts/cleanup.sh" } ] }}SessionStart
Runs at session start:
{ "hooks": { "sessionStart": [ { "command": "./scripts/init-session.sh" } ] }}Matcher Patterns
Tool Name
{ "matcher": "Bash"}Glob Pattern
{ "matcher": "Write(src/**/*.ts)"}Multiple Tools
{ "matcher": "Bash|Write|Edit"}All Tools
{ "matcher": "*"}Argument Pattern
{ "matcher": "Bash(npm *)"}Environment Variables
Hooks receive context via environment variables:
| Variable | Description |
|---|---|
TOOL_NAME | Name of the tool |
TOOL_ARGS | JSON-encoded arguments |
TOOL_FILE | File path (for file tools) |
TOOL_COMMAND | Command (for Bash) |
TOOL_CONTENT | Content (for Write) |
SESSION_ID | Current session ID |
WORKING_DIR | Working directory |
Using Variables
#!/bin/bashARGS=$(echo "$TOOL_ARGS" | jq -r '.command')
if [[ "$ARGS" == *"rm -rf"* ]]; then echo "BLOCK: Dangerous command detected" exit 1fi
exit 0Exit Codes
Hook commands control behavior via exit codes:
| Exit Code | Action |
|---|---|
| 0 | Continue execution |
| 1 | Block execution |
| 2 | Skip with warning |
Example Script
#!/bin/bash
# Parse commandCMD="$TOOL_COMMAND"
# Check for dangerous patternsif [[ "$CMD" =~ (rm -rf|dd if=|mkfs) ]]; then echo "Blocked: Dangerous command pattern" exit 1fi
# Check for sudoif [[ "$CMD" == sudo* ]]; then echo "Warning: Sudo command" exit 2fi
# Allowexit 0Hook Output
Standard Output
Hook stdout is displayed to user:
#!/bin/bashecho "Validating command..."# validation logicecho "Command approved"exit 0Standard Error
Hook stderr is logged:
#!/bin/bashecho "Error: Invalid command" >&2exit 1JSON Response
Return structured data:
#!/bin/bashcat <<EOF{ "action": "block", "message": "Command not allowed", "reason": "Contains dangerous pattern"}EOFexit 1Conditional Hooks
By File Extension
{ "hooks": { "postToolUse": [ { "matcher": "Write(*.ts)", "command": "npx tsc --noEmit $TOOL_FILE" }, { "matcher": "Write(*.py)", "command": "python -m py_compile $TOOL_FILE" } ] }}By Directory
{ "hooks": { "preToolUse": [ { "matcher": "Write(src/secure/**)", "command": "./scripts/security-review.sh" } ] }}Multiple Hooks
Multiple hooks run in order:
{ "hooks": { "postToolUse": [ { "matcher": "Write(*.ts)", "command": "npx eslint --fix $TOOL_FILE" }, { "matcher": "Write(*.ts)", "command": "npx prettier --write $TOOL_FILE" }, { "matcher": "Write(*.ts)", "command": "npx tsc --noEmit $TOOL_FILE" } ] }}Timeout
Set Timeout
{ "hooks": { "postToolUse": [ { "matcher": "Write(*)", "command": "npm run test", "timeout": 30000 } ] }}Timeout in milliseconds (default: 10000).
Async Execution
Run in Background
{ "hooks": { "postToolUse": [ { "matcher": "*", "command": "./scripts/log-async.sh &", "async": true } ] }}Async hooks don’t block execution.
Examples
Lint on Write
{ "hooks": { "postToolUse": [ { "matcher": "Write(*.{ts,js,tsx,jsx})", "command": "npx eslint --fix $TOOL_FILE && npx prettier --write $TOOL_FILE" } ] }}Security Validation
{ "hooks": { "preToolUse": [ { "matcher": "Bash", "command": "./scripts/security-check.sh" }, { "matcher": "Write(.env*)", "command": "echo 'BLOCK: Cannot modify .env files' && exit 1" } ] }}Audit Logging
{ "hooks": { "postToolUse": [ { "matcher": "*", "command": "echo \"$(date -Iseconds) $TOOL_NAME\" >> .cyberstrike/audit.log", "async": true } ] }}Auto-Format
{ "hooks": { "postToolUse": [ { "matcher": "Write(*.py)", "command": "black $TOOL_FILE && isort $TOOL_FILE" }, { "matcher": "Write(*.go)", "command": "gofmt -w $TOOL_FILE" }, { "matcher": "Write(*.rs)", "command": "rustfmt $TOOL_FILE" } ] }}Troubleshooting
Hook Not Running
Check:
- Matcher pattern is correct
- Script is executable (
chmod +x) - Path is correct
Permission Denied
chmod +x ./scripts/validate.shTimeout
Increase timeout or optimize script:
{ "timeout": 60000}Caution
Long-running hooks can slow down Cyberstrike. Keep hooks fast or run them async.
Related Documentation
- Hooks Overview - Hook system basics
- Plugin Hooks - Programmatic hooks
- Configuration - Config file reference