#!/usr/bin/env bash set -euo pipefail # agent_worktree_launcher.sh # # Recreate the "background coding agent" pattern without depending on Cursor-specific # infrastructure: each async task gets a git worktree, a packet, a trace file, and a # merge/review gate. # # Usage: # tools/agent_workflows/agent_worktree_launcher.sh \ # --repo . \ # --task "Add billing CSV export" \ # --base main \ # --out generated/background_agents/demo \ # --mode dry-run # # Modes: # dry-run Create packet + commands only. Does not modify git worktrees. # create Create a branch/worktree and packet. Requires a clean git repo. MODE="dry-run" REPO="." TASK="" BASE="main" OUT="" AGENT_NAME="background-agent" BASE_URL="https://cn.crazyrouter.com/v1" usage() { sed -n '2,34p' "$0" | sed 's/^# \{0,1\}//' } slugify() { printf '%s' "$1" | tr '[:upper:]' '[:lower:]' | sed -E 's/[^a-z0-9]+/-/g; s/^-+|-+$//g; s/--+/-/g' } json_escape() { python3 -c 'import json,sys; print(json.dumps(sys.stdin.read()))' } while [[ $# -gt 0 ]]; do case "$1" in --mode) MODE="$2"; shift 2 ;; --repo) REPO="$2"; shift 2 ;; --task) TASK="$2"; shift 2 ;; --base) BASE="$2"; shift 2 ;; --out) OUT="$2"; shift 2 ;; --agent-name) AGENT_NAME="$2"; shift 2 ;; --base-url) BASE_URL="$2"; shift 2 ;; -h|--help) usage; exit 0 ;; *) echo "Unknown argument: $1" >&2; usage >&2; exit 2 ;; esac done if [[ -z "$TASK" ]]; then echo "--task is required" >&2 exit 2 fi SLUG="$(slugify "$TASK")" [[ -n "$SLUG" ]] || SLUG="background-task" [[ -n "$OUT" ]] || OUT="generated/background_agents/$SLUG" BRANCH="agent/$SLUG" WORKTREE_DIR="$OUT/worktrees/$SLUG" PACKET_DIR="$OUT/packets" TRACE="$OUT/trace.jsonl" mkdir -p "$PACKET_DIR" "$OUT/commands" "$OUT/review" : > "$TRACE" cat > "$OUT/README.md" < "$PACKET_DIR/01-background-agent.md" < "$OUT/commands/create-worktree.sh" < "$OUT/commands/review-before-merge.sh" < "$OUT/review/diff.patch" printf 'Saved diff to %s\n' "$OUT/review/diff.patch" EOF chmod +x "$OUT/commands/review-before-merge.sh" python3 - <&2 exit 1 fi "$OUT/commands/create-worktree.sh" elif [[ "$MODE" != "dry-run" ]]; then echo "Unknown --mode: $MODE" >&2 exit 2 fi printf '%s\n' "$OUT"