PreToolUse
Runs before Claude executes any tool. Perfect for validation, security checks, or preparing the environment.
Automation is where Claude Code transforms from a helpful assistant into a force multiplier. This lesson explores how to create self-running workflows, automate repetitive tasks, and build intelligent pipelines that handle complex operations with minimal human intervention.
Scenario: Your team maintains 50 microservices. A security update requires changing authentication middleware across all services, updating tests, and creating pull requests. Doing this manually would take days. With Claude Code automation, it’s a single afternoon.
Claude Code’s automation capabilities extend far beyond simple scripts. It can orchestrate complex, multi-step operations across your entire codebase, handle conditional logic, and even self-correct when issues arise.
Hooks are the foundation of Claude Code automation. They’re shell commands that execute automatically at specific points in Claude’s lifecycle, turning suggestions into enforced patterns.
Claude Code provides several hook points:
PreToolUse
Runs before Claude executes any tool. Perfect for validation, security checks, or preparing the environment.
PostToolUse
Executes after a tool completes successfully. Ideal for formatting, testing, or cleanup operations.
Notification
Triggers when Claude needs your attention. Customize alerts for different platforms or urgency levels.
Stop
Fires when Claude finishes responding. Great for final checks, summaries, or triggering follow-up actions.
Let’s create a hook that automatically formats code after every edit:
Create the hooks configuration
{ "hooks": [ { "matcher": "Edit|Write", "hooks": [ { "type": "command", "command": "prettier --write \"$CLAUDE_FILE_PATHS\"" } ] } ]}
Add language-specific formatting
{ "matcher": "Edit", "hooks": [ { "type": "command", "command": "if [[ \"$CLAUDE_FILE_PATHS\" =~ \\.py$ ]]; then black \"$CLAUDE_FILE_PATHS\"; fi" }, { "type": "command", "command": "if [[ \"$CLAUDE_FILE_PATHS\" =~ \\.go$ ]]; then gofmt -w \"$CLAUDE_FILE_PATHS\"; fi" } ]}
Test the hook
> Create a new Python function for calculating fibonacci numbers# Claude creates the file, then Black formats it automatically
Validation Hooks: Prevent dangerous operations
{ "matcher": "Edit", "hooks": [ { "type": "command", "command": "if [[ \"$CLAUDE_FILE_PATHS\" =~ production|secret ]]; then echo 'BLOCKED: Cannot edit sensitive files' && exit 1; fi" } ]}
Testing Hooks: Run tests after changes
{ "matcher": "Edit", "hooks": [ { "type": "command", "command": "if [[ \"$CLAUDE_FILE_PATHS\" =~ \\.spec\\.|test\\. ]]; then npm test -- \"$CLAUDE_FILE_PATHS\"; fi" } ]}
Compliance Hooks: Enforce standards
{ "matcher": "Edit", "hooks": [ { "type": "command", "command": "/path/to/security-scanner.sh \"$CLAUDE_FILE_PATHS\" || (echo 'Security check failed' && exit 1)" } ]}
Headless mode (claude -p
) enables programmatic use of Claude Code in scripts, CI/CD pipelines, and automated workflows.
# Simple one-off taskclaude -p "Update all copyright headers to 2025"
# With specific tools allowedclaude -p "Fix all ESLint errors" --allowedTools Edit,Bash
# JSON output for parsingclaude -p "List all TODO comments" --output-format json
Batch Processing Pattern: Handle multiple files or tasks
#!/bin/bash# Generate list of components to migrateclaude -p "List all class components that need conversion to hooks" \ --output-format json > components.json
# Process each componentwhile read -r file; do claude -p "Convert $file to use React hooks" \ --allowedTools Edit \ --max-turns 10done < <(jq -r '.files[]' components.json)
# Verify migrationsclaude -p "Run tests for all migrated components"
Pipeline Integration: Feed Claude’s output to other tools
# Generate API documentation and feed to static site generatorclaude -p "Generate OpenAPI spec from our FastAPI routes" --json | \ npx swagger-to-markdown | \ hugo new content/api/reference.md
# Process multiple tasks in parallelTASKS=( "service-auth:Update authentication to use JWT" "service-user:Add rate limiting to API endpoints" "service-payment:Implement webhook retry logic")
for task in "${TASKS[@]}"; do IFS=':' read -r service description <<< "$task" ( cd "../$service" claude -p "$description" \ --allowedTools Edit,Write,Bash \ --max-retries 3 ) &done
wait # Wait for all parallel tasks
# Only proceed if conditions are metif claude -p "Are there any failing tests?" --json | jq -e '.failing_tests > 0'; then claude -p "Fix the failing tests" --allowedTools Edit,Bash
if claude -p "Do tests pass now?" --json | jq -e '.all_passing'; then git add -A git commit -m "fix: resolved failing tests (automated)" fifi
Create reusable automation patterns with custom slash commands:
Migrate the database schema from version $ARGUMENTS. Follow these steps:
1. Create a new migration file with timestamp2. Analyze differences between current and target schema3. Generate forward migration SQL4. Generate rollback SQL5. Create migration test6. Update migration documentation
Ensure:- Zero downtime deployment compatibility- Data integrity preservation- Performance optimization for large tables
Usage: /migrate-database v2.3.0
Build a library of automation commands:
.claude/commands/├── security/│ ├── audit.md # Security audit workflow│ ├── update-deps.md # Dependency updates│ └── rotate-keys.md # Key rotation process├── deployment/│ ├── release.md # Release automation│ ├── rollback.md # Rollback procedures│ └── hotfix.md # Emergency fix workflow└── maintenance/ ├── cleanup.md # Code cleanup tasks ├── optimize.md # Performance optimization └── refactor.md # Refactoring patterns
Automated PR Reviews
name: Claude Code Reviewon: pull_request: types: [opened, synchronize]
jobs: review: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: anthropics/claude-code-action@v1 with: api-key: ${{ secrets.ANTHROPIC_API_KEY }} prompt: | Review this PR for: - Security vulnerabilities - Performance issues - Missing tests - Code quality problems
Only comment on significant issues.
name: Auto-fix Issueson: issues: types: [labeled]
jobs: auto-fix: if: github.event.label.name == 'auto-fix' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4
- name: Create fix branch run: | git checkout -b fix/issue-${{ github.event.issue.number }}
- name: Claude fix run: | claude -p "Fix issue: ${{ github.event.issue.title }}
Description: ${{ github.event.issue.body }}
Create a complete fix with tests" \ --allowedTools Edit,Write,Bash \ --dangerously-skip-permissions
- name: Create PR uses: peter-evans/create-pull-request@v5 with: title: "fix: ${{ github.event.issue.title }}" body: "Fixes #${{ github.event.issue.number }}"
Leverage multiple Claude instances for complex workflows:
#!/bin/bash# Parallel code review system
review_branch() { local branch=$1 local reviewer_focus=$2
git worktree add "../review-$branch" "$branch" cd "../review-$branch"
claude -p "Review this branch focusing on: $reviewer_focus Provide detailed feedback and suggestions" \ --output-format json > "review-$reviewer_focus.json"}
# Run specialized reviews in parallelreview_branch "feature/auth" "security" &review_branch "feature/auth" "performance" &review_branch "feature/auth" "test coverage" &
wait
# Aggregate reviewsclaude -p "Summarize these code reviews and create a unified report" \ --attach review-*.json
Set up the automation script
#!/bin/bash# Check for outdated dependenciesOUTDATED=$(npm outdated --json)
if [ -n "$OUTDATED" ]; then # Create update branch git checkout -b chore/dependency-updates-$(date +%Y%m%d)
# Update dependencies intelligently claude -p "Update NPM dependencies based on this outdated list: $OUTDATED
For each update: 1. Check breaking changes 2. Update code if needed 3. Run tests 4. Update documentation" \ --allowedTools Edit,Bash
# If successful, create PR if npm test; then gh pr create --title "chore: update dependencies" \ --body "Automated dependency updates with necessary code changes" fifi
Schedule via cron or CI
on: schedule: - cron: '0 0 * * 1' # Weekly on Monday
# Refactor authentication across 100+ filesclaude -p "Create a refactoring plan to migrate from cookies to JWT tokens" \ --output-format json > refactor-plan.json
# Execute plan with progress trackingtotal=$(jq '.steps | length' refactor-plan.json)current=0
jq -r '.steps[] | @json' refactor-plan.json | while read -r step; do current=$((current + 1)) echo "[$current/$total] Processing..."
task=$(echo "$step" | jq -r '.task') files=$(echo "$step" | jq -r '.files[]')
claude -p "$task" \ --attach $files \ --allowedTools Edit,Write \ --max-turns 20
# Checkpoint after each major step git add -A git commit -m "refactor: $task (step $current/$total)"done
# Robust automation with error handlingrun_with_retry() { local max_attempts=3 local attempt=1
while [ $attempt -le $max_attempts ]; do if "$@"; then return 0 fi
echo "Attempt $attempt failed. Retrying..." attempt=$((attempt + 1)) sleep 5 done
return 1}
# Use with Clauderun_with_retry claude -p "Complex refactoring task" --max-turns 30
Track your automation effectiveness:
# Track automation metricsclaude -p "Analyze our git history and calculate:- Time saved through automated commits- Error rate in automated vs manual changes- Test coverage improvements from automated test generation- Documentation completeness scores
Output as a markdown report" > automation-metrics.md
Automation with Claude Code is a journey from simple scripts to sophisticated workflows. Start with basic hooks, experiment with headless mode for repetitive tasks, then gradually build more complex automation patterns.
The key is to identify repetitive, error-prone tasks in your workflow and systematically automate them. Each automation you create becomes a building block for more complex workflows.
Ready to handle large-scale code transformations? Continue to Refactoring to learn how Claude Code can help you safely restructure entire codebases.