← back to Lifestyle Asset Intel
.yolo/run-tick.sh
49 lines
#!/bin/bash
# LAI yolo tick runner — fired by launchd every 30 minutes.
# Locks via flock so overlapping fires don't race on git.
set -u
PROJ="/Users/macstudio3/Projects/lifestyle-asset-intel"
LOCK="$PROJ/.yolo/.lock"
LOG="$PROJ/.yolo/yolo-loop.log"
PROMPT="$PROJ/.yolo/tick-prompt.md"
cd "$PROJ" || { echo "[$(date -u +%FT%TZ)] cwd FAIL" >> "$LOG"; exit 2; }
# Standing rule: NEVER use Anthropic API key — Claude CLI uses Max plan only.
unset ANTHROPIC_API_KEY ANTHROPIC_AUTH_TOKEN
# Single-fire lock — bail if a previous tick is still running.
# macOS has no flock, so we use a mkdir-as-lock pattern (atomic on POSIX).
LOCK_DIR="$PROJ/.yolo/.lock.d"
if ! mkdir "$LOCK_DIR" 2>/dev/null; then
# Stale lock recovery: if the dir is older than 12 minutes (max-turns 12 +
# margin), assume the previous tick is dead and steal the lock.
if [ "$(find "$LOCK_DIR" -maxdepth 0 -mmin +12 2>/dev/null | wc -l)" -gt 0 ]; then
echo "[$(date -u +%FT%TZ)] STALE lock → steal" >> "$LOG"
rmdir "$LOCK_DIR" 2>/dev/null
mkdir "$LOCK_DIR" || { echo "[$(date -u +%FT%TZ)] lock steal FAIL" >> "$LOG"; exit 0; }
else
echo "[$(date -u +%FT%TZ)] SKIP — previous tick still running" >> "$LOG"
exit 0
fi
fi
trap 'rmdir "$LOCK_DIR" 2>/dev/null' EXIT
START=$(date -u +%FT%TZ)
echo "[$START] tick start" >> "$LOG"
# Pipe the prompt to claude CLI, --print so it exits, --max-turns 25.
# Bumped from 12 → 25 after the 2026-05-10 08:14 fire blew its budget
# mid-implementation. 25 leaves room for (read+plan) + (do work) +
# (test+restart+commit) + (1-2 extra) without uncapped runaway.
/Users/macstudio3/.local/bin/claude --print --dangerously-skip-permissions --max-turns 25 < "$PROMPT" \
>> "$LOG" 2>&1
EXIT=$?
END=$(date -u +%FT%TZ)
echo "[$END] tick end exit=$EXIT" >> "$LOG"
echo "---" >> "$LOG"
exit "$EXIT"