← back to Rentv
ops/buildloop-cycle.sh
30 lines
#!/bin/bash
# RENTV autonomous build loop — one /yoloforever cycle, headless + SANDBOXED.
# Installed via launchd (com.steve.rentv-buildloop) so it survives restarts.
#
# SAFETY MODEL: this runs `claude -p` with a RESTRICTED allowedTools set — it can
# read/edit/write files and run git/node/npm, but it has NO tool to run deploy.sh,
# curl, or any paid API. So it CANNOT deploy to prod or spend money; gated work is
# structurally forced to a draft in ~/.claude/yolo-queue/pending-approval/ for Steve.
# Stop it: launchctl bootout gui/$(id -u)/com.steve.rentv-buildloop
set -euo pipefail
cd "$HOME/Projects/rentv" || exit 1
mkdir -p "$HOME/Projects/rentv/ops"
LOG="$HOME/Projects/rentv/ops/buildloop.log"
# Trim the log if it grows past ~5MB.
[ -f "$LOG" ] && [ "$(wc -c <"$LOG")" -gt 5000000 ] && tail -c 2000000 "$LOG" > "$LOG.tmp" && mv "$LOG.tmp" "$LOG"
PROMPT='/yoloforever continue — autonomous build loop for the RENTV project (~/Projects/rentv, live at rentv.agentabrams.com; surfaces: pr-intelligence CRM, Content Studio, Deal Desk, /audience, /blog + front-end). STANDING OBJECTIVE: harden/extend rentv. THIS cycle pick ONE highest-value SAFE reversible item and finish it: a real bug fix, UI/UX polish, enforce Steve standing rules (admin cards show created date+time; every data point hrefs deeper; grids have sort+density; lists have adjustable/expandable columns), CA/AZ data completeness, Content Studio / Deal Desk / Boomer improvements, dedup/quality. VERIFY any claimed defect by reproducing before fixing (drop phantoms). Do reversible work directly (edit + node --check) and git commit each success (author steve@designerwallcoverings.com). YOU HAVE NO DEPLOY OR SPEND TOOL — for any gated action (prod deploy, DNS, ElevenLabs/Gemini/HeyGen spend, send-to-list, publish, remote push) WRITE a memo to ~/.claude/yolo-queue/pending-approval/ with APPROVE/REVISE/BLOCK; never attempt to run it. If nothing safe+valuable remains, write a short ops/buildloop.log note and exit. One increment per run; do not loop internally.'
# `claude` is a shell function in interactive shells; launchd runs non-interactive, so pin the real binary.
CLAUDE_BIN="$HOME/.local/bin/claude"; [ -x "$CLAUDE_BIN" ] || CLAUDE_BIN="$(command -v claude)"
{
echo "==================== $(date '+%Y-%m-%d %H:%M:%S') cycle start ===================="
"$CLAUDE_BIN" -p "$PROMPT" \
--model sonnet \
--allowedTools "Read" "Edit" "Write" "Grep" "Glob" "Bash(git:*)" "Bash(node:*)" "Bash(npm:*)" \
2>&1 || echo "[cycle exited non-zero: $?]"
echo "==================== $(date '+%Y-%m-%d %H:%M:%S') cycle end ===================="
} >> "$LOG" 2>&1