Files
wild-cloud/.ai/docs/automation.md

8.1 KiB

Automation Guide [Claude Code only]

This guide explains how automation works for Claude Code and how to extend it for your needs.

🔄 How Automation Works

The Hook System

Claude Code supports hooks that trigger actions based on events:

{
  "hooks": {
    "EventName": [
      {
        "matcher": "pattern",
        "hooks": [
          {
            "type": "command",
            "command": "script-to-run.sh"
          }
        ]
      }
    ]
  }
}

Current Automations

1. Automatic Quality Checks

  • Trigger: After any file edit/write
  • Script: .claude/tools/make-check.sh
  • What it does:
    • Finds the nearest Makefile
    • Runs make check
    • Reports results
    • Works with monorepos

2. Desktop Notifications

  • Trigger: Any Claude Code notification event
  • Script: .claude/tools/notify.sh
  • Features:
    • Native notifications on all platforms
    • Shows project context
    • Non-intrusive fallbacks

🛠️ The Make Check System

How It Works

The make-check.sh script is intelligent:

# 1. Detects what file was edited
/path/to/project/src/component.tsx

# 2. Looks for Makefile in order:
/path/to/project/src/Makefile      # Local directory
/path/to/project/Makefile          # Project root
/path/to/Makefile                  # Parent directories

# 3. Runs make check from appropriate location
cd /path/to/project && make check

Setting Up Your Makefile

Create a Makefile in your project root:

.PHONY: check
check: format lint typecheck test

.PHONY: format
format:
	@echo "Formatting code..."
	# Python
	black . || true
	isort . || true
	# JavaScript/TypeScript
	prettier --write . || true

.PHONY: lint
lint:
	@echo "Linting code..."
	# Python
	ruff check . || true
	# JavaScript/TypeScript
	eslint . --fix || true

.PHONY: typecheck
typecheck:
	@echo "Type checking..."
	# Python
	mypy . || true
	# TypeScript
	tsc --noEmit || true

.PHONY: test
test:
	@echo "Running tests..."
	# Python
	pytest || true
	# JavaScript
	npm test || true

Customizing Quality Checks

For different languages/frameworks:

Python Project:

check: format lint typecheck test

format:
	uv run black .
	uv run isort .

lint:
	uv run ruff check .

typecheck:
	uv run mypy .

test:
	uv run pytest

Node.js Project:

check: format lint typecheck test

format:
	npm run format

lint:
	npm run lint

typecheck:
	npm run typecheck

test:
	npm test

Go Project:

check: format lint test

format:
	go fmt ./...

lint:
	golangci-lint run

test:
	go test ./...

🔔 Notification System

How Notifications Work

  1. Event Occurs: Claude Code needs attention
  2. Hook Triggered: Notification hook activates
  3. Context Gathered: Project name, session ID extracted
  4. Platform Detection: Appropriate notification method chosen
  5. Notification Sent: Native notification appears

Customizing Notifications

Edit .claude/tools/notify.sh:

# Add custom notification categories
case "$MESSAGE" in
    *"error"*)
        URGENCY="critical"
        ICON="error.png"
        ;;
    *"success"*)
        URGENCY="normal"
        ICON="success.png"
        ;;
    *)
        URGENCY="low"
        ICON="info.png"
        ;;
esac

Adding Sound Alerts

macOS:

# Add to notify.sh
afplay /System/Library/Sounds/Glass.aiff

Linux:

# Add to notify.sh
paplay /usr/share/sounds/freedesktop/stereo/complete.oga

Windows/WSL:

# Add to PowerShell section
[System.Media.SystemSounds]::Exclamation.Play()

🎯 Creating Custom Automations

Example: Auto-Format on Save

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": ".claude/tools/auto-format.sh"
          }
        ]
      }
    ]
  }
}

Create .claude/tools/auto-format.sh:

#!/usr/bin/env bash
set -euo pipefail

# Read JSON input
JSON_INPUT=$(cat)

# Extract file path
FILE_PATH=$(echo "$JSON_INPUT" | grep -o '"file_path"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/.*"file_path"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/')

# Format based on file extension
case "$FILE_PATH" in
    *.py)
        black "$FILE_PATH"
        ;;
    *.js|*.jsx|*.ts|*.tsx)
        prettier --write "$FILE_PATH"
        ;;
    *.go)
        gofmt -w "$FILE_PATH"
        ;;
esac

Example: Git Auto-Commit

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": ".claude/tools/auto-commit.sh"
          }
        ]
      }
    ]
  }
}

Create .claude/tools/auto-commit.sh:

#!/usr/bin/env bash
# Auto-commit changes with descriptive messages

# ... parse JSON and get file path ...

# Generate commit message
COMMIT_MSG="Auto-update: $(basename "$FILE_PATH")"

# Stage and commit
git add "$FILE_PATH"
git commit -m "$COMMIT_MSG" --no-verify || true

Example: Test Runner

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write",
        "hooks": [
          {
            "type": "command",
            "command": ".claude/tools/run-tests.sh"
          }
        ]
      }
    ]
  }
}

🏗️ Advanced Automation Patterns

Conditional Execution

#!/usr/bin/env bash
# Only run on specific files

FILE_PATH=$(extract_file_path_from_json)

# Only check Python files
if [[ "$FILE_PATH" == *.py ]]; then
    python -m py_compile "$FILE_PATH"
fi

# Only test when source files change
if [[ "$FILE_PATH" == */src/* ]]; then
    npm test
fi

Parallel Execution

#!/usr/bin/env bash
# Run multiple checks in parallel

{
    echo "Starting parallel checks..."

    # Run all checks in background
    make format &
    PID1=$!

    make lint &
    PID2=$!

    make typecheck &
    PID3=$!

    # Wait for all to complete
    wait $PID1 $PID2 $PID3

    echo "All checks complete!"
}

Error Handling

#!/usr/bin/env bash
# Graceful error handling

set -euo pipefail

# Trap errors
trap 'echo "Check failed at line $LINENO"' ERR

# Run with error collection
ERRORS=0

make format || ((ERRORS++))
make lint || ((ERRORS++))
make test || ((ERRORS++))

if [ $ERRORS -gt 0 ]; then
    echo "⚠️  $ERRORS check(s) failed"
    exit 1
else
    echo "✅ All checks passed!"
fi

🔧 Debugging Automations

Enable Debug Logging

# Add to any automation script
DEBUG_LOG="/tmp/claude-automation-debug.log"
echo "[$(date)] Script started" >> "$DEBUG_LOG"
echo "Input: $JSON_INPUT" >> "$DEBUG_LOG"

Test Scripts Manually

# Test with sample input
echo '{"file_path": "/path/to/test.py", "success": true}' | .claude/tools/make-check.sh

Common Issues

  1. Script Not Executing

    • Check file permissions: chmod +x .claude/tools/*.sh
    • Verify path in settings.json
  2. No Output

    • Check if script outputs to stdout
    • Look for error logs in /tmp/
  3. Platform-Specific Issues

    • Test platform detection logic
    • Ensure fallbacks work

🚀 Best Practices

  1. Fast Execution: Keep automations under 5 seconds
  2. Fail Gracefully: Don't break Claude Code workflow
  3. User Feedback: Provide clear success/failure messages
  4. Cross-Platform: Test on Mac, Linux, Windows, WSL
  5. Configurable: Allow users to customize behavior

📊 Performance Optimization

Caching Results

# Cache expensive operations
CACHE_FILE="/tmp/claude-check-cache"
CACHE_AGE=$(($(date +%s) - $(stat -f %m "$CACHE_FILE" 2>/dev/null || echo 0)))

if [ $CACHE_AGE -lt 300 ]; then  # 5 minutes
    cat "$CACHE_FILE"
else
    make check | tee "$CACHE_FILE"
fi

Incremental Checks

# Only check changed files
CHANGED_FILES=$(git diff --name-only HEAD)
for file in $CHANGED_FILES; do
    case "$file" in
        *.py) pylint "$file" ;;
        *.js) eslint "$file" ;;
    esac
done