Skip to Content

Hooks

Hooks are automated checks that run at specific points during a Copilot session. They provide guardrails β€” scanning for secrets, blocking dangerous commands, detecting PII, and enforcing governance policies.

Available Events

EventWhen It FiresRecommended Use
SessionStartSession beginsLoad context, check config, verify prerequisites
UserPromptSubmitUser sends a messagePII detection, governance audit
PreToolUseBefore tool executionBlock dangerous commands ⚠️
PostToolUseAfter tool executionValidate tool output
PreCompactBefore context compactionSave critical context
SubagentStartSub-agent spawnsTrack agent delegation
SubagentStopSub-agent completesValidate sub-agent output
StopSession endsScan for leaked secrets, audit logging
⚠️

Never Use PreToolUse in Production

PreToolUse hooks spawn a process for every tool call, adding ~5 seconds of delay each time. Use SessionStart for upfront validation instead. Only use PreToolUse during development or security audits where the delay is acceptable.

Folder Structure

Every hook lives in its own folder under hooks/:

hooks/ fai-secrets-scanner/ hooks.json # Required β€” event configuration scan-secrets.sh # Required β€” the script to execute README.md # Recommended β€” documentation

hooks.json Configuration

hooks/fai-secrets-scanner/hooks.json
{ "version": 1, "hooks": { "SessionStart": [ { "type": "command", "bash": "./hooks/fai-secrets-scanner/scan-secrets.sh", "cwd": ".", "env": { "HOOK_MODE": "warn" }, "timeoutSec": 10 } ] } }

Configuration Fields

FieldRequiredDescription
versionβœ…Always 1
hooks.<event>βœ…Array of commands for this event
typeβœ…Always "command"
bashβœ…Path to the script
cwdβœ…Working directory (usually ".")
envNoEnvironment variables passed to script
timeoutSecβœ…Max seconds before kill (5–60)

Writing Hook Scripts

Hook scripts receive input on stdin and communicate results via exit codes:

  • Exit 0 β€” check passed, allow action to proceed
  • Exit 1 β€” check failed, block the action
hooks/fai-secrets-scanner/scan-secrets.sh
#!/usr/bin/env bash set -euo pipefail MODE="${HOOK_MODE:-warn}" FINDINGS=0 # Scan for common secret patterns PATTERNS=( "AKIA[0-9A-Z]{16}" # AWS access key "sk-[a-zA-Z0-9]{48}" # OpenAI API key "ghp_[a-zA-Z0-9]{36}" # GitHub PAT "password\s*=\s*['\"][^'\"]+['\"]" # Hardcoded passwords ) for pattern in "${PATTERNS[@]}"; do if grep -rqE "$pattern" --include="*.py" --include="*.js" --include="*.ts" .; then echo "🚨 Secret pattern detected: $pattern" FINDINGS=$((FINDINGS + 1)) fi done if [ "$FINDINGS" -gt 0 ]; then if [ "$MODE" = "block" ]; then echo "❌ Blocked: $FINDINGS secret(s) found" exit 1 fi echo "⚠️ Warning: $FINDINGS potential secret(s) found" fi echo "βœ… Secrets scan passed" exit 0

Existing FrootAI Hooks

HookEventPurpose
fai-secrets-scannerStop25+ credential patterns
fai-tool-guardianPreToolUseBlock destructive commands
fai-governance-auditUserPromptSubmitData governance
fai-license-checkerSessionStartOSS license compliance
fai-waf-complianceStopWAF pillar validation
fai-session-loggerSessionStart + StopAudit trail
fai-cost-trackerPreToolUseToken/cost monitoring
fai-pii-redactorUserPromptSubmitPII removal
fai-token-budget-enforcerPreToolUseToken limit enforcement
fai-output-validatorStopOutput quality checking
πŸ’‘

Recommended: SessionStart

SessionStart is the safest and fastest event. Use it for prerequisite checks, configuration loading, and initial security scans. It fires only once per session with no performance penalty.

Wiring Hooks into Plays

Reference hooks in fai-manifest.json:

{ "primitives": { "hooks": [ "../../hooks/fai-secrets-scanner/", "../../hooks/fai-tool-guardian/" ] } }

Or in a plugin’s plugin.json:

{ "hooks": ["../../hooks/fai-secrets-scanner/"] }

Best Practices

  1. Always set a timeout β€” hooks should never hang the session (10s max for PreToolUse)
  2. Support both warn and block modes β€” let users choose via HOOK_MODE env var
  3. Read from stdin β€” that’s how tool call data arrives for PreToolUse hooks
  4. Exit 0 for pass, exit 1 for block β€” standard convention
  5. Log clearly β€” use emoji prefixes (🚨 ⚠️ βœ…) for quick scanning
  6. Prefer SessionStart β€” run expensive checks once, not per tool call
  7. Test with edge cases β€” empty input, malformed JSON, unicode

See Also

Last updated on