GC-301g · Module 3

Shell Script Integration

3 min read

Shell scripts are the natural home for Gemini CLI automation. Bash provides variable expansion, conditionals, loops, pipes, redirects, and error handling — everything you need to build multi-step AI workflows. The pattern: define a function that wraps gemini -p with error handling and output validation, then call that function from your workflow logic. Separation of the Gemini invocation from the workflow logic makes scripts testable, debuggable, and maintainable.

Production shell scripts need defensive coding. Set -euo pipefail at the top to fail on any error, undefined variable, or pipe failure. Trap EXIT to clean up temporary files. Quote all variable expansions to handle filenames with spaces. Log every Gemini invocation with timestamp, input size, exit code, and output size for post-mortem debugging. These are not optional niceties — they are the difference between a script that works on your machine and one that works in production.

#!/bin/bash
set -euo pipefail
trap 'rm -f "$TMPFILE"' EXIT

LOGFILE="gemini-automation.log"
TMPFILE=$(mktemp)

log() { echo "[$(date -Iseconds)] $*" >> "$LOGFILE"; }

gemini_safe() {
  local prompt="$1"
  local label="${2:-unnamed}"
  local start=$(date +%s)

  log "START $label (prompt: ${#prompt} chars)"

  if ! gemini -p "$prompt" --output-format json > "$TMPFILE" 2>/dev/null; then
    log "FAIL  $label (exit: $?)"
    return 1
  fi

  if ! jq empty "$TMPFILE" 2>/dev/null; then
    log "FAIL  $label (invalid JSON)"
    return 1
  fi

  local elapsed=$(( $(date +%s) - start ))
  log "OK    $label (${elapsed}s, $(wc -c < "$TMPFILE") bytes)"
  cat "$TMPFILE"
}

# Usage in a workflow
result=$(gemini_safe "Analyze the test coverage gaps in src/" "coverage-analysis")
if [ $? -eq 0 ]; then
  echo "$result" | jq '.response' > reports/coverage-gaps.md
  log "Report written to reports/coverage-gaps.md"
fi