← back to Answer Cockpit
start.sh
58 lines
#!/usr/bin/env bash
# Answer Cockpit launcher — nohup node server.js on 127.0.0.1:9805 (hard-coded).
# bash start.sh start (refuses if 9805 is already bound by a different command)
# bash start.sh --stop stop the instance recorded in .running
# bash start.sh --status show listener
set -uo pipefail
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PORT=9805
mkdir -p "$DIR/tmp" "$DIR/data"
LOG="$DIR/tmp/server.log"
# The server must NEVER inherit a Claude session's bridge identity — its osascript
# children would otherwise trip the colordots.sh subagent rail / look like a subagent.
unset CLAUDE_CODE_CHILD_SESSION CLAUDE_PID CLAUDE_CODE_ENTRYPOINT 2>/dev/null || true
listener() { lsof -nP -iTCP:"$PORT" -sTCP:LISTEN 2>/dev/null | awk 'NR>1{print $2}' | head -1; }
case "${1:-}" in
--stop)
pid="$(listener)"; [ -z "$pid" ] && { echo "nothing on :$PORT"; exit 0; }
cmd="$(ps -o command= -p "$pid" 2>/dev/null)"
case "$cmd" in *answer-cockpit/server.js*|*"$DIR/server.js"*) kill "$pid" && echo "stopped pid $pid"; rm -f "$DIR/.running"; exit 0;;
*) echo "refusing: :$PORT is held by a different command (pid $pid): $cmd"; exit 1;; esac;;
--status)
pid="$(listener)"; [ -z "$pid" ] && { echo "not running"; exit 1; }
echo "pid $pid $(ps -o command= -p "$pid")"; exit 0;;
esac
pid="$(listener)"
if [ -n "$pid" ]; then
cmd="$(ps -o command= -p "$pid" 2>/dev/null)"
case "$cmd" in
*answer-cockpit/server.js*|*"$DIR/server.js"*) echo "already running (pid $pid): http://127.0.0.1:$PORT (admin / DW2024!)"; exit 0;;
*) echo "refusing to start: :$PORT is already bound by a different command (pid $pid): $cmd" >&2; exit 1;;
esac
fi
: > "$LOG"
nohup node "$DIR/server.js" >"$LOG" 2>&1 &
PID=$!
disown "$PID" 2>/dev/null || true
for _ in $(seq 1 50); do
grep -q 'COCKPIT_LISTENING port=' "$LOG" 2>/dev/null && break
kill -0 "$PID" 2>/dev/null || { echo "server failed to start:" >&2; cat "$LOG" >&2; exit 1; }
sleep 0.1
done
grep -q 'COCKPIT_LISTENING port=' "$LOG" || { echo "timed out waiting for COCKPIT_LISTENING" >&2; cat "$LOG" >&2; exit 1; }
printf '%s\t%s\t%s\t%s\n' "$(date +%FT%T)" "$PID" "$PORT" "$LOG" > "$DIR/.running"
cat <<EOF
✅ Answer Cockpit is live
URL: http://127.0.0.1:$PORT (admin / DW2024!)
PID: $PID (log: $LOG)
Stop: bash $DIR/start.sh --stop
cost: \$0 (local)
EOF