Files
claude-foundations/best-practices/scripting.md
Paul O'Reilly e94417b896 Add best practices, hooks, memory files, and scripts from recent sessions
Includes: spec-driven and test-driven development best practices,
reproduce-before-fixing debugging workflow, require-plan-file hook,
find-project-root script, session logs, memory files for decisions/
gotchas/process-lessons, and updates to existing best practice topics.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 09:47:47 +13:00

2.5 KiB

Scripting Conventions

Structure

  • All scripts live in scripts/ and run from the repository root
  • Scripts should be idempotent and safe to re-run
  • Exit non-zero on failure so && chains work naturally

Verification Scripts

  • Automated checks confirming milestone or feature outcomes
  • Use colour output (green/red) for pass/fail indicators
  • Should be non-destructive and environment-resilient
  • Avoid needing sudo — test from the accessible side of a connection instead
  • Check for default/insecure credentials and print remediation instructions on failure
  • Use curl --resolve to bypass DNS/proxy layers when testing direct connectivity

Automation Triggers

If you run the same 3+ commands in sequence more than once, it should become a script. Look for:

  • Repeated command sequences in conversation history
  • Steps requiring careful ordering
  • Multi-step manual processes that are error-prone

Error Handling by Tool Purpose

Not all scripts need the same error handling strategy:

  • Destructive scripts (deploy, configure, delete) should use set -euo pipefail — fail fast on any error.
  • Reporting/read-only scripts (status dashboards, aggregation, monitoring) should start without set -e — complex data collection from multiple sources is hard to debug under errexit. Use explicit conditional checks instead.
  • The choice depends on the tool's purpose. A script that writes to production needs strict error handling. A script that reads from 10 sources and aggregates results needs resilience.

Dryrun Mode

Every script that modifies state should support --dryrun / -n:

  • Makes the script self-documenting about its side effects
  • Enables safe testing and review before execution
  • Enables test harnesses that verify output without executing changes
  • Dryrun output should show exactly what would happen, not a summary

Shell Gotchas

  • ((PASS++)) fails under set -e when PASS=0 — the expression evaluates to 0 (false), triggering errexit. Use PASS=$((PASS + 1)) instead.
  • set -e silently terminates complex pipelines and subshells with no output — makes debugging extremely difficult. Also kills command substitutions that capture non-zero exit codes (e.g., result=$(grep "pattern" file) exits if grep finds nothing).
  • grep interprets option-like strings (starting with -) as flags — use -- terminator before patterns or input that may start with dashes.
  • Always quote variables in conditionals and file paths
  • Use trap for cleanup of temp files and credentials