← Back to SKILL.md1#!/usr/bin/env bash2# Start the OmniVoice FastAPI backend on 127.0.0.1:3900, detached, idempotent.3# Honors $OMNIVOICE_HOME (default ~/VoiceStudio).4#5# Exit codes:6# 0 success (already running, or freshly started + healthy within 60s)7# 2 $OMNIVOICE_HOME doesn't exist8# 3 port 3900 held but /health unresponsive (won't auto-kill — caller decides)9# 4 backend started but /health didn't respond within 60s10# 5 uvicorn process died during the wait11 12set -euo pipefail13 14HOME_DIR="${OMNIVOICE_HOME:-$HOME/VoiceStudio}"15URL="${OMNIVOICE_API_URL:-http://127.0.0.1:3900}"16LOG="$HOME_DIR/backend.log"17 18if [ ! -d "$HOME_DIR" ]; then19 echo "OMNIVOICE_HOME not found: $HOME_DIR" >&220 echo "See references/mcp-setup.md for install steps." >&221 exit 222fi23 24# Already up?25if curl -sf --max-time 2 "$URL/health" >/dev/null 2>&1; then26 echo "already running: $URL"27 curl -sf "$URL/health"; echo28 exit 029fi30 31# Port held by something else? Identify it before refusing.32BIND_PID="$(lsof -nP -iTCP:3900 -sTCP:LISTEN -t 2>/dev/null | head -1)"33if [ -n "$BIND_PID" ]; then34 BIND_CMD="$(ps -o command= -p "$BIND_PID" 2>/dev/null || echo "?")"35 echo "port 3900 held by PID $BIND_PID but /health not responding — investigate before starting" >&236 echo " bound process: $BIND_CMD" >&237 case "$BIND_CMD" in38 *uvicorn*main:app*)39 echo " → looks like a stale uvicorn from a previous run; consider scripts/stop-backend.sh" >&240 ;;41 *)42 echo " → unknown process holds the port; resolve before re-running this script" >&243 ;;44 esac45 exit 346fi47 48cd "$HOME_DIR"49nohup uv run uvicorn main:app --app-dir backend --host 127.0.0.1 --port 3900 \50 > "$LOG" 2>&1 &51PID=$!52echo "starting backend (PID $PID, log: $LOG)..."53 54# Wait up to 60s for /health, AND verify the child stays alive.55# A dead child means immediate bind failure (port grabbed in the TOCTOU window above)56# or an early crash — surface it instead of waiting the full timeout.57for i in $(seq 1 30); do58 sleep 259 if ! kill -0 "$PID" 2>/dev/null; then60 echo "✗ uvicorn (PID $PID) exited during startup — see $LOG" >&261 tail -20 "$LOG" >&2 || true62 exit 563 fi64 if curl -sf --max-time 2 "$URL/health" >/dev/null 2>&1; then65 curl -sf "$URL/health"; echo66 echo "ready after $((i*2))s"67 exit 068 fi69done70 71echo "backend did not respond on $URL/health within 60s — see $LOG" >&272exit 473