Skip to content

Instantly share code, notes, and snippets.

@kevinold
Created March 31, 2026 13:42
Show Gist options
  • Select an option

  • Save kevinold/3d433c9549b17e6bb01dab763069ddd5 to your computer and use it in GitHub Desktop.

Select an option

Save kevinold/3d433c9549b17e6bb01dab763069ddd5 to your computer and use it in GitHub Desktop.
overnight-ce.sh — Queue GitHub issues, run each through /slfg overnight. Review PRs over morning coffee.
#!/bin/bash
# overnight-ce.sh — Queue GitHub issues, run each through /slfg overnight.
# Review PRs over morning coffee. ☕
#
# Usage:
# ./overnight-ce.sh # all issues labeled "agent-ready"
# ./overnight-ce.sh --limit 5 # cap at 5
# ./overnight-ce.sh --label "priority" # different label
# ./overnight-ce.sh --dry-run # preview only
#
# Prerequisites:
# - gh CLI authenticated
# - claude with compound-engineering plugin installed
# - Inside your project git repo
set -euo pipefail
LABEL="${LABEL:-agent-ready}"
LIMIT="${LIMIT:-0}"
MAX_TURNS="${MAX_TURNS:-300}"
DRY_RUN=false
LOG_DIR="$HOME/.overnight-ce/logs"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
while [[ $# -gt 0 ]]; do
case $1 in
--label) LABEL="$2"; shift 2 ;;
--limit) LIMIT="$2"; shift 2 ;;
--turns) MAX_TURNS="$2"; shift 2 ;;
--dry-run) DRY_RUN=true; shift ;;
-h|--help) sed -n '2,/^$/s/^# //p' "$0"; exit 0 ;;
*) echo "Unknown option: $1"; exit 1 ;;
esac
done
mkdir -p "$LOG_DIR"
for cmd in gh claude jq git; do
command -v "$cmd" >/dev/null 2>&1 || { echo "❌ $cmd not found"; exit 1; }
done
git rev-parse --is-inside-work-tree >/dev/null 2>&1 || { echo "❌ Not in a git repo"; exit 1; }
STAGING_BRANCH="staging"
# ── Fetch issues ────────────────────────────────────────────────────────────
echo "🔍 Fetching issues with label '$LABEL'..."
LIMIT_FLAG=$( [[ "$LIMIT" -gt 0 ]] && echo "$LIMIT" || echo "100" )
ISSUES_JSON=$(gh issue list --label "$LABEL" --state open --json number,title,body --limit "$LIMIT_FLAG")
ISSUE_COUNT=$(echo "$ISSUES_JSON" | jq length)
if [[ "$ISSUE_COUNT" -eq 0 ]]; then
echo "✅ No issues with label '$LABEL'. Nothing to do!"
exit 0
fi
echo ""
echo "🌙 Overnight CE Run — $ISSUE_COUNT issues"
echo "$ISSUES_JSON" | jq -r '.[] | " #\(.number): \(.title)"'
echo ""
if $DRY_RUN; then
echo "🏜️ DRY RUN — nothing executed."
exit 0
fi
# ── Process each issue ──────────────────────────────────────────────────────
SUCCEEDED=0
FAILED=0
for row in $(echo "$ISSUES_JSON" | jq -r '.[] | @base64'); do
_jq() { echo "$row" | base64 --decode | jq -r "$1"; }
ISSUE_NUM=$(_jq '.number')
ISSUE_TITLE=$(_jq '.title')
ISSUE_BODY=$(_jq '.body')
LOG_FILE="$LOG_DIR/${TIMESTAMP}_issue-${ISSUE_NUM}.log"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "🚀 #${ISSUE_NUM}: ${ISSUE_TITLE}"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
git checkout "$STAGING_BRANCH" 2>/dev/null
git pull --ff-only origin "$STAGING_BRANCH" 2>/dev/null || true
PROMPT="Implement GitHub issue #${ISSUE_NUM}.
Title: ${ISSUE_TITLE}
${ISSUE_BODY}
Create your branch from this GitHub issue, then run /slfg to implement it end-to-end. The PR must reference \"Closes #${ISSUE_NUM}\".
You are running autonomously in a ralph-loop — when you have clarifying questions, ask them and then answer them yourself using your best judgment based on the codebase, existing patterns, and docs. Document any key assumptions in the PR description.
If you hit an unresolvable blocker, create a draft PR documenting it."
echo " ⏳ Running /slfg... (started $(date +%H:%M:%S))"
START_TIME=$(date +%s)
if echo "$PROMPT" | claude -p --dangerously-skip-permissions --max-turns "$MAX_TURNS" > "$LOG_FILE" 2>&1; then
DURATION=$(( ($(date +%s) - START_TIME) / 60 ))
echo " ✅ Done in ~${DURATION}min"
SUCCEEDED=$((SUCCEEDED + 1))
else
DURATION=$(( ($(date +%s) - START_TIME) / 60 ))
echo " ❌ Failed after ~${DURATION}min — tail -50 $LOG_FILE"
FAILED=$((FAILED + 1))
fi
echo ""
done
git checkout "$STAGING_BRANCH" 2>/dev/null || true
# ── Summary ─────────────────────────────────────────────────────────────────
echo ""
echo "☀️ Done — ✅ $SUCCEEDED ❌ $FAILED"
echo ""
echo "☕ Review PRs:"
echo " gh pr list --author @me --state open"
echo ""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment