Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Turn ideas into validated designs and specs through collaborative dialogue before any code is written
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
scripts/start-server.sh
1#!/usr/bin/env bash2# Start the brainstorm server and output connection info3# Usage: start-server.sh [--project-dir <path>] [--host <bind-host>] [--url-host <display-host>] [--foreground] [--background]4#5# Starts server on a random high port, outputs JSON with URL.6# Each session gets its own directory to avoid conflicts.7#8# Options:9# --project-dir <path> Store session files under <path>/.superpowers/brainstorm/10# instead of /tmp. Files persist after server stops.11# --host <bind-host> Host/interface to bind (default: 127.0.0.1).12# Use 0.0.0.0 in remote/containerized environments.13# --url-host <host> Hostname shown in returned URL JSON.14# --idle-timeout-minutes <n> Shut down after n minutes idle (default 240 = 4h).15# --open Auto-open the browser on the first screen (use only16# after the user approves the visual companion).17# --foreground Run server in the current terminal (no backgrounding).18# --background Force background mode (overrides Codex auto-foreground).1920SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"2122# Parse arguments23PROJECT_DIR=""24FOREGROUND="false"25FORCE_BACKGROUND="false"26BIND_HOST="127.0.0.1"27URL_HOST=""28IDLE_TIMEOUT_MINUTES=""29while [[ $# -gt 0 ]]; do30case "$1" in31--project-dir)32PROJECT_DIR="$2"33shift 234;;35--host)36BIND_HOST="$2"37shift 238;;39--url-host)40URL_HOST="$2"41shift 242;;43--idle-timeout-minutes)44IDLE_TIMEOUT_MINUTES="$2"45shift 246;;47--open)48export BRAINSTORM_OPEN=149shift50;;51--foreground|--no-daemon)52FOREGROUND="true"53shift54;;55--background|--daemon)56FORCE_BACKGROUND="true"57shift58;;59*)60echo "{\"error\": \"Unknown argument: $1\"}"61exit 162;;63esac64done6566if [[ -z "$URL_HOST" ]]; then67if [[ "$BIND_HOST" == "127.0.0.1" || "$BIND_HOST" == "localhost" ]]; then68URL_HOST="localhost"69else70URL_HOST="$BIND_HOST"71fi72fi7374if [[ -n "$IDLE_TIMEOUT_MINUTES" ]]; then75if ! [[ "$IDLE_TIMEOUT_MINUTES" =~ ^[0-9]+$ ]] || [[ "$IDLE_TIMEOUT_MINUTES" -lt 1 ]]; then76echo "{\"error\": \"--idle-timeout-minutes must be a positive integer\"}"77exit 178fi79export BRAINSTORM_IDLE_TIMEOUT_MS=$(( IDLE_TIMEOUT_MINUTES * 60 * 1000 ))80fi8182is_windows_like_shell() {83case "${OSTYPE:-}" in84msys*|cygwin*|mingw*) return 0 ;;85esac86if [[ -n "${MSYSTEM:-}" ]]; then87return 088fi89local uname_s90uname_s="$(uname -s 2>/dev/null || true)"91case "$uname_s" in92MSYS*|MINGW*|CYGWIN*) return 0 ;;93esac94return 195}9697# Some environments reap detached/background processes. Auto-foreground when detected.98if [[ -n "${CODEX_CI:-}" && "$FOREGROUND" != "true" && "$FORCE_BACKGROUND" != "true" ]]; then99FOREGROUND="true"100fi101102# Windows/Git Bash reaps nohup background processes. Auto-foreground when detected.103if [[ "$FOREGROUND" != "true" && "$FORCE_BACKGROUND" != "true" ]]; then104if is_windows_like_shell; then105FOREGROUND="true"106fi107fi108109# Session files (server.log, server-info, .last-token) embed the session key —110# keep everything this script and the server create owner-only.111umask 077112113# Generate unique session directory114SESSION_ID="$$-$(date +%s)"115116if [[ -n "$PROJECT_DIR" ]]; then117SESSION_DIR="${PROJECT_DIR}/.superpowers/brainstorm/${SESSION_ID}"118# Persist the bound port and key per project so a restart reuses them and an119# already-open browser tab reconnects to the same URL with a valid cookie.120export BRAINSTORM_PORT_FILE="${PROJECT_DIR}/.superpowers/brainstorm/.last-port"121export BRAINSTORM_TOKEN_FILE="${PROJECT_DIR}/.superpowers/brainstorm/.last-token"122else123SESSION_DIR="/tmp/brainstorm-${SESSION_ID}"124fi125126STATE_DIR="${SESSION_DIR}/state"127PID_FILE="${STATE_DIR}/server.pid"128LOG_FILE="${STATE_DIR}/server.log"129SERVER_ID_FILE="${STATE_DIR}/server-instance-id"130131# Create fresh session directory with content and state peers132mkdir -p "${SESSION_DIR}/content" "$STATE_DIR"133134SERVER_ID=""135if [[ -r /dev/urandom ]]; then136SERVER_ID="$(od -An -N24 -tx1 /dev/urandom 2>/dev/null | tr -d ' \n' || true)"137fi138if ! [[ "$SERVER_ID" =~ ^[A-Za-z0-9_-]{32,64}$ ]]; then139SERVER_ID="$(printf '%08x%08x%08x%08x' "$$" "$(date +%s)" "${RANDOM:-0}" "${RANDOM:-0}")"140fi141printf '%s\n' "$SERVER_ID" > "$SERVER_ID_FILE"142chmod 600 "$SERVER_ID_FILE" 2>/dev/null || true143144# Kill any existing server145if [[ -f "$PID_FILE" ]]; then146old_pid=$(cat "$PID_FILE")147kill "$old_pid" 2>/dev/null148rm -f "$PID_FILE"149fi150151cd "$SCRIPT_DIR" || exit 1152153# Resolve the harness PID (grandparent of this script).154# $PPID is the ephemeral shell the harness spawned to run us — it dies155# when this script exits. The harness itself is $PPID's parent.156OWNER_PID="$(ps -o ppid= -p "$PPID" 2>/dev/null | tr -d ' ')"157if [[ -z "$OWNER_PID" || "$OWNER_PID" == "1" ]]; then158OWNER_PID="$PPID"159fi160161# Windows/MSYS2: Node.js cannot see POSIX PIDs from the MSYS2 namespace.162# Passing a PID node cannot verify causes server to log owner-pid-invalid163# and self-terminate at the 60-second lifecycle check. Clear it so the164# watchdog is disabled and the idle timeout becomes the only shutdown trigger.165if is_windows_like_shell; then166OWNER_PID=""167fi168169# Foreground mode for environments that reap detached/background processes.170if [[ "$FOREGROUND" == "true" ]]; then171env BRAINSTORM_DIR="$SESSION_DIR" BRAINSTORM_HOST="$BIND_HOST" BRAINSTORM_URL_HOST="$URL_HOST" BRAINSTORM_OWNER_PID="$OWNER_PID" node server.cjs "--brainstorm-server-id=$SERVER_ID" &172SERVER_PID=$!173echo "$SERVER_PID" > "$PID_FILE"174wait "$SERVER_PID"175exit $?176fi177178# Start server, capturing output to log file179# Use nohup to survive shell exit; disown to remove from job table180nohup env BRAINSTORM_DIR="$SESSION_DIR" BRAINSTORM_HOST="$BIND_HOST" BRAINSTORM_URL_HOST="$URL_HOST" BRAINSTORM_OWNER_PID="$OWNER_PID" node server.cjs "--brainstorm-server-id=$SERVER_ID" > "$LOG_FILE" 2>&1 &181SERVER_PID=$!182disown "$SERVER_PID" 2>/dev/null183echo "$SERVER_PID" > "$PID_FILE"184185# Wait for server-started message (check log file)186for _ in {1..50}; do187if grep -q "server-started" "$LOG_FILE" 2>/dev/null; then188# Verify server is still alive after a short window (catches process reapers)189alive="true"190for _ in {1..20}; do191if ! kill -0 "$SERVER_PID" 2>/dev/null; then192alive="false"193break194fi195sleep 0.1196done197if [[ "$alive" != "true" ]]; then198echo "{\"error\": \"Server started but was killed. Retry in a persistent terminal with: $SCRIPT_DIR/start-server.sh${PROJECT_DIR:+ --project-dir $PROJECT_DIR} --host $BIND_HOST --url-host $URL_HOST --foreground\"}"199exit 1200fi201grep "server-started" "$LOG_FILE" | head -1202exit 0203fi204sleep 0.1205done206207# Timeout - server didn't start208echo '{"error": "Server failed to start within 5 seconds"}'209exit 1210