Skip to content

Hooks Overview

conclaude integrates with Claude Code through lifecycle hooks—strategic intervention points that let you enforce rules, run validations, and maintain control over your codebase.

When Claude Code runs in a directory with conclaude configured, it invokes conclaude at specific moments:

  1. Claude Code fires a hook event (e.g., “PreToolUse”)
  2. conclaude receives the event as a JSON payload via stdin
  3. conclaude evaluates rules and runs commands based on your configuration
  4. conclaude returns a result (allow, block, or error)
  5. Claude Code proceeds based on the result

When: Before Claude uses any tool (Write, Bash, Read, etc.)

Purpose: Gate tool execution based on your rules.

Common Use Cases:

  • Block file creation at project root
  • Protect critical files from modification
  • Validate tool inputs before execution

Configuration:

preToolUse:
preventRootAdditions: true
uneditableFiles:
- "Cargo.lock"
- ".env*"
- "target/**"

Example Scenario:

Claude wants to create debug.log in your project root. With preventRootAdditions: true, conclaude blocks the operation. Claude adapts and creates logs/debug.log instead.


When: After a tool operation completes

Purpose: Observe and log tool results.

Common Use Cases:

  • Audit logging of all changes
  • Performance monitoring
  • Post-processing validation

Note: PostToolUse is currently used for logging and observation. It does not block operations.


When: Claude finishes a task and the session is about to end

Purpose: Final validation gate before session completion.

This is the most important hook for enforcing code quality.

Configuration:

stop:
commands:
- run: cargo fmt --check
message: "Check code formatting"
- run: cargo clippy -- -D warnings
message: "Run clippy lints"
- run: cargo test
message: "Run test suite"

How It Works:

  1. Claude completes a task
  2. conclaude runs each command in order
  3. If any command fails, Claude sees the error output
  4. Claude can fix the issues
  5. Session only completes when all commands pass

Infinite Mode:

For long coding sessions, enable continuous validation:

stop:
commands:
- run: cargo check
- run: cargo test
infinite: true
infiniteMessage: "Monitoring active - validating after each change"

With infinite mode, validation runs after every task completion, not just at session end.

Workflow Guardrails: PR Verification

Beyond code quality checks, Stop hooks can enforce workflow policies. This example ensures all changes are committed and a pull request exists before the session ends:

stop:
commands:
# Ensure no uncommitted changes
- run: |
if [ -n "$(git status --porcelain)" ]; then
echo "Error: Uncommitted changes detected"
git status --short
exit 1
fi
message: "Check for uncommitted changes"
# Ensure no untracked files
- run: |
UNTRACKED=$(git ls-files --others --exclude-standard)
if [ -n "$UNTRACKED" ]; then
echo "Error: Untracked files detected:"
echo "$UNTRACKED"
exit 1
fi
message: "Check for untracked files"
# Verify PR exists for current branch
- run: |
BRANCH=$(git branch --show-current)
if [ "$BRANCH" = "main" ] || [ "$BRANCH" = "master" ]; then
exit 0 # Skip PR check on main/master
fi
PR_COUNT=$(gh pr list --head "$BRANCH" --json number --jq 'length')
if [ "$PR_COUNT" -eq 0 ]; then
echo "Error: No open PR found for branch '$BRANCH'"
echo "Create a PR with: gh pr create"
exit 1
fi
message: "Verify pull request exists"

Prerequisites:

  • Git must be installed and the directory must be a Git repository
  • GitHub CLI (gh) must be installed and authenticated for PR verification
  • Run gh auth login to authenticate if needed

How It Works:

  1. Uncommitted changes check: Uses git status --porcelain to detect any staged or unstaged modifications
  2. Untracked files check: Uses git ls-files --others --exclude-standard to find files not yet added to Git
  3. PR verification: Queries GitHub for open PRs from the current branch using gh pr list

When Checks Fail:

  • If uncommitted changes exist, Claude sees the list of modified files and can commit them
  • If untracked files exist, Claude sees the file list and can add them to Git
  • If no PR exists, Claude sees instructions to create one with gh pr create
  • The session only completes when all checks pass

Combining with Code Quality:

stop:
commands:
# Code quality first
- run: cargo fmt --check
message: "Check formatting"
- run: cargo test
message: "Run tests"
# Then workflow checks
- run: test -z "$(git status --porcelain)"
message: "No uncommitted changes"
- run: |
BRANCH=$(git branch --show-current)
[ "$BRANCH" = "main" ] || gh pr list --head "$BRANCH" --json number --jq 'length' | grep -q '[1-9]'
message: "PR exists for branch"

This pattern ensures code quality AND workflow discipline before session completion.


When: A new Claude Code session begins

Purpose: Initialize session-specific resources.

Use Cases:

  • Set up session logging
  • Initialize monitoring
  • Prepare workspace

When: User submits input to Claude

Purpose: Process user prompts and inject context based on prompt content.

Use Cases:

  • Context injection based on prompt patterns
  • Automatically load project-specific guidelines
  • Audit logging of user inputs

Configuration:

userPromptSubmit:
contextRules:
- pattern: "sidebar|navigation"
prompt: |
Read @.claude/contexts/sidebar.md before making changes.
- pattern: "auth|login|authentication"
prompt: |
Review authentication patterns in @.claude/contexts/auth.md
caseInsensitive: true

How It Works:

Context injection allows you to automatically prepend relevant guidelines, documentation, or reminders to Claude’s system prompt based on what you’re asking about. When your prompt matches a configured pattern, conclaude injects the associated context before Claude processes your request.

Example Scenario:

You ask: “How do I update the sidebar component?”

With the configuration above:

  1. Pattern sidebar|navigation matches “sidebar”
  2. conclaude prepends the context from .claude/contexts/sidebar.md
  3. Claude receives your prompt with additional context about sidebar guidelines
  4. Claude responds with knowledge of your project-specific sidebar patterns

Pattern Matching:

  • Supports regular expressions for flexible matching
  • Multiple rules can match and inject context
  • Case-sensitive by default (use caseInsensitive: true to override)
  • File references using @ syntax are expanded to file contents

See Also: UserPromptSubmit Configuration Reference


When: A Claude subagent (coder, tester, stuck, etc.) begins work

Purpose: Track subagent initialization.

Payload Fields:

  • agent_id — Identifier for the subagent (e.g., “coder”, “tester”)
  • subagent_type — Category of subagent (e.g., “implementation”, “testing”)
  • agent_transcript_path — Path to subagent’s transcript file

Configuration:

notifications:
enabled: true
hooks:
- "SubagentStart"

Use Cases:

  • Log when specific agents start
  • Initialize agent-specific resources
  • Collect timing metrics

When: A Claude subagent completes its work

Purpose: Handle subagent completion.

Payload Fields:

  • agent_id — Identifier for the completed subagent
  • agent_transcript_path — Path to subagent’s transcript file

Configuration:

notifications:
enabled: true
hooks:
- "SubagentStop"

Use Cases:

  • Log subagent completion
  • Cleanup operations
  • Performance metrics

When: System notifications are sent

Purpose: Handle and filter system alerts.


When: Before transcript compaction

Purpose: Prepare transcripts before archival.


When: A tool requests permission

Purpose: Handle permission flows.


When: A session terminates

Purpose: Cleanup and final logging.


stop:
commands:
- run: cargo check
message: "Type check"
preToolUse:
preventRootAdditions: false
uneditableFiles:
- "Cargo.toml"
stop:
commands:
- run: cargo fmt --check
message: "Formatting must pass"
- run: cargo clippy -- -D warnings
message: "No clippy warnings allowed"
- run: cargo test
message: "All tests must pass"
- run: cargo build --release
message: "Release build must succeed"
preToolUse:
preventRootAdditions: true
uneditableFiles:
- "Cargo.toml"
- "Cargo.lock"
- ".env*"
- ".github/workflows/**"
stop:
commands:
- run: npm run lint
message: "ESLint check"
- run: npm run typecheck
message: "TypeScript check"
- run: npm test
message: "Jest tests"
preToolUse:
preventRootAdditions: true
uneditableFiles:
- "package-lock.json"
- ".env*"
- "node_modules/**"
stop:
commands:
- run: cargo check --quiet
- run: cargo test --quiet
infinite: true
infiniteMessage: "Validating after each change..."
preToolUse:
preventRootAdditions: false

Automatically inject relevant context when working on specific features:

userPromptSubmit:
contextRules:
# React component guidelines
- pattern: "component|react|jsx|tsx"
prompt: |
Component guidelines: @.claude/contexts/components.md
- Use TypeScript
- Add PropTypes
- Include unit tests
caseInsensitive: true
# API development standards
- pattern: "api|endpoint|route"
prompt: |
API standards: @.claude/contexts/api.md
- Use proper HTTP status codes
- Implement error handling
- Add request validation
# Security reminders
- pattern: "auth|login|password|security"
prompt: |
SECURITY CHECKLIST:
- Never commit secrets
- Use environment variables
- Review: @.claude/contexts/security.md
caseInsensitive: true
# Optional: Get notified when context is injected
notifications:
enabled: true
hooks:
- "UserPromptSubmit"
showSuccess: true

How This Helps:

When you ask “How do I add a new React component?”, conclaude automatically reminds Claude about your component guidelines before it responds. You don’t need to repeat instructions manually.

Get system notifications when hooks execute:

notifications:
enabled: true
hooks:
- "Stop"
- "PreToolUse"

Use ["*"] for all hooks:

notifications:
enabled: true
hooks: ["*"]

Commands executed by hooks have access to context variables:

VariableDescription
CONCLAUDE_SESSION_IDUnique session identifier
CONCLAUDE_TRANSCRIPT_PATHPath to session transcript
CONCLAUDE_CWDCurrent working directory
CONCLAUDE_HOOK_EVENTName of executing hook
CONCLAUDE_CONFIG_DIRDirectory containing config

For subagent hooks:

VariableDescription
CONCLAUDE_AGENT_IDRaw agent identifier (e.g., “adb0a8b”)
CONCLAUDE_AGENT_NAMESemantic agent name (e.g., “coder”, “tester”, “stuck”). Falls back to agent ID if extraction fails. (SubagentStop only)
CONCLAUDE_SUBAGENT_TYPESubagent type (e.g., “implementation”) (SubagentStart only)
CONCLAUDE_AGENT_TRANSCRIPT_PATHPath to subagent transcript