Skip to content

Script Automation

You have a Claude Code workflow that works every time: pipe in the git diff, ask for a changelog entry, format it, append to CHANGELOG.md. You run it before every release. But it takes five manual steps and you forget the exact prompt every time. Scripting turns this from a manual workflow into a single command.

  • Print mode patterns for scripting Claude Code into pipelines
  • Pre-commit hooks that run Claude Code before every commit
  • Cron jobs for scheduled codebase maintenance
  • Error handling and retry patterns for production scripts

The -p flag makes Claude Code scriptable. It takes a prompt, processes it, prints the result, and exits:

Terminal window
# Basic usage
claude -p "What does this project do?"
# With piped input
cat error.log | claude -p "What caused this error?"
# With output format
claude -p "List all TODO comments in the codebase" --output-format json
# With budget limits
claude -p "Refactor src/utils.ts" --max-turns 5 --max-budget-usd 1.00
FormatUse CaseExample
text (default)Human-readable output--output-format text
jsonScript consumption--output-format json
stream-jsonReal-time streaming--output-format stream-json

Run Claude Code as a pre-commit check. This catches issues before code reaches the repository:

.git/hooks/pre-commit
#!/bin/bash
# Quick review of staged changes
STAGED_DIFF=$(git diff --cached --no-color)
if [ -z "$STAGED_DIFF" ]; then
exit 0
fi
RESULT=$(echo "$STAGED_DIFF" | claude -p "Review this diff for critical issues only: \
security vulnerabilities, obvious bugs, and broken error handling. \
If you find CRITICAL issues, output 'BLOCK: [reason]'. \
If the code looks safe, output 'PASS'." \
--max-turns 3 --output-format text 2>&1)
if echo "$RESULT" | grep -q "BLOCK:"; then
echo "Pre-commit review found issues:"
echo "$RESULT"
exit 1
fi
exit 0
#!/bin/bash
# cron-health-check.sh -- Run daily at 6 AM
# Crontab: 0 6 * * * /path/to/cron-health-check.sh
cd /path/to/project
REPORT=$(claude -p "Run a health check on this project: \
1. Check for TypeScript errors: npx tsc --noEmit \
2. Run the linter: npm run lint \
3. Check for outdated dependencies: npm outdated \
4. Summarize findings in a brief report" \
--max-turns 10 \
--dangerously-skip-permissions \
--output-format text 2>&1)
# Send via notification (adjust for your team's channel)
echo "$REPORT" | mail -s "Daily Code Health: $(date +%Y-%m-%d)" team@company.com
weekly-audit.sh
#!/bin/bash
cd /path/to/project
claude -p "Run npm audit and analyze the results. \
For each vulnerability: \
1. Assess if it affects us (check if the vulnerable code path is used) \
2. Check if an upgrade is available \
3. Note any breaking changes in the upgrade \
Output a prioritized action list." \
--max-turns 8 \
--dangerously-skip-permissions \
--output-format text > /tmp/audit-report.txt
# Only notify if there are actionable findings
if grep -q "CRITICAL\|HIGH" /tmp/audit-report.txt; then
cat /tmp/audit-report.txt # Send to your notification system
fi
#!/bin/bash
set -euo pipefail
MAX_RETRIES=3
RETRY_DELAY=5
run_claude() {
local prompt="$1"
local retries=0
while [ $retries -lt $MAX_RETRIES ]; do
result=$(claude -p "$prompt" --max-turns 5 --output-format text 2>&1)
exit_code=$?
if [ $exit_code -eq 0 ]; then
echo "$result"
return 0
fi
retries=$((retries + 1))
echo "Attempt $retries failed. Retrying in ${RETRY_DELAY}s..." >&2
sleep $RETRY_DELAY
done
echo "Failed after $MAX_RETRIES attempts" >&2
return 1
}
# Usage
run_claude "Analyze the test coverage report and identify untested code paths"

Script hangs waiting for permissions: In print mode, Claude Code stops when it needs permission for a dangerous operation. Use --dangerously-skip-permissions for trusted environments, or --allowedTools to pre-approve specific operations.

Output format inconsistency: Claude Code’s text output may vary between runs. When parsing output programmatically, use --output-format json and parse with jq. Do not rely on specific text formatting.

Budget exceeded mid-task: The --max-budget-usd flag stops execution when the budget is reached. For critical tasks, set a generous budget and monitor costs via /cost or OpenTelemetry.

Cron job environment differs from shell: Cron jobs run with a minimal environment. Ensure your PATH includes node and claude, and that all required environment variables (API keys, proxy settings) are set in the crontab.