refactor: add pipefail to error handling flags

Changed 65 agent scripts from `set -e` to `set -eo pipefail` to ensure
errors in piped commands are properly caught. This prevents silent
failures when commands like `curl | bash` fail in the middle.

Files updated across all cloud providers:
- aws-lightsail: 10 scripts
- digitalocean: 3 scripts
- e2b: 10 scripts
- gcp: 10 scripts
- hetzner: 3 scripts
- lambda: 10 scripts
- linode: 3 scripts
- modal: 10 scripts
- sprite: 3 scripts
- vultr: 3 scripts

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Sprite 2026-02-08 02:34:45 +00:00
parent e0dfc9672a
commit cabdbc37ba
113 changed files with 1756 additions and 1596 deletions

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=aws-lightsail/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/aws-lightsail/lib/common.sh)"
fi
@ -21,15 +21,15 @@ ensure_ssh_key
# 3. Get instance name and create server
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 4. Wait for SSH and cloud-init
verify_server_connectivity "$LIGHTSAIL_SERVER_IP"
wait_for_cloud_init "$LIGHTSAIL_SERVER_IP"
verify_server_connectivity "${LIGHTSAIL_SERVER_IP}"
wait_for_cloud_init "${LIGHTSAIL_SERVER_IP}"
# 5. Install Aider
log_warn "Installing Aider..."
run_server "$LIGHTSAIL_SERVER_IP" "pip install aider-chat 2>/dev/null || pip3 install aider-chat"
run_server "${LIGHTSAIL_SERVER_IP}" "pip install aider-chat 2>/dev/null || pip3 install aider-chat"
log_info "Aider installed"
# 6. Get OpenRouter API key
@ -51,23 +51,23 @@ MODEL_ID="${MODEL_ID:-openrouter/auto}"
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
EOF
upload_file "$LIGHTSAIL_SERVER_IP" "$ENV_TEMP" "/tmp/env_config"
run_server "$LIGHTSAIL_SERVER_IP" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
upload_file "${LIGHTSAIL_SERVER_IP}" "${ENV_TEMP}" "/tmp/env_config"
run_server "${LIGHTSAIL_SERVER_IP}" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "${ENV_TEMP}"
echo ""
log_info "Lightsail instance setup completed successfully!"
log_info "Instance: $SERVER_NAME (IP: $LIGHTSAIL_SERVER_IP)"
log_info "Instance: ${SERVER_NAME} (IP: ${LIGHTSAIL_SERVER_IP})"
echo ""
# 9. Start Aider interactively
log_warn "Starting Aider..."
sleep 1
clear
interactive_session "$LIGHTSAIL_SERVER_IP" "source ~/.zshrc && aider --model openrouter/${MODEL_ID}"
interactive_session "${LIGHTSAIL_SERVER_IP}" "source ~/.zshrc && aider --model openrouter/${MODEL_ID}"

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=aws-lightsail/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/aws-lightsail/lib/common.sh)"
fi
@ -21,15 +21,15 @@ ensure_ssh_key
# 3. Get instance name and create server
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 4. Wait for SSH and cloud-init
verify_server_connectivity "$LIGHTSAIL_SERVER_IP"
wait_for_cloud_init "$LIGHTSAIL_SERVER_IP"
verify_server_connectivity "${LIGHTSAIL_SERVER_IP}"
wait_for_cloud_init "${LIGHTSAIL_SERVER_IP}"
# 5. Install Amazon Q CLI
log_warn "Installing Amazon Q CLI..."
run_server "$LIGHTSAIL_SERVER_IP" "curl -fsSL https://desktop-release.q.us-east-1.amazonaws.com/latest/amazon-q-cli-install.sh | bash"
run_server "${LIGHTSAIL_SERVER_IP}" "curl -fsSL https://desktop-release.q.us-east-1.amazonaws.com/latest/amazon-q-cli-install.sh | bash"
log_info "Amazon Q CLI installed"
# 6. Get OpenRouter API key
@ -44,7 +44,7 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
@ -52,17 +52,17 @@ export OPENAI_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_BASE_URL="https://openrouter.ai/api/v1"
EOF
upload_file "$LIGHTSAIL_SERVER_IP" "$ENV_TEMP" "/tmp/env_config"
run_server "$LIGHTSAIL_SERVER_IP" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
upload_file "${LIGHTSAIL_SERVER_IP}" "${ENV_TEMP}" "/tmp/env_config"
run_server "${LIGHTSAIL_SERVER_IP}" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "${ENV_TEMP}"
echo ""
log_info "Lightsail instance setup completed successfully!"
log_info "Instance: $SERVER_NAME (IP: $LIGHTSAIL_SERVER_IP)"
log_info "Instance: ${SERVER_NAME} (IP: ${LIGHTSAIL_SERVER_IP})"
echo ""
# 8. Start Amazon Q interactively
log_warn "Starting Amazon Q..."
sleep 1
clear
interactive_session "$LIGHTSAIL_SERVER_IP" "source ~/.zshrc && q chat"
interactive_session "${LIGHTSAIL_SERVER_IP}" "source ~/.zshrc && q chat"

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=aws-lightsail/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/aws-lightsail/lib/common.sh)"
fi
@ -21,17 +21,17 @@ ensure_ssh_key
# 3. Get instance name and create server
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 4. Wait for SSH and cloud-init
verify_server_connectivity "$LIGHTSAIL_SERVER_IP"
wait_for_cloud_init "$LIGHTSAIL_SERVER_IP"
verify_server_connectivity "${LIGHTSAIL_SERVER_IP}"
wait_for_cloud_init "${LIGHTSAIL_SERVER_IP}"
# 5. Verify Claude Code is installed (fallback to manual install)
log_warn "Verifying Claude Code installation..."
if ! run_server "$LIGHTSAIL_SERVER_IP" "command -v claude" >/dev/null 2>&1; then
if ! run_server "${LIGHTSAIL_SERVER_IP}" "command -v claude" >/dev/null 2>&1; then
log_warn "Claude Code not found, installing manually..."
run_server "$LIGHTSAIL_SERVER_IP" "curl -fsSL https://claude.ai/install.sh | bash"
run_server "${LIGHTSAIL_SERVER_IP}" "curl -fsSL https://claude.ai/install.sh | bash"
fi
log_info "Claude Code is installed"
@ -47,7 +47,7 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
@ -58,22 +58,22 @@ export CLAUDE_CODE_SKIP_ONBOARDING="1"
export CLAUDE_CODE_ENABLE_TELEMETRY="0"
EOF
upload_file "$LIGHTSAIL_SERVER_IP" "$ENV_TEMP" "/tmp/env_config"
run_server "$LIGHTSAIL_SERVER_IP" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
upload_file "${LIGHTSAIL_SERVER_IP}" "${ENV_TEMP}" "/tmp/env_config"
run_server "${LIGHTSAIL_SERVER_IP}" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "${ENV_TEMP}"
# 8. Configure Claude Code settings
setup_claude_code_config "$OPENROUTER_API_KEY" \
"upload_file $LIGHTSAIL_SERVER_IP" \
"run_server $LIGHTSAIL_SERVER_IP"
setup_claude_code_config "${OPENROUTER_API_KEY}" \
"upload_file ${LIGHTSAIL_SERVER_IP}" \
"run_server ${LIGHTSAIL_SERVER_IP}"
echo ""
log_info "Lightsail instance setup completed successfully!"
log_info "Instance: $SERVER_NAME (IP: $LIGHTSAIL_SERVER_IP)"
log_info "Instance: ${SERVER_NAME} (IP: ${LIGHTSAIL_SERVER_IP})"
echo ""
# 9. Start Claude Code interactively
log_warn "Starting Claude Code..."
sleep 1
clear
interactive_session "$LIGHTSAIL_SERVER_IP" "source ~/.zshrc && claude"
interactive_session "${LIGHTSAIL_SERVER_IP}" "source ~/.zshrc && claude"

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=aws-lightsail/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/aws-lightsail/lib/common.sh)"
fi
@ -21,15 +21,15 @@ ensure_ssh_key
# 3. Get instance name and create server
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 4. Wait for SSH and cloud-init
verify_server_connectivity "$LIGHTSAIL_SERVER_IP"
wait_for_cloud_init "$LIGHTSAIL_SERVER_IP"
verify_server_connectivity "${LIGHTSAIL_SERVER_IP}"
wait_for_cloud_init "${LIGHTSAIL_SERVER_IP}"
# 5. Install Cline
log_warn "Installing Cline..."
run_server "$LIGHTSAIL_SERVER_IP" "npm install -g cline"
run_server "${LIGHTSAIL_SERVER_IP}" "npm install -g cline"
log_info "Cline installed"
# 6. Get OpenRouter API key
@ -44,7 +44,7 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
@ -52,17 +52,17 @@ export OPENAI_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_BASE_URL="https://openrouter.ai/api/v1"
EOF
upload_file "$LIGHTSAIL_SERVER_IP" "$ENV_TEMP" "/tmp/env_config"
run_server "$LIGHTSAIL_SERVER_IP" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
upload_file "${LIGHTSAIL_SERVER_IP}" "${ENV_TEMP}" "/tmp/env_config"
run_server "${LIGHTSAIL_SERVER_IP}" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "${ENV_TEMP}"
echo ""
log_info "Lightsail instance setup completed successfully!"
log_info "Instance: $SERVER_NAME (IP: $LIGHTSAIL_SERVER_IP)"
log_info "Instance: ${SERVER_NAME} (IP: ${LIGHTSAIL_SERVER_IP})"
echo ""
# 8. Start Cline interactively
log_warn "Starting Cline..."
sleep 1
clear
interactive_session "$LIGHTSAIL_SERVER_IP" "source ~/.zshrc && cline"
interactive_session "${LIGHTSAIL_SERVER_IP}" "source ~/.zshrc && cline"

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=aws-lightsail/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/aws-lightsail/lib/common.sh)"
fi
@ -21,15 +21,15 @@ ensure_ssh_key
# 3. Get instance name and create server
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 4. Wait for SSH and cloud-init
verify_server_connectivity "$LIGHTSAIL_SERVER_IP"
wait_for_cloud_init "$LIGHTSAIL_SERVER_IP"
verify_server_connectivity "${LIGHTSAIL_SERVER_IP}"
wait_for_cloud_init "${LIGHTSAIL_SERVER_IP}"
# 5. Install Codex CLI
log_warn "Installing Codex CLI..."
run_server "$LIGHTSAIL_SERVER_IP" "npm install -g @openai/codex"
run_server "${LIGHTSAIL_SERVER_IP}" "npm install -g @openai/codex"
log_info "Codex CLI installed"
# 6. Get OpenRouter API key
@ -44,7 +44,7 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
@ -52,17 +52,17 @@ export OPENAI_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_BASE_URL="https://openrouter.ai/api/v1"
EOF
upload_file "$LIGHTSAIL_SERVER_IP" "$ENV_TEMP" "/tmp/env_config"
run_server "$LIGHTSAIL_SERVER_IP" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
upload_file "${LIGHTSAIL_SERVER_IP}" "${ENV_TEMP}" "/tmp/env_config"
run_server "${LIGHTSAIL_SERVER_IP}" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "${ENV_TEMP}"
echo ""
log_info "Lightsail instance setup completed successfully!"
log_info "Instance: $SERVER_NAME (IP: $LIGHTSAIL_SERVER_IP)"
log_info "Instance: ${SERVER_NAME} (IP: ${LIGHTSAIL_SERVER_IP})"
echo ""
# 8. Start Codex interactively
log_warn "Starting Codex..."
sleep 1
clear
interactive_session "$LIGHTSAIL_SERVER_IP" "source ~/.zshrc && codex"
interactive_session "${LIGHTSAIL_SERVER_IP}" "source ~/.zshrc && codex"

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=aws-lightsail/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/aws-lightsail/lib/common.sh)"
fi
@ -21,15 +21,15 @@ ensure_ssh_key
# 3. Get instance name and create server
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 4. Wait for SSH and cloud-init
verify_server_connectivity "$LIGHTSAIL_SERVER_IP"
wait_for_cloud_init "$LIGHTSAIL_SERVER_IP"
verify_server_connectivity "${LIGHTSAIL_SERVER_IP}"
wait_for_cloud_init "${LIGHTSAIL_SERVER_IP}"
# 5. Install Gemini CLI
log_warn "Installing Gemini CLI..."
run_server "$LIGHTSAIL_SERVER_IP" "npm install -g @google/gemini-cli"
run_server "${LIGHTSAIL_SERVER_IP}" "npm install -g @google/gemini-cli"
log_info "Gemini CLI installed"
# 6. Get OpenRouter API key
@ -44,7 +44,7 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
@ -53,17 +53,17 @@ export OPENAI_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_BASE_URL="https://openrouter.ai/api/v1"
EOF
upload_file "$LIGHTSAIL_SERVER_IP" "$ENV_TEMP" "/tmp/env_config"
run_server "$LIGHTSAIL_SERVER_IP" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
upload_file "${LIGHTSAIL_SERVER_IP}" "${ENV_TEMP}" "/tmp/env_config"
run_server "${LIGHTSAIL_SERVER_IP}" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "${ENV_TEMP}"
echo ""
log_info "Lightsail instance setup completed successfully!"
log_info "Instance: $SERVER_NAME (IP: $LIGHTSAIL_SERVER_IP)"
log_info "Instance: ${SERVER_NAME} (IP: ${LIGHTSAIL_SERVER_IP})"
echo ""
# 8. Start Gemini interactively
log_warn "Starting Gemini..."
sleep 1
clear
interactive_session "$LIGHTSAIL_SERVER_IP" "source ~/.zshrc && gemini"
interactive_session "${LIGHTSAIL_SERVER_IP}" "source ~/.zshrc && gemini"

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=aws-lightsail/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/aws-lightsail/lib/common.sh)"
fi
@ -21,15 +21,15 @@ ensure_ssh_key
# 3. Get instance name and create server
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 4. Wait for SSH and cloud-init
verify_server_connectivity "$LIGHTSAIL_SERVER_IP"
wait_for_cloud_init "$LIGHTSAIL_SERVER_IP"
verify_server_connectivity "${LIGHTSAIL_SERVER_IP}"
wait_for_cloud_init "${LIGHTSAIL_SERVER_IP}"
# 5. Install Goose
log_warn "Installing Goose..."
run_server "$LIGHTSAIL_SERVER_IP" "CONFIGURE=false curl -fsSL https://github.com/block/goose/releases/latest/download/download_cli.sh | bash"
run_server "${LIGHTSAIL_SERVER_IP}" "CONFIGURE=false curl -fsSL https://github.com/block/goose/releases/latest/download/download_cli.sh | bash"
log_info "Goose installed"
# 6. Get OpenRouter API key
@ -44,24 +44,24 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export GOOSE_PROVIDER=openrouter
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
EOF
upload_file "$LIGHTSAIL_SERVER_IP" "$ENV_TEMP" "/tmp/env_config"
run_server "$LIGHTSAIL_SERVER_IP" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
upload_file "${LIGHTSAIL_SERVER_IP}" "${ENV_TEMP}" "/tmp/env_config"
run_server "${LIGHTSAIL_SERVER_IP}" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "${ENV_TEMP}"
echo ""
log_info "Lightsail instance setup completed successfully!"
log_info "Instance: $SERVER_NAME (IP: $LIGHTSAIL_SERVER_IP)"
log_info "Instance: ${SERVER_NAME} (IP: ${LIGHTSAIL_SERVER_IP})"
echo ""
# 8. Start Goose interactively
log_warn "Starting Goose..."
sleep 1
clear
interactive_session "$LIGHTSAIL_SERVER_IP" "source ~/.zshrc && goose"
interactive_session "${LIGHTSAIL_SERVER_IP}" "source ~/.zshrc && goose"

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=aws-lightsail/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/aws-lightsail/lib/common.sh)"
fi
@ -21,15 +21,15 @@ ensure_ssh_key
# 3. Get instance name and create server
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 4. Wait for SSH and cloud-init
verify_server_connectivity "$LIGHTSAIL_SERVER_IP"
wait_for_cloud_init "$LIGHTSAIL_SERVER_IP"
verify_server_connectivity "${LIGHTSAIL_SERVER_IP}"
wait_for_cloud_init "${LIGHTSAIL_SERVER_IP}"
# 5. Install Open Interpreter
log_warn "Installing Open Interpreter..."
run_server "$LIGHTSAIL_SERVER_IP" "pip install open-interpreter 2>/dev/null || pip3 install open-interpreter"
run_server "${LIGHTSAIL_SERVER_IP}" "pip install open-interpreter 2>/dev/null || pip3 install open-interpreter"
log_info "Open Interpreter installed"
# 6. Get OpenRouter API key
@ -44,7 +44,7 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
@ -52,17 +52,17 @@ export OPENAI_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_BASE_URL="https://openrouter.ai/api/v1"
EOF
upload_file "$LIGHTSAIL_SERVER_IP" "$ENV_TEMP" "/tmp/env_config"
run_server "$LIGHTSAIL_SERVER_IP" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
upload_file "${LIGHTSAIL_SERVER_IP}" "${ENV_TEMP}" "/tmp/env_config"
run_server "${LIGHTSAIL_SERVER_IP}" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "${ENV_TEMP}"
echo ""
log_info "Lightsail instance setup completed successfully!"
log_info "Instance: $SERVER_NAME (IP: $LIGHTSAIL_SERVER_IP)"
log_info "Instance: ${SERVER_NAME} (IP: ${LIGHTSAIL_SERVER_IP})"
echo ""
# 8. Start Open Interpreter interactively
log_warn "Starting Open Interpreter..."
sleep 1
clear
interactive_session "$LIGHTSAIL_SERVER_IP" "source ~/.zshrc && interpreter"
interactive_session "${LIGHTSAIL_SERVER_IP}" "source ~/.zshrc && interpreter"

View file

@ -77,8 +77,8 @@ su - ubuntu -c 'curl -fsSL https://bun.sh/install | bash'
# Install Claude Code
su - ubuntu -c 'curl -fsSL https://claude.ai/install.sh | bash'
# Configure PATH
echo 'export PATH="$HOME/.claude/local/bin:$HOME/.bun/bin:$PATH"' >> /home/ubuntu/.bashrc
echo 'export PATH="$HOME/.claude/local/bin:$HOME/.bun/bin:$PATH"' >> /home/ubuntu/.zshrc
echo 'export PATH="${HOME}/.claude/local/bin:${HOME}/.bun/bin:${PATH}"' >> /home/ubuntu/.bashrc
echo 'export PATH="${HOME}/.claude/local/bin:${HOME}/.bun/bin:${PATH}"' >> /home/ubuntu/.zshrc
touch /home/ubuntu/.cloud-init-complete
chown ubuntu:ubuntu /home/ubuntu/.cloud-init-complete
CLOUD_INIT_EOF

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=aws-lightsail/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/aws-lightsail/lib/common.sh)"
fi
@ -21,18 +21,18 @@ ensure_ssh_key
# 3. Get instance name and create server
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 4. Wait for SSH and cloud-init
verify_server_connectivity "$LIGHTSAIL_SERVER_IP"
wait_for_cloud_init "$LIGHTSAIL_SERVER_IP"
verify_server_connectivity "${LIGHTSAIL_SERVER_IP}"
wait_for_cloud_init "${LIGHTSAIL_SERVER_IP}"
# 5. Install Node.js deps and clone nanoclaw
log_warn "Installing tsx..."
run_server "$LIGHTSAIL_SERVER_IP" "source ~/.bashrc && bun install -g tsx"
run_server "${LIGHTSAIL_SERVER_IP}" "source ~/.bashrc && bun install -g tsx"
log_warn "Cloning and building nanoclaw..."
run_server "$LIGHTSAIL_SERVER_IP" "git clone https://github.com/gavrielc/nanoclaw.git ~/nanoclaw && cd ~/nanoclaw && npm install && npm run build"
run_server "${LIGHTSAIL_SERVER_IP}" "git clone https://github.com/gavrielc/nanoclaw.git ~/nanoclaw && cd ~/nanoclaw && npm install && npm run build"
log_info "NanoClaw installed"
# 6. Get OpenRouter API key
@ -47,7 +47,7 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
@ -55,28 +55,28 @@ export ANTHROPIC_API_KEY="${OPENROUTER_API_KEY}"
export ANTHROPIC_BASE_URL="https://openrouter.ai/api"
EOF
upload_file "$LIGHTSAIL_SERVER_IP" "$ENV_TEMP" "/tmp/env_config"
run_server "$LIGHTSAIL_SERVER_IP" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
upload_file "${LIGHTSAIL_SERVER_IP}" "${ENV_TEMP}" "/tmp/env_config"
run_server "${LIGHTSAIL_SERVER_IP}" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "${ENV_TEMP}"
# 8. Create nanoclaw .env file
log_warn "Configuring nanoclaw..."
DOTENV_TEMP=$(mktemp)
cat > "$DOTENV_TEMP" << EOF
cat > "${DOTENV_TEMP}" << EOF
ANTHROPIC_API_KEY=${OPENROUTER_API_KEY}
EOF
upload_file "$LIGHTSAIL_SERVER_IP" "$DOTENV_TEMP" "/home/ubuntu/nanoclaw/.env"
rm "$DOTENV_TEMP"
upload_file "${LIGHTSAIL_SERVER_IP}" "${DOTENV_TEMP}" "/home/ubuntu/nanoclaw/.env"
rm "${DOTENV_TEMP}"
echo ""
log_info "Lightsail instance setup completed successfully!"
log_info "Instance: $SERVER_NAME (IP: $LIGHTSAIL_SERVER_IP)"
log_info "Instance: ${SERVER_NAME} (IP: ${LIGHTSAIL_SERVER_IP})"
echo ""
# 9. Start nanoclaw
log_warn "Starting nanoclaw..."
log_warn "You will need to scan a WhatsApp QR code to authenticate."
echo ""
interactive_session "$LIGHTSAIL_SERVER_IP" "cd ~/nanoclaw && source ~/.zshrc && npm run dev"
interactive_session "${LIGHTSAIL_SERVER_IP}" "cd ~/nanoclaw && source ~/.zshrc && npm run dev"

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=aws-lightsail/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/aws-lightsail/lib/common.sh)"
fi
@ -21,15 +21,15 @@ ensure_ssh_key
# 3. Get instance name and create server
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 4. Wait for SSH and cloud-init
verify_server_connectivity "$LIGHTSAIL_SERVER_IP"
wait_for_cloud_init "$LIGHTSAIL_SERVER_IP"
verify_server_connectivity "${LIGHTSAIL_SERVER_IP}"
wait_for_cloud_init "${LIGHTSAIL_SERVER_IP}"
# 5. Install openclaw via bun
log_warn "Installing openclaw..."
run_server "$LIGHTSAIL_SERVER_IP" "source ~/.bashrc && bun install -g openclaw"
run_server "${LIGHTSAIL_SERVER_IP}" "source ~/.bashrc && bun install -g openclaw"
log_info "OpenClaw installed"
# 6. Get OpenRouter API key
@ -45,23 +45,23 @@ MODEL_ID=$(get_model_id_interactive "openrouter/auto" "Openclaw") || exit 1
# 8. Inject environment variables into ~/.zshrc
log_warn "Setting up environment variables..."
inject_env_vars_ssh "$LIGHTSAIL_SERVER_IP" upload_file run_server \
"OPENROUTER_API_KEY=$OPENROUTER_API_KEY" \
"ANTHROPIC_API_KEY=$OPENROUTER_API_KEY" \
inject_env_vars_ssh "${LIGHTSAIL_SERVER_IP}" upload_file run_server \
"OPENROUTER_API_KEY=${OPENROUTER_API_KEY}" \
"ANTHROPIC_API_KEY=${OPENROUTER_API_KEY}" \
"ANTHROPIC_BASE_URL=https://openrouter.ai/api"
# 9. Configure openclaw
setup_openclaw_config "$OPENROUTER_API_KEY" "$MODEL_ID" \
"upload_file $LIGHTSAIL_SERVER_IP" \
"run_server $LIGHTSAIL_SERVER_IP"
setup_openclaw_config "${OPENROUTER_API_KEY}" "${MODEL_ID}" \
"upload_file ${LIGHTSAIL_SERVER_IP}" \
"run_server ${LIGHTSAIL_SERVER_IP}"
echo ""
log_info "Lightsail instance setup completed successfully!"
log_info "Instance: $SERVER_NAME (IP: $LIGHTSAIL_SERVER_IP)"
log_info "Instance: ${SERVER_NAME} (IP: ${LIGHTSAIL_SERVER_IP})"
echo ""
# 10. Start openclaw gateway in background and launch TUI
log_warn "Starting openclaw..."
run_server "$LIGHTSAIL_SERVER_IP" "source ~/.zshrc && nohup openclaw gateway > /tmp/openclaw-gateway.log 2>&1 &"
run_server "${LIGHTSAIL_SERVER_IP}" "source ~/.zshrc && nohup openclaw gateway > /tmp/openclaw-gateway.log 2>&1 &"
sleep 2
interactive_session "$LIGHTSAIL_SERVER_IP" "source ~/.zshrc && openclaw tui"
interactive_session "${LIGHTSAIL_SERVER_IP}" "source ~/.zshrc && openclaw tui"

View file

@ -13,7 +13,7 @@
set -eo pipefail
SPAWN_REPO="OpenRouterTeam/spawn"
SPAWN_RAW_BASE="https://raw.githubusercontent.com/$SPAWN_REPO/main"
SPAWN_RAW_BASE="https://raw.githubusercontent.com/${SPAWN_REPO}/main"
RED='\033[0;31m'
GREEN='\033[0;32m'
@ -31,27 +31,27 @@ if command -v bun &>/dev/null; then
log_info "Installing spawn via bun..."
# Clone/download the cli directory and install from it
tmpdir=$(mktemp -d)
trap 'rm -rf "$tmpdir"' EXIT
trap 'rm -rf "${tmpdir}"' EXIT
log_info "Downloading CLI package..."
mkdir -p "$tmpdir/cli/src"
curl -fsSL "$SPAWN_RAW_BASE/cli/package.json" -o "$tmpdir/cli/package.json"
curl -fsSL "$SPAWN_RAW_BASE/cli/tsconfig.json" -o "$tmpdir/cli/tsconfig.json"
curl -fsSL "$SPAWN_RAW_BASE/cli/src/index.ts" -o "$tmpdir/cli/src/index.ts"
curl -fsSL "$SPAWN_RAW_BASE/cli/src/manifest.ts" -o "$tmpdir/cli/src/manifest.ts"
curl -fsSL "$SPAWN_RAW_BASE/cli/src/commands.ts" -o "$tmpdir/cli/src/commands.ts"
curl -fsSL "$SPAWN_RAW_BASE/cli/src/version.ts" -o "$tmpdir/cli/src/version.ts"
mkdir -p "${tmpdir}/cli/src"
curl -fsSL "${SPAWN_RAW_BASE}/cli/package.json" -o "${tmpdir}/cli/package.json"
curl -fsSL "${SPAWN_RAW_BASE}/cli/tsconfig.json" -o "${tmpdir}/cli/tsconfig.json"
curl -fsSL "${SPAWN_RAW_BASE}/cli/src/index.ts" -o "${tmpdir}/cli/src/index.ts"
curl -fsSL "${SPAWN_RAW_BASE}/cli/src/manifest.ts" -o "${tmpdir}/cli/src/manifest.ts"
curl -fsSL "${SPAWN_RAW_BASE}/cli/src/commands.ts" -o "${tmpdir}/cli/src/commands.ts"
curl -fsSL "${SPAWN_RAW_BASE}/cli/src/version.ts" -o "${tmpdir}/cli/src/version.ts"
cd "$tmpdir/cli"
cd "${tmpdir}/cli"
bun install
bun link 2>/dev/null || bun install -g . 2>/dev/null || {
# If global install fails, build and copy binary
log_warn "Global install failed, building binary..."
bun build src/index.ts --compile --outfile spawn
INSTALL_DIR="${SPAWN_INSTALL_DIR:-$HOME/.local/bin}"
mkdir -p "$INSTALL_DIR"
mv spawn "$INSTALL_DIR/spawn"
log_info "Installed spawn binary to $INSTALL_DIR/spawn"
INSTALL_DIR="${SPAWN_INSTALL_DIR:-${HOME}/.local/bin}"
mkdir -p "${INSTALL_DIR}"
mv spawn "${INSTALL_DIR}/spawn"
log_info "Installed spawn binary to ${INSTALL_DIR}/spawn"
}
log_info "spawn installed successfully!"
@ -68,18 +68,18 @@ fi
if command -v npm &>/dev/null && command -v node &>/dev/null; then
log_info "Installing spawn via npm..."
tmpdir=$(mktemp -d)
trap 'rm -rf "$tmpdir"' EXIT
trap 'rm -rf "${tmpdir}"' EXIT
log_info "Downloading CLI package..."
mkdir -p "$tmpdir/cli/src"
curl -fsSL "$SPAWN_RAW_BASE/cli/package.json" -o "$tmpdir/cli/package.json"
curl -fsSL "$SPAWN_RAW_BASE/cli/tsconfig.json" -o "$tmpdir/cli/tsconfig.json"
curl -fsSL "$SPAWN_RAW_BASE/cli/src/index.ts" -o "$tmpdir/cli/src/index.ts"
curl -fsSL "$SPAWN_RAW_BASE/cli/src/manifest.ts" -o "$tmpdir/cli/src/manifest.ts"
curl -fsSL "$SPAWN_RAW_BASE/cli/src/commands.ts" -o "$tmpdir/cli/src/commands.ts"
curl -fsSL "$SPAWN_RAW_BASE/cli/src/version.ts" -o "$tmpdir/cli/src/version.ts"
mkdir -p "${tmpdir}/cli/src"
curl -fsSL "${SPAWN_RAW_BASE}/cli/package.json" -o "${tmpdir}/cli/package.json"
curl -fsSL "${SPAWN_RAW_BASE}/cli/tsconfig.json" -o "${tmpdir}/cli/tsconfig.json"
curl -fsSL "${SPAWN_RAW_BASE}/cli/src/index.ts" -o "${tmpdir}/cli/src/index.ts"
curl -fsSL "${SPAWN_RAW_BASE}/cli/src/manifest.ts" -o "${tmpdir}/cli/src/manifest.ts"
curl -fsSL "${SPAWN_RAW_BASE}/cli/src/commands.ts" -o "${tmpdir}/cli/src/commands.ts"
curl -fsSL "${SPAWN_RAW_BASE}/cli/src/version.ts" -o "${tmpdir}/cli/src/version.ts"
cd "$tmpdir/cli"
cd "${tmpdir}/cli"
npm install
npm install -g . 2>/dev/null || {
log_warn "npm global install requires permissions. Try:"
@ -102,27 +102,27 @@ fi
# --- Method 3: Direct download fallback (bash wrapper) ---
log_warn "Neither bun nor npm found. Installing bash fallback..."
INSTALL_DIR="${SPAWN_INSTALL_DIR:-$HOME/.local/bin}"
mkdir -p "$INSTALL_DIR"
INSTALL_DIR="${SPAWN_INSTALL_DIR:-${HOME}/.local/bin}"
mkdir -p "${INSTALL_DIR}"
if ! curl -fsSL "$SPAWN_RAW_BASE/cli/spawn.sh" -o "$INSTALL_DIR/spawn"; then
if ! curl -fsSL "${SPAWN_RAW_BASE}/cli/spawn.sh" -o "${INSTALL_DIR}/spawn"; then
log_error "Failed to download spawn CLI"
exit 1
fi
chmod +x "$INSTALL_DIR/spawn"
log_info "Installed spawn (bash) to $INSTALL_DIR/spawn"
chmod +x "${INSTALL_DIR}/spawn"
log_info "Installed spawn (bash) to ${INSTALL_DIR}/spawn"
# Check if install dir is in PATH
if ! echo "$PATH" | tr ':' '\n' | grep -qx "$INSTALL_DIR"; then
log_warn "$INSTALL_DIR is not in your PATH"
if ! echo "${PATH}" | tr ':' '\n' | grep -qx "${INSTALL_DIR}"; then
log_warn "${INSTALL_DIR} is not in your PATH"
echo ""
echo "Add it by running one of:"
echo ""
case "${SHELL:-/bin/bash}" in
*/zsh) echo " echo 'export PATH=\"$INSTALL_DIR:\$PATH\"' >> ~/.zshrc && source ~/.zshrc" ;;
*/fish) echo " fish_add_path $INSTALL_DIR" ;;
*) echo " echo 'export PATH=\"$INSTALL_DIR:\$PATH\"' >> ~/.bashrc && source ~/.bashrc" ;;
*/zsh) echo " echo 'export PATH=\"${INSTALL_DIR}:\${PATH}\"' >> ~/.zshrc && source ~/.zshrc" ;;
*/fish) echo " fish_add_path ${INSTALL_DIR}" ;;
*) echo " echo 'export PATH=\"${INSTALL_DIR}:\${PATH}\"' >> ~/.bashrc && source ~/.bashrc" ;;
esac
echo ""
else

View file

@ -22,9 +22,9 @@ set -eo pipefail
SPAWN_VERSION="0.1.0"
SPAWN_REPO="OpenRouterTeam/spawn"
SPAWN_RAW_BASE="https://raw.githubusercontent.com/$SPAWN_REPO/main"
SPAWN_CACHE_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/spawn"
SPAWN_MANIFEST="$SPAWN_CACHE_DIR/manifest.json"
SPAWN_RAW_BASE="https://raw.githubusercontent.com/${SPAWN_REPO}/main"
SPAWN_CACHE_DIR="${XDG_CACHE_HOME:-${HOME}/.cache}/spawn"
SPAWN_MANIFEST="${SPAWN_CACHE_DIR}/manifest.json"
SPAWN_CACHE_TTL=3600 # 1 hour in seconds
# ── Colors & Logging ──────────────────────────────────────────────────────────
@ -53,7 +53,7 @@ check_deps() {
fi
command -v jq &>/dev/null && HAS_JQ=true
command -v python3 &>/dev/null && HAS_PYTHON3=true
if ! $HAS_JQ && ! $HAS_PYTHON3; then
if ! ${HAS_JQ} && ! ${HAS_PYTHON3}; then
log_error "Either jq or python3 is required for JSON parsing"
exit 1
fi
@ -65,21 +65,21 @@ check_deps() {
json_validate() {
local file="$1"
if $HAS_JQ; then
jq empty "$file" 2>/dev/null
elif $HAS_PYTHON3; then
python3 -c "import json; json.load(open('$file'))" 2>/dev/null
if ${HAS_JQ}; then
jq empty "${file}" 2>/dev/null
elif ${HAS_PYTHON3}; then
python3 -c "import json; json.load(open('${file}'))" 2>/dev/null
fi
}
# List agent keys (one per line)
manifest_agents() {
if $HAS_JQ; then
jq -r '.agents | keys[]' "$SPAWN_MANIFEST"
if ${HAS_JQ}; then
jq -r '.agents | keys[]' "${SPAWN_MANIFEST}"
else
python3 -c "
import json
m = json.load(open('$SPAWN_MANIFEST'))
m = json.load(open('${SPAWN_MANIFEST}'))
for k in m['agents']:
print(k)
"
@ -88,12 +88,12 @@ for k in m['agents']:
# List cloud keys (one per line)
manifest_clouds() {
if $HAS_JQ; then
jq -r '.clouds | keys[]' "$SPAWN_MANIFEST"
if ${HAS_JQ}; then
jq -r '.clouds | keys[]' "${SPAWN_MANIFEST}"
else
python3 -c "
import json
m = json.load(open('$SPAWN_MANIFEST'))
m = json.load(open('${SPAWN_MANIFEST}'))
for k in m['clouds']:
print(k)
"
@ -103,13 +103,13 @@ for k in m['clouds']:
# Get agent display name
manifest_agent_name() {
local agent="$1"
if $HAS_JQ; then
jq -r --arg a "$agent" '.agents[$a].name // empty' "$SPAWN_MANIFEST"
if ${HAS_JQ}; then
jq -r --arg a "${agent}" '.agents[${a}].name // empty' "${SPAWN_MANIFEST}"
else
python3 -c "
import json
m = json.load(open('$SPAWN_MANIFEST'))
a = m['agents'].get('$agent', {})
m = json.load(open('${SPAWN_MANIFEST}'))
a = m['agents'].get('${agent}', {})
print(a.get('name', ''))
"
fi
@ -118,13 +118,13 @@ print(a.get('name', ''))
# Get agent description
manifest_agent_desc() {
local agent="$1"
if $HAS_JQ; then
jq -r --arg a "$agent" '.agents[$a].description // empty' "$SPAWN_MANIFEST"
if ${HAS_JQ}; then
jq -r --arg a "${agent}" '.agents[${a}].description // empty' "${SPAWN_MANIFEST}"
else
python3 -c "
import json
m = json.load(open('$SPAWN_MANIFEST'))
a = m['agents'].get('$agent', {})
m = json.load(open('${SPAWN_MANIFEST}'))
a = m['agents'].get('${agent}', {})
print(a.get('description', ''))
"
fi
@ -133,13 +133,13 @@ print(a.get('description', ''))
# Get cloud display name
manifest_cloud_name() {
local cloud="$1"
if $HAS_JQ; then
jq -r --arg c "$cloud" '.clouds[$c].name // empty' "$SPAWN_MANIFEST"
if ${HAS_JQ}; then
jq -r --arg c "${cloud}" '.clouds[${c}].name // empty' "${SPAWN_MANIFEST}"
else
python3 -c "
import json
m = json.load(open('$SPAWN_MANIFEST'))
c = m['clouds'].get('$cloud', {})
m = json.load(open('${SPAWN_MANIFEST}'))
c = m['clouds'].get('${cloud}', {})
print(c.get('name', ''))
"
fi
@ -148,13 +148,13 @@ print(c.get('name', ''))
# Get cloud description
manifest_cloud_desc() {
local cloud="$1"
if $HAS_JQ; then
jq -r --arg c "$cloud" '.clouds[$c].description // empty' "$SPAWN_MANIFEST"
if ${HAS_JQ}; then
jq -r --arg c "${cloud}" '.clouds[${c}].description // empty' "${SPAWN_MANIFEST}"
else
python3 -c "
import json
m = json.load(open('$SPAWN_MANIFEST'))
c = m['clouds'].get('$cloud', {})
m = json.load(open('${SPAWN_MANIFEST}'))
c = m['clouds'].get('${cloud}', {})
print(c.get('description', ''))
"
fi
@ -163,25 +163,25 @@ print(c.get('description', ''))
# Get matrix status for cloud/agent
manifest_matrix_status() {
local cloud="$1" agent="$2"
if $HAS_JQ; then
jq -r --arg key "$cloud/$agent" '.matrix[$key] // "missing"' "$SPAWN_MANIFEST"
if ${HAS_JQ}; then
jq -r --arg key "${cloud}/${agent}" '.matrix[${key}] // "missing"' "${SPAWN_MANIFEST}"
else
python3 -c "
import json
m = json.load(open('$SPAWN_MANIFEST'))
print(m.get('matrix', {}).get('$cloud/$agent', 'missing'))
m = json.load(open('${SPAWN_MANIFEST}'))
print(m.get('matrix', {}).get('${cloud}/${agent}', 'missing'))
"
fi
}
# Count implemented entries
manifest_count_implemented() {
if $HAS_JQ; then
jq '[.matrix | to_entries[] | select(.value == "implemented")] | length' "$SPAWN_MANIFEST"
if ${HAS_JQ}; then
jq '[.matrix | to_entries[] | select(.value == "implemented")] | length' "${SPAWN_MANIFEST}"
else
python3 -c "
import json
m = json.load(open('$SPAWN_MANIFEST'))
m = json.load(open('${SPAWN_MANIFEST}'))
print(sum(1 for v in m.get('matrix', {}).values() if v == 'implemented'))
"
fi
@ -195,21 +195,21 @@ file_age_seconds() {
now=$(date +%s)
local mtime
# macOS uses -f, Linux uses -c
if stat -f %m "$file" &>/dev/null; then
mtime=$(stat -f %m "$file")
if stat -f %m "${file}" &>/dev/null; then
mtime=$(stat -f %m "${file}")
else
mtime=$(stat -c %Y "$file" 2>/dev/null || echo 0)
mtime=$(stat -c %Y "${file}" 2>/dev/null || echo 0)
fi
echo $(( now - mtime ))
}
ensure_manifest() {
mkdir -p "$SPAWN_CACHE_DIR"
mkdir -p "${SPAWN_CACHE_DIR}"
# Check if cache exists and is fresh
if [[ -f "$SPAWN_MANIFEST" ]]; then
if [[ -f "${SPAWN_MANIFEST}" ]]; then
local age
age=$(file_age_seconds "$SPAWN_MANIFEST")
age=$(file_age_seconds "${SPAWN_MANIFEST}")
if (( age < SPAWN_CACHE_TTL )); then
return 0
fi
@ -218,21 +218,21 @@ ensure_manifest() {
log_info "Fetching manifest..."
local tmp
tmp=$(mktemp)
if curl -fsSL "$SPAWN_RAW_BASE/manifest.json" -o "$tmp" 2>/dev/null; then
if json_validate "$tmp"; then
mv "$tmp" "$SPAWN_MANIFEST"
if curl -fsSL "${SPAWN_RAW_BASE}/manifest.json" -o "${tmp}" 2>/dev/null; then
if json_validate "${tmp}"; then
mv "${tmp}" "${SPAWN_MANIFEST}"
return 0
else
rm -f "$tmp"
rm -f "${tmp}"
log_warn "Downloaded manifest is invalid JSON"
fi
else
rm -f "$tmp"
rm -f "${tmp}"
log_warn "Failed to fetch manifest"
fi
# Offline fallback: use stale cache if available
if [[ -f "$SPAWN_MANIFEST" ]]; then
if [[ -f "${SPAWN_MANIFEST}" ]]; then
log_warn "Using cached manifest (offline fallback)"
return 0
fi
@ -255,19 +255,19 @@ picker() {
local i
for (( i = 0; i < count; i++ )); do
printf " %s%2d)%s %s\n" "${GREEN}" $(( i + 1 )) "${NC}" "${items[$i]}" >&2
printf " %s%2d)%s %s\n" "${GREEN}" $(( i + 1 )) "${NC}" "${items[${i}]}" >&2
done
echo "" >&2
local choice
while true; do
printf " Enter number (1-%d): " "$count" >&2
printf " Enter number (1-%d): " "${count}" >&2
read -r choice </dev/tty
if [[ "$choice" =~ ^[0-9]+$ ]] && (( choice >= 1 && choice <= count )); then
if [[ "${choice}" =~ ^[0-9]+$ ]] && (( choice >= 1 && choice <= count )); then
echo $(( choice - 1 ))
return 0
fi
log_warn "Invalid choice. Enter a number between 1 and $count."
log_warn "Invalid choice. Enter a number between 1 and ${count}."
done
}
@ -280,10 +280,10 @@ cmd_interactive() {
local -a agent_keys=()
local -a agent_labels=()
while IFS= read -r key; do
agent_keys+=("$key")
agent_keys+=("${key}")
local name desc
name=$(manifest_agent_name "$key")
desc=$(manifest_agent_desc "$key")
name=$(manifest_agent_name "${key}")
desc=$(manifest_agent_desc "${key}")
agent_labels+=("${name} ${DIM}- ${desc}${NC}")
done < <(manifest_agents)
@ -294,35 +294,35 @@ cmd_interactive() {
local agent_idx
agent_idx=$(picker "Select an agent:" "${agent_labels[@]}")
local agent="${agent_keys[$agent_idx]}"
local agent="${agent_keys[${agent_idx}]}"
# Build cloud list — only show implemented clouds for this agent
local -a cloud_keys=()
local -a cloud_labels=()
while IFS= read -r key; do
local status
status=$(manifest_matrix_status "$key" "$agent")
if [[ "$status" == "implemented" ]]; then
cloud_keys+=("$key")
status=$(manifest_matrix_status "${key}" "${agent}")
if [[ "${status}" == "implemented" ]]; then
cloud_keys+=("${key}")
local name desc
name=$(manifest_cloud_name "$key")
desc=$(manifest_cloud_desc "$key")
name=$(manifest_cloud_name "${key}")
desc=$(manifest_cloud_desc "${key}")
cloud_labels+=("${name} ${DIM}- ${desc}${NC}")
fi
done < <(manifest_clouds)
if (( ${#cloud_keys[@]} == 0 )); then
local aname
aname=$(manifest_agent_name "$agent")
log_error "No implemented clouds found for $aname"
aname=$(manifest_agent_name "${agent}")
log_error "No implemented clouds found for ${aname}"
exit 1
fi
local cloud_idx
cloud_idx=$(picker "Select a cloud provider:" "${cloud_labels[@]}")
local cloud="${cloud_keys[$cloud_idx]}"
local cloud="${cloud_keys[${cloud_idx}]}"
cmd_run "$agent" "$cloud"
cmd_run "${agent}" "${cloud}"
}
cmd_run() {
@ -330,70 +330,70 @@ cmd_run() {
ensure_manifest
local agent_name cloud_name status
agent_name=$(manifest_agent_name "$agent")
cloud_name=$(manifest_cloud_name "$cloud")
agent_name=$(manifest_agent_name "${agent}")
cloud_name=$(manifest_cloud_name "${cloud}")
if [[ -z "$agent_name" ]]; then
log_error "Unknown agent: $agent"
if [[ -z "${agent_name}" ]]; then
log_error "Unknown agent: ${agent}"
echo "Run 'spawn agents' to see available agents." >&2
exit 1
fi
if [[ -z "$cloud_name" ]]; then
log_error "Unknown cloud: $cloud"
if [[ -z "${cloud_name}" ]]; then
log_error "Unknown cloud: ${cloud}"
echo "Run 'spawn clouds' to see available clouds." >&2
exit 1
fi
status=$(manifest_matrix_status "$cloud" "$agent")
if [[ "$status" != "implemented" ]]; then
log_error "$agent_name on $cloud_name is not yet implemented"
status=$(manifest_matrix_status "${cloud}" "${agent}")
if [[ "${status}" != "implemented" ]]; then
log_error "${agent_name} on ${cloud_name} is not yet implemented"
exit 1
fi
log_info "Launching ${BOLD}${agent_name}${NC}${GREEN} on ${BOLD}${cloud_name}${NC}${GREEN}...${NC}"
local url="https://openrouter.ai/lab/spawn/${cloud}/${agent}.sh"
bash <(curl -fsSL "$url")
bash <(curl -fsSL "${url}")
}
cmd_list() {
ensure_manifest
if $HAS_PYTHON3; then
if ${HAS_PYTHON3}; then
cmd_list_python
elif $HAS_JQ; then
elif ${HAS_JQ}; then
cmd_list_jq
fi
}
cmd_list_jq() {
jq -r '
def pad($n): . + (" " * ($n - length)) | .[:$n];
def pad(${n}): . + (" " * (${n} - length)) | .[:${n}];
def status_icon: if . == "implemented" then " ✓" else " -" end;
. as $root |
($root.agents | keys) as $agents |
($root.clouds | keys) as $clouds |
. as ${root} |
(${root}.agents | keys) as ${agents} |
(${root}.clouds | keys) as ${clouds} |
(("" | pad(18)) + ($clouds | map(. as $c | $root.clouds[$c].name | pad(14)) | join(""))),
($agents[] as $agent |
($root.agents[$agent].name | pad(18)) +
($clouds | map(. as $cloud |
($root.matrix["\($cloud)/\($agent)"] // "missing" | status_icon | pad(14))
(("" | pad(18)) + (${clouds} | map(. as ${c} | ${root}.clouds[${c}].name | pad(14)) | join(""))),
(${agents}[] as ${agent} |
(${root}.agents[${agent}].name | pad(18)) +
(${clouds} | map(. as ${cloud} |
(${root}.matrix["\(${cloud})/\(${agent})"] // "missing" | status_icon | pad(14))
) | join(""))
),
"",
([$root.matrix | to_entries[] | select(.value == "implemented")] | length | tostring) +
([${root}.matrix | to_entries[] | select(.value == "implemented")] | length | tostring) +
"/" +
(($agents | length) * ($clouds | length) | tostring) +
((${agents} | length) * (${clouds} | length) | tostring) +
" implemented"
' "$SPAWN_MANIFEST"
' "${SPAWN_MANIFEST}"
}
cmd_list_python() {
python3 -c "
import json
m = json.load(open('$SPAWN_MANIFEST'))
m = json.load(open('${SPAWN_MANIFEST}'))
agents = list(m['agents'].keys())
clouds = list(m['clouds'].keys())
matrix = m.get('matrix', {})
@ -438,9 +438,9 @@ cmd_agents() {
while IFS= read -r key; do
local name desc
name=$(manifest_agent_name "$key")
desc=$(manifest_agent_desc "$key")
printf " ${GREEN}%-16s${NC} %s\n" "$name" "$desc"
name=$(manifest_agent_name "${key}")
desc=$(manifest_agent_desc "${key}")
printf " ${GREEN}%-16s${NC} %s\n" "${name}" "${desc}"
done < <(manifest_agents)
echo ""
}
@ -454,9 +454,9 @@ cmd_clouds() {
while IFS= read -r key; do
local name desc
name=$(manifest_cloud_name "$key")
desc=$(manifest_cloud_desc "$key")
printf " ${GREEN}%-16s${NC} %s\n" "$name" "$desc"
name=$(manifest_cloud_name "${key}")
desc=$(manifest_cloud_desc "${key}")
printf " ${GREEN}%-16s${NC} %s\n" "${name}" "${desc}"
done < <(manifest_clouds)
echo ""
}
@ -466,11 +466,11 @@ cmd_agent_info() {
ensure_manifest
local agent_name agent_desc
agent_name=$(manifest_agent_name "$agent")
agent_desc=$(manifest_agent_desc "$agent")
agent_name=$(manifest_agent_name "${agent}")
agent_desc=$(manifest_agent_desc "${agent}")
if [[ -z "$agent_name" ]]; then
log_error "Unknown agent: $agent"
if [[ -z "${agent_name}" ]]; then
log_error "Unknown agent: ${agent}"
echo "Run 'spawn agents' to see available agents." >&2
exit 1
fi
@ -484,16 +484,16 @@ cmd_agent_info() {
local found=false
while IFS= read -r cloud; do
local status
status=$(manifest_matrix_status "$cloud" "$agent")
if [[ "$status" == "implemented" ]]; then
status=$(manifest_matrix_status "${cloud}" "${agent}")
if [[ "${status}" == "implemented" ]]; then
local cloud_name
cloud_name=$(manifest_cloud_name "$cloud")
printf " ${GREEN}%-16s${NC} spawn %s %s\n" "$cloud_name" "$agent" "$cloud"
cloud_name=$(manifest_cloud_name "${cloud}")
printf " ${GREEN}%-16s${NC} spawn %s %s\n" "${cloud_name}" "${agent}" "${cloud}"
found=true
fi
done < <(manifest_clouds)
if ! $found; then
if ! ${found}; then
echo " No implemented clouds yet."
fi
echo ""
@ -507,26 +507,26 @@ cmd_improve() {
if [[ -f "./improve.sh" && -f "./manifest.json" ]]; then
repo_dir="."
else
repo_dir="$SPAWN_CACHE_DIR/repo"
if [[ -d "$repo_dir/.git" ]]; then
repo_dir="${SPAWN_CACHE_DIR}/repo"
if [[ -d "${repo_dir}/.git" ]]; then
log_info "Updating spawn repo..."
git -C "$repo_dir" pull --ff-only 2>/dev/null || true
git -C "${repo_dir}" pull --ff-only 2>/dev/null || true
else
log_info "Cloning spawn repo..."
git clone "https://github.com/$SPAWN_REPO.git" "$repo_dir"
git clone "https://github.com/${SPAWN_REPO}.git" "${repo_dir}"
fi
fi
(cd "$repo_dir" && bash improve.sh "$@")
(cd "${repo_dir}" && bash improve.sh "$@")
}
cmd_update() {
local self
self=$(command -v spawn 2>/dev/null || echo "")
if [[ -z "$self" ]]; then
if [[ -z "${self}" ]]; then
# Try common install locations
if [[ -f "$HOME/.local/bin/spawn" ]]; then
self="$HOME/.local/bin/spawn"
if [[ -f "${HOME}/.local/bin/spawn" ]]; then
self="${HOME}/.local/bin/spawn"
else
log_error "Cannot find spawn binary for self-update"
exit 1
@ -536,29 +536,29 @@ cmd_update() {
log_info "Checking for updates..."
local tmp
tmp=$(mktemp)
if curl -fsSL "$SPAWN_RAW_BASE/cli/spawn.sh" -o "$tmp" 2>/dev/null; then
if curl -fsSL "${SPAWN_RAW_BASE}/cli/spawn.sh" -o "${tmp}" 2>/dev/null; then
local remote_version
remote_version=$(grep '^SPAWN_VERSION=' "$tmp" | head -1 | cut -d'"' -f2)
if [[ -z "$remote_version" ]]; then
rm -f "$tmp"
remote_version=$(grep '^SPAWN_VERSION=' "${tmp}" | head -1 | cut -d'"' -f2)
if [[ -z "${remote_version}" ]]; then
rm -f "${tmp}"
log_error "Could not determine remote version"
exit 1
fi
if [[ "$remote_version" == "$SPAWN_VERSION" ]]; then
rm -f "$tmp"
if [[ "${remote_version}" == "${SPAWN_VERSION}" ]]; then
rm -f "${tmp}"
log_info "Already up to date (v${SPAWN_VERSION})"
return 0
fi
chmod +x "$tmp"
mv "$tmp" "$self"
chmod +x "${tmp}"
mv "${tmp}" "${self}"
log_info "Updated: v${SPAWN_VERSION} → v${remote_version}"
# Invalidate manifest cache on update
rm -f "$SPAWN_MANIFEST"
rm -f "${SPAWN_MANIFEST}"
else
rm -f "$tmp"
rm -f "${tmp}"
log_error "Failed to download update"
exit 1
fi
@ -588,7 +588,7 @@ ${BOLD}EXAMPLES${NC}
spawn list See the full agent x cloud matrix
${BOLD}INSTALL${NC}
curl -fsSL $SPAWN_RAW_BASE/cli/install.sh | bash
curl -fsSL ${SPAWN_RAW_BASE}/cli/install.sh | bash
"
}
@ -631,17 +631,17 @@ main() {
# Check if it's a valid agent
local agent_name
agent_name=$(manifest_agent_name "$agent")
if [[ -z "$agent_name" ]]; then
log_error "Unknown command or agent: $agent"
agent_name=$(manifest_agent_name "${agent}")
if [[ -z "${agent_name}" ]]; then
log_error "Unknown command or agent: ${agent}"
echo "Run 'spawn help' for usage." >&2
exit 1
fi
if (( $# >= 2 )); then
cmd_run "$agent" "$2"
cmd_run "${agent}" "$2"
else
cmd_agent_info "$agent"
cmd_agent_info "${agent}"
fi
;;
esac

View file

@ -4,8 +4,8 @@ set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=digitalocean/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/digitalocean/lib/common.sh)"
fi
@ -21,20 +21,20 @@ ensure_ssh_key
# 3. Get droplet name and create droplet
DROPLET_NAME=$(get_server_name)
create_server "$DROPLET_NAME"
create_server "${DROPLET_NAME}"
# 4. Wait for SSH and cloud-init
verify_server_connectivity "$DO_SERVER_IP"
wait_for_cloud_init "$DO_SERVER_IP"
verify_server_connectivity "${DO_SERVER_IP}"
wait_for_cloud_init "${DO_SERVER_IP}"
# 5. Install Aider
log_warn "Installing Aider..."
run_server "$DO_SERVER_IP" "pip install aider-chat 2>/dev/null || pip3 install aider-chat"
run_server "${DO_SERVER_IP}" "pip install aider-chat 2>/dev/null || pip3 install aider-chat"
# Verify installation succeeded
if ! run_server "$DO_SERVER_IP" "command -v aider &> /dev/null && aider --version &> /dev/null"; then
if ! run_server "${DO_SERVER_IP}" "command -v aider &> /dev/null && aider --version &> /dev/null"; then
log_error "Aider installation verification failed"
log_error "The 'aider' command is not available or not working properly on server $DO_SERVER_IP"
log_error "The 'aider' command is not available or not working properly on server ${DO_SERVER_IP}"
exit 1
fi
log_info "Aider installation verified successfully"
@ -51,16 +51,16 @@ fi
MODEL_ID=$(get_model_id_interactive "openrouter/auto" "Aider") || exit 1
log_warn "Setting up environment variables..."
inject_env_vars_ssh "$DO_SERVER_IP" upload_file run_server \
"OPENROUTER_API_KEY=$OPENROUTER_API_KEY"
inject_env_vars_ssh "${DO_SERVER_IP}" upload_file run_server \
"OPENROUTER_API_KEY=${OPENROUTER_API_KEY}"
echo ""
log_info "DigitalOcean droplet setup completed successfully!"
log_info "Droplet: $DROPLET_NAME (ID: $DO_DROPLET_ID, IP: $DO_SERVER_IP)"
log_info "Droplet: ${DROPLET_NAME} (ID: ${DO_DROPLET_ID}, IP: ${DO_SERVER_IP})"
echo ""
# 9. Start Aider interactively
log_warn "Starting Aider..."
sleep 1
clear
interactive_session "$DO_SERVER_IP" "source ~/.zshrc && aider --model openrouter/${MODEL_ID}"
interactive_session "${DO_SERVER_IP}" "source ~/.zshrc && aider --model openrouter/${MODEL_ID}"

View file

@ -1,10 +1,10 @@
#!/bin/bash
set -e
set -eo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=digitalocean/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/digitalocean/lib/common.sh)"
fi
@ -16,12 +16,12 @@ ensure_do_token
ensure_ssh_key
DROPLET_NAME=$(get_server_name)
create_server "$DROPLET_NAME"
verify_server_connectivity "$DO_SERVER_IP"
wait_for_cloud_init "$DO_SERVER_IP"
create_server "${DROPLET_NAME}"
verify_server_connectivity "${DO_SERVER_IP}"
wait_for_cloud_init "${DO_SERVER_IP}"
log_warn "Installing Amazon Q CLI..."
run_server "$DO_SERVER_IP" "curl -fsSL https://desktop-release.q.us-east-1.amazonaws.com/latest/amazon-q-cli-install.sh | bash"
run_server "${DO_SERVER_IP}" "curl -fsSL https://desktop-release.q.us-east-1.amazonaws.com/latest/amazon-q-cli-install.sh | bash"
log_info "Amazon Q CLI installed"
echo ""
@ -33,23 +33,23 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_BASE_URL="https://openrouter.ai/api/v1"
EOF
upload_file "$DO_SERVER_IP" "$ENV_TEMP" "/tmp/env_config"
run_server "$DO_SERVER_IP" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
upload_file "${DO_SERVER_IP}" "${ENV_TEMP}" "/tmp/env_config"
run_server "${DO_SERVER_IP}" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "${ENV_TEMP}"
echo ""
log_info "DigitalOcean droplet setup completed successfully!"
log_info "Droplet: $DROPLET_NAME (ID: $DO_DROPLET_ID, IP: $DO_SERVER_IP)"
log_info "Droplet: ${DROPLET_NAME} (ID: ${DO_DROPLET_ID}, IP: ${DO_SERVER_IP})"
echo ""
log_warn "Starting Amazon Q..."
sleep 1
clear
interactive_session "$DO_SERVER_IP" "source ~/.zshrc && q chat"
interactive_session "${DO_SERVER_IP}" "source ~/.zshrc && q chat"

View file

@ -4,8 +4,8 @@ set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=digitalocean/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/digitalocean/lib/common.sh)"
fi
@ -24,23 +24,23 @@ ensure_ssh_key
# 3. Get droplet name and create droplet
DROPLET_NAME=$(get_server_name)
create_server "$DROPLET_NAME"
create_server "${DROPLET_NAME}"
# 4. Wait for SSH and cloud-init
verify_server_connectivity "$DO_SERVER_IP"
wait_for_cloud_init "$DO_SERVER_IP"
verify_server_connectivity "${DO_SERVER_IP}"
wait_for_cloud_init "${DO_SERVER_IP}"
# 5. Verify Claude Code is installed (fallback to manual install)
log_warn "Verifying Claude Code installation..."
if ! run_server "$DO_SERVER_IP" "command -v claude" >/dev/null 2>&1; then
if ! run_server "${DO_SERVER_IP}" "command -v claude" >/dev/null 2>&1; then
log_warn "Claude Code not found, installing manually..."
run_server "$DO_SERVER_IP" "curl -fsSL https://claude.ai/install.sh | bash"
run_server "${DO_SERVER_IP}" "curl -fsSL https://claude.ai/install.sh | bash"
fi
# Verify installation succeeded
if ! run_server "$DO_SERVER_IP" "command -v claude &> /dev/null && claude --version &> /dev/null"; then
if ! run_server "${DO_SERVER_IP}" "command -v claude &> /dev/null && claude --version &> /dev/null"; then
log_error "Claude Code installation verification failed"
log_error "The 'claude' command is not available or not working properly on server $DO_SERVER_IP"
log_error "The 'claude' command is not available or not working properly on server ${DO_SERVER_IP}"
exit 1
fi
log_info "Claude Code installation verified successfully"
@ -55,26 +55,26 @@ fi
# 7. Inject environment variables into ~/.zshrc
log_warn "Setting up environment variables..."
inject_env_vars_ssh "$DO_SERVER_IP" upload_file run_server \
"OPENROUTER_API_KEY=$OPENROUTER_API_KEY" \
inject_env_vars_ssh "${DO_SERVER_IP}" upload_file run_server \
"OPENROUTER_API_KEY=${OPENROUTER_API_KEY}" \
"ANTHROPIC_BASE_URL=https://openrouter.ai/api" \
"ANTHROPIC_AUTH_TOKEN=$OPENROUTER_API_KEY" \
"ANTHROPIC_AUTH_TOKEN=${OPENROUTER_API_KEY}" \
"ANTHROPIC_API_KEY=" \
"CLAUDE_CODE_SKIP_ONBOARDING=1" \
"CLAUDE_CODE_ENABLE_TELEMETRY=0"
# 8. Configure Claude Code settings
setup_claude_code_config "$OPENROUTER_API_KEY" \
"upload_file $DO_SERVER_IP" \
"run_server $DO_SERVER_IP"
setup_claude_code_config "${OPENROUTER_API_KEY}" \
"upload_file ${DO_SERVER_IP}" \
"run_server ${DO_SERVER_IP}"
echo ""
log_info "DigitalOcean droplet setup completed successfully!"
log_info "Droplet: $DROPLET_NAME (ID: $DO_DROPLET_ID, IP: $DO_SERVER_IP)"
log_info "Droplet: ${DROPLET_NAME} (ID: ${DO_DROPLET_ID}, IP: ${DO_SERVER_IP})"
echo ""
# 9. Start Claude Code interactively
log_warn "Starting Claude Code..."
sleep 1
clear
interactive_session "$DO_SERVER_IP" "source ~/.zshrc && claude"
interactive_session "${DO_SERVER_IP}" "source ~/.zshrc && claude"

View file

@ -1,10 +1,10 @@
#!/bin/bash
set -e
set -eo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=digitalocean/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/digitalocean/lib/common.sh)"
fi
@ -16,12 +16,12 @@ ensure_do_token
ensure_ssh_key
DROPLET_NAME=$(get_server_name)
create_server "$DROPLET_NAME"
verify_server_connectivity "$DO_SERVER_IP"
wait_for_cloud_init "$DO_SERVER_IP"
create_server "${DROPLET_NAME}"
verify_server_connectivity "${DO_SERVER_IP}"
wait_for_cloud_init "${DO_SERVER_IP}"
log_warn "Installing Cline..."
run_server "$DO_SERVER_IP" "npm install -g cline"
run_server "${DO_SERVER_IP}" "npm install -g cline"
log_info "Cline installed"
echo ""
@ -33,23 +33,23 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_BASE_URL="https://openrouter.ai/api/v1"
EOF
upload_file "$DO_SERVER_IP" "$ENV_TEMP" "/tmp/env_config"
run_server "$DO_SERVER_IP" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
upload_file "${DO_SERVER_IP}" "${ENV_TEMP}" "/tmp/env_config"
run_server "${DO_SERVER_IP}" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "${ENV_TEMP}"
echo ""
log_info "DigitalOcean droplet setup completed successfully!"
log_info "Droplet: $DROPLET_NAME (ID: $DO_DROPLET_ID, IP: $DO_SERVER_IP)"
log_info "Droplet: ${DROPLET_NAME} (ID: ${DO_DROPLET_ID}, IP: ${DO_SERVER_IP})"
echo ""
log_warn "Starting Cline..."
sleep 1
clear
interactive_session "$DO_SERVER_IP" "source ~/.zshrc && cline"
interactive_session "${DO_SERVER_IP}" "source ~/.zshrc && cline"

View file

@ -3,8 +3,8 @@ set -eo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=digitalocean/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/digitalocean/lib/common.sh)"
fi
@ -16,12 +16,12 @@ ensure_do_token
ensure_ssh_key
DROPLET_NAME=$(get_server_name)
create_server "$DROPLET_NAME"
verify_server_connectivity "$DO_SERVER_IP"
wait_for_cloud_init "$DO_SERVER_IP"
create_server "${DROPLET_NAME}"
verify_server_connectivity "${DO_SERVER_IP}"
wait_for_cloud_init "${DO_SERVER_IP}"
log_warn "Installing Codex CLI..."
run_server "$DO_SERVER_IP" "npm install -g @openai/codex"
run_server "${DO_SERVER_IP}" "npm install -g @openai/codex"
log_info "Codex CLI installed"
echo ""
@ -32,17 +32,17 @@ else
fi
log_warn "Setting up environment variables..."
inject_env_vars_ssh "$DO_SERVER_IP" upload_file run_server \
"OPENROUTER_API_KEY=$OPENROUTER_API_KEY" \
"OPENAI_API_KEY=$OPENROUTER_API_KEY" \
inject_env_vars_ssh "${DO_SERVER_IP}" upload_file run_server \
"OPENROUTER_API_KEY=${OPENROUTER_API_KEY}" \
"OPENAI_API_KEY=${OPENROUTER_API_KEY}" \
"OPENAI_BASE_URL=https://openrouter.ai/api/v1"
echo ""
log_info "DigitalOcean droplet setup completed successfully!"
log_info "Droplet: $DROPLET_NAME (ID: $DO_DROPLET_ID, IP: $DO_SERVER_IP)"
log_info "Droplet: ${DROPLET_NAME} (ID: ${DO_DROPLET_ID}, IP: ${DO_SERVER_IP})"
echo ""
log_warn "Starting Codex..."
sleep 1
clear
interactive_session "$DO_SERVER_IP" "source ~/.zshrc && codex"
interactive_session "${DO_SERVER_IP}" "source ~/.zshrc && codex"

View file

@ -1,10 +1,10 @@
#!/bin/bash
set -e
set -eo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=digitalocean/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/digitalocean/lib/common.sh)"
fi
@ -16,12 +16,12 @@ ensure_do_token
ensure_ssh_key
DROPLET_NAME=$(get_server_name)
create_server "$DROPLET_NAME"
verify_server_connectivity "$DO_SERVER_IP"
wait_for_cloud_init "$DO_SERVER_IP"
create_server "${DROPLET_NAME}"
verify_server_connectivity "${DO_SERVER_IP}"
wait_for_cloud_init "${DO_SERVER_IP}"
log_warn "Installing Gemini CLI..."
run_server "$DO_SERVER_IP" "npm install -g @google/gemini-cli"
run_server "${DO_SERVER_IP}" "npm install -g @google/gemini-cli"
log_info "Gemini CLI installed"
echo ""
@ -33,7 +33,7 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
@ -41,16 +41,16 @@ export GEMINI_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_BASE_URL="https://openrouter.ai/api/v1"
EOF
upload_file "$DO_SERVER_IP" "$ENV_TEMP" "/tmp/env_config"
run_server "$DO_SERVER_IP" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
upload_file "${DO_SERVER_IP}" "${ENV_TEMP}" "/tmp/env_config"
run_server "${DO_SERVER_IP}" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "${ENV_TEMP}"
echo ""
log_info "DigitalOcean droplet setup completed successfully!"
log_info "Droplet: $DROPLET_NAME (ID: $DO_DROPLET_ID, IP: $DO_SERVER_IP)"
log_info "Droplet: ${DROPLET_NAME} (ID: ${DO_DROPLET_ID}, IP: ${DO_SERVER_IP})"
echo ""
log_warn "Starting Gemini..."
sleep 1
clear
interactive_session "$DO_SERVER_IP" "source ~/.zshrc && gemini"
interactive_session "${DO_SERVER_IP}" "source ~/.zshrc && gemini"

View file

@ -4,8 +4,8 @@ set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=digitalocean/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/digitalocean/lib/common.sh)"
fi
@ -21,15 +21,15 @@ ensure_ssh_key
# 3. Get droplet name and create droplet
DROPLET_NAME=$(get_server_name)
create_server "$DROPLET_NAME"
create_server "${DROPLET_NAME}"
# 4. Wait for SSH and cloud-init
verify_server_connectivity "$DO_SERVER_IP"
wait_for_cloud_init "$DO_SERVER_IP"
verify_server_connectivity "${DO_SERVER_IP}"
wait_for_cloud_init "${DO_SERVER_IP}"
# 5. Install Goose
log_warn "Installing Goose..."
run_server "$DO_SERVER_IP" "CONFIGURE=false curl -fsSL https://github.com/block/goose/releases/latest/download/download_cli.sh | bash"
run_server "${DO_SERVER_IP}" "CONFIGURE=false curl -fsSL https://github.com/block/goose/releases/latest/download/download_cli.sh | bash"
log_info "Goose installed"
# 6. Get OpenRouter API key
@ -41,17 +41,17 @@ else
fi
log_warn "Setting up environment variables..."
inject_env_vars_ssh "$DO_SERVER_IP" upload_file run_server \
inject_env_vars_ssh "${DO_SERVER_IP}" upload_file run_server \
"GOOSE_PROVIDER=openrouter" \
"OPENROUTER_API_KEY=$OPENROUTER_API_KEY"
"OPENROUTER_API_KEY=${OPENROUTER_API_KEY}"
echo ""
log_info "DigitalOcean droplet setup completed successfully!"
log_info "Droplet: $DROPLET_NAME (ID: $DO_DROPLET_ID, IP: $DO_SERVER_IP)"
log_info "Droplet: ${DROPLET_NAME} (ID: ${DO_DROPLET_ID}, IP: ${DO_SERVER_IP})"
echo ""
# 8. Start Goose interactively
log_warn "Starting Goose..."
sleep 1
clear
interactive_session "$DO_SERVER_IP" "source ~/.zshrc && goose"
interactive_session "${DO_SERVER_IP}" "source ~/.zshrc && goose"

View file

@ -3,8 +3,8 @@ set -eo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=digitalocean/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/digitalocean/lib/common.sh)"
fi
@ -16,12 +16,12 @@ ensure_do_token
ensure_ssh_key
DROPLET_NAME=$(get_server_name)
create_server "$DROPLET_NAME"
verify_server_connectivity "$DO_SERVER_IP"
wait_for_cloud_init "$DO_SERVER_IP"
create_server "${DROPLET_NAME}"
verify_server_connectivity "${DO_SERVER_IP}"
wait_for_cloud_init "${DO_SERVER_IP}"
log_warn "Installing Open Interpreter..."
run_server "$DO_SERVER_IP" "pip install open-interpreter 2>/dev/null || pip3 install open-interpreter"
run_server "${DO_SERVER_IP}" "pip install open-interpreter 2>/dev/null || pip3 install open-interpreter"
log_info "Open Interpreter installed"
echo ""
@ -32,17 +32,17 @@ else
fi
log_warn "Setting up environment variables..."
inject_env_vars_ssh "$DO_SERVER_IP" upload_file run_server \
"OPENROUTER_API_KEY=$OPENROUTER_API_KEY" \
"OPENAI_API_KEY=$OPENROUTER_API_KEY" \
inject_env_vars_ssh "${DO_SERVER_IP}" upload_file run_server \
"OPENROUTER_API_KEY=${OPENROUTER_API_KEY}" \
"OPENAI_API_KEY=${OPENROUTER_API_KEY}" \
"OPENAI_BASE_URL=https://openrouter.ai/api/v1"
echo ""
log_info "DigitalOcean droplet setup completed successfully!"
log_info "Droplet: $DROPLET_NAME (ID: $DO_DROPLET_ID, IP: $DO_SERVER_IP)"
log_info "Droplet: ${DROPLET_NAME} (ID: ${DO_DROPLET_ID}, IP: ${DO_SERVER_IP})"
echo ""
log_warn "Starting Open Interpreter..."
sleep 1
clear
interactive_session "$DO_SERVER_IP" "source ~/.zshrc && interpreter"
interactive_session "${DO_SERVER_IP}" "source ~/.zshrc && interpreter"

View file

@ -4,8 +4,8 @@ set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=digitalocean/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/digitalocean/lib/common.sh)"
fi
@ -21,18 +21,18 @@ ensure_ssh_key
# 3. Get droplet name and create droplet
DROPLET_NAME=$(get_server_name)
create_server "$DROPLET_NAME"
create_server "${DROPLET_NAME}"
# 4. Wait for SSH and cloud-init
verify_server_connectivity "$DO_SERVER_IP"
wait_for_cloud_init "$DO_SERVER_IP"
verify_server_connectivity "${DO_SERVER_IP}"
wait_for_cloud_init "${DO_SERVER_IP}"
# 5. Install Node.js deps and clone nanoclaw
log_warn "Installing tsx..."
run_server "$DO_SERVER_IP" "source ~/.bashrc && bun install -g tsx"
run_server "${DO_SERVER_IP}" "source ~/.bashrc && bun install -g tsx"
log_warn "Cloning and building nanoclaw..."
run_server "$DO_SERVER_IP" "git clone https://github.com/gavrielc/nanoclaw.git ~/nanoclaw && cd ~/nanoclaw && npm install && npm run build"
run_server "${DO_SERVER_IP}" "git clone https://github.com/gavrielc/nanoclaw.git ~/nanoclaw && cd ~/nanoclaw && npm install && npm run build"
log_info "NanoClaw installed"
# 6. Get OpenRouter API key
@ -44,30 +44,30 @@ else
fi
log_warn "Setting up environment variables..."
inject_env_vars_ssh "$DO_SERVER_IP" upload_file run_server \
"OPENROUTER_API_KEY=$OPENROUTER_API_KEY" \
"ANTHROPIC_API_KEY=$OPENROUTER_API_KEY" \
inject_env_vars_ssh "${DO_SERVER_IP}" upload_file run_server \
"OPENROUTER_API_KEY=${OPENROUTER_API_KEY}" \
"ANTHROPIC_API_KEY=${OPENROUTER_API_KEY}" \
"ANTHROPIC_BASE_URL=https://openrouter.ai/api"
# 8. Create nanoclaw .env file
log_warn "Configuring nanoclaw..."
DOTENV_TEMP=$(mktemp)
chmod 600 "$DOTENV_TEMP"
cat > "$DOTENV_TEMP" << EOF
chmod 600 "${DOTENV_TEMP}"
cat > "${DOTENV_TEMP}" << EOF
ANTHROPIC_API_KEY=${OPENROUTER_API_KEY}
EOF
upload_file "$DO_SERVER_IP" "$DOTENV_TEMP" "/root/nanoclaw/.env"
rm "$DOTENV_TEMP"
upload_file "${DO_SERVER_IP}" "${DOTENV_TEMP}" "/root/nanoclaw/.env"
rm "${DOTENV_TEMP}"
echo ""
log_info "DigitalOcean droplet setup completed successfully!"
log_info "Droplet: $DROPLET_NAME (ID: $DO_DROPLET_ID, IP: $DO_SERVER_IP)"
log_info "Droplet: ${DROPLET_NAME} (ID: ${DO_DROPLET_ID}, IP: ${DO_SERVER_IP})"
echo ""
# 9. Start nanoclaw
log_warn "Starting nanoclaw..."
log_warn "You will need to scan a WhatsApp QR code to authenticate."
echo ""
interactive_session "$DO_SERVER_IP" "cd ~/nanoclaw && source ~/.zshrc && npm run dev"
interactive_session "${DO_SERVER_IP}" "cd ~/nanoclaw && source ~/.zshrc && npm run dev"

View file

@ -4,8 +4,8 @@ set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=digitalocean/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/digitalocean/lib/common.sh)"
fi
@ -21,15 +21,15 @@ ensure_ssh_key
# 3. Get droplet name and create droplet
DROPLET_NAME=$(get_server_name)
create_server "$DROPLET_NAME"
create_server "${DROPLET_NAME}"
# 4. Wait for SSH and cloud-init
verify_server_connectivity "$DO_SERVER_IP"
wait_for_cloud_init "$DO_SERVER_IP"
verify_server_connectivity "${DO_SERVER_IP}"
wait_for_cloud_init "${DO_SERVER_IP}"
# 5. Install openclaw via bun
log_warn "Installing openclaw..."
run_server "$DO_SERVER_IP" "source ~/.bashrc && bun install -g openclaw"
run_server "${DO_SERVER_IP}" "source ~/.bashrc && bun install -g openclaw"
log_info "OpenClaw installed"
# 6. Get OpenRouter API key
@ -44,23 +44,23 @@ fi
MODEL_ID=$(get_model_id_interactive "openrouter/auto" "Openclaw") || exit 1
log_warn "Setting up environment variables..."
inject_env_vars_ssh "$DO_SERVER_IP" upload_file run_server \
"OPENROUTER_API_KEY=$OPENROUTER_API_KEY" \
"ANTHROPIC_API_KEY=$OPENROUTER_API_KEY" \
inject_env_vars_ssh "${DO_SERVER_IP}" upload_file run_server \
"OPENROUTER_API_KEY=${OPENROUTER_API_KEY}" \
"ANTHROPIC_API_KEY=${OPENROUTER_API_KEY}" \
"ANTHROPIC_BASE_URL=https://openrouter.ai/api"
# 9. Configure openclaw
setup_openclaw_config "$OPENROUTER_API_KEY" "$MODEL_ID" \
"upload_file $DO_SERVER_IP" \
"run_server $DO_SERVER_IP"
setup_openclaw_config "${OPENROUTER_API_KEY}" "${MODEL_ID}" \
"upload_file ${DO_SERVER_IP}" \
"run_server ${DO_SERVER_IP}"
echo ""
log_info "DigitalOcean droplet setup completed successfully!"
log_info "Droplet: $DROPLET_NAME (ID: $DO_DROPLET_ID, IP: $DO_SERVER_IP)"
log_info "Droplet: ${DROPLET_NAME} (ID: ${DO_DROPLET_ID}, IP: ${DO_SERVER_IP})"
echo ""
# 10. Start openclaw gateway in background and launch TUI
log_warn "Starting openclaw..."
run_server "$DO_SERVER_IP" "source ~/.zshrc && nohup openclaw gateway > /tmp/openclaw-gateway.log 2>&1 &"
run_server "${DO_SERVER_IP}" "source ~/.zshrc && nohup openclaw gateway > /tmp/openclaw-gateway.log 2>&1 &"
sleep 2
interactive_session "$DO_SERVER_IP" "source ~/.zshrc && openclaw tui"
interactive_session "${DO_SERVER_IP}" "source ~/.zshrc && openclaw tui"

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=e2b/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/e2b/lib/common.sh)"
fi
@ -19,7 +19,7 @@ ensure_e2b_token
# 2. Get sandbox name and create sandbox
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 3. Wait for base tools
wait_for_cloud_init
@ -48,19 +48,19 @@ MODEL_ID="${MODEL_ID:-openrouter/auto}"
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
EOF
upload_file "$ENV_TEMP" "/tmp/env_config"
upload_file "${ENV_TEMP}" "/tmp/env_config"
run_server "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
rm "${ENV_TEMP}"
echo ""
log_info "E2B sandbox setup completed successfully!"
log_info "Sandbox: $SERVER_NAME (ID: $E2B_SANDBOX_ID)"
log_info "Sandbox: ${SERVER_NAME} (ID: ${E2B_SANDBOX_ID})"
echo ""
# 8. Start Aider interactively

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=e2b/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/e2b/lib/common.sh)"
fi
@ -19,7 +19,7 @@ ensure_e2b_token
# 2. Get sandbox name and create sandbox
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 3. Wait for base tools
wait_for_cloud_init
@ -41,7 +41,7 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
@ -49,13 +49,13 @@ export OPENAI_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_BASE_URL="https://openrouter.ai/api/v1"
EOF
upload_file "$ENV_TEMP" "/tmp/env_config"
upload_file "${ENV_TEMP}" "/tmp/env_config"
run_server "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
rm "${ENV_TEMP}"
echo ""
log_info "E2B sandbox setup completed successfully!"
log_info "Sandbox: $SERVER_NAME (ID: $E2B_SANDBOX_ID)"
log_info "Sandbox: ${SERVER_NAME} (ID: ${E2B_SANDBOX_ID})"
echo ""
# 7. Start Amazon Q interactively

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=e2b/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/e2b/lib/common.sh)"
fi
@ -19,7 +19,7 @@ ensure_e2b_token
# 2. Get sandbox name and create sandbox
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 3. Wait for base tools
wait_for_cloud_init
@ -44,7 +44,7 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
@ -55,18 +55,18 @@ export CLAUDE_CODE_SKIP_ONBOARDING="1"
export CLAUDE_CODE_ENABLE_TELEMETRY="0"
EOF
upload_file "$ENV_TEMP" "/tmp/env_config"
upload_file "${ENV_TEMP}" "/tmp/env_config"
run_server "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
rm "${ENV_TEMP}"
# 7. Configure Claude Code settings
setup_claude_code_config "$OPENROUTER_API_KEY" \
setup_claude_code_config "${OPENROUTER_API_KEY}" \
"upload_file" \
"run_server"
echo ""
log_info "E2B sandbox setup completed successfully!"
log_info "Sandbox: $SERVER_NAME (ID: $E2B_SANDBOX_ID)"
log_info "Sandbox: ${SERVER_NAME} (ID: ${E2B_SANDBOX_ID})"
echo ""
# 8. Start Claude Code interactively

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=e2b/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/e2b/lib/common.sh)"
fi
@ -19,7 +19,7 @@ ensure_e2b_token
# 2. Get sandbox name and create sandbox
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 3. Wait for base tools
wait_for_cloud_init
@ -41,7 +41,7 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
@ -49,13 +49,13 @@ export OPENAI_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_BASE_URL="https://openrouter.ai/api/v1"
EOF
upload_file "$ENV_TEMP" "/tmp/env_config"
upload_file "${ENV_TEMP}" "/tmp/env_config"
run_server "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
rm "${ENV_TEMP}"
echo ""
log_info "E2B sandbox setup completed successfully!"
log_info "Sandbox: $SERVER_NAME (ID: $E2B_SANDBOX_ID)"
log_info "Sandbox: ${SERVER_NAME} (ID: ${E2B_SANDBOX_ID})"
echo ""
# 7. Start Cline interactively

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=e2b/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/e2b/lib/common.sh)"
fi
@ -19,7 +19,7 @@ ensure_e2b_token
# 2. Get sandbox name and create sandbox
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 3. Wait for base tools
wait_for_cloud_init
@ -41,7 +41,7 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
@ -49,13 +49,13 @@ export OPENAI_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_BASE_URL="https://openrouter.ai/api/v1"
EOF
upload_file "$ENV_TEMP" "/tmp/env_config"
upload_file "${ENV_TEMP}" "/tmp/env_config"
run_server "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
rm "${ENV_TEMP}"
echo ""
log_info "E2B sandbox setup completed successfully!"
log_info "Sandbox: $SERVER_NAME (ID: $E2B_SANDBOX_ID)"
log_info "Sandbox: ${SERVER_NAME} (ID: ${E2B_SANDBOX_ID})"
echo ""
# 7. Start Codex interactively

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=e2b/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/e2b/lib/common.sh)"
fi
@ -19,7 +19,7 @@ ensure_e2b_token
# 2. Get sandbox name and create sandbox
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 3. Wait for base tools
wait_for_cloud_init
@ -41,7 +41,7 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
@ -50,13 +50,13 @@ export OPENAI_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_BASE_URL="https://openrouter.ai/api/v1"
EOF
upload_file "$ENV_TEMP" "/tmp/env_config"
upload_file "${ENV_TEMP}" "/tmp/env_config"
run_server "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
rm "${ENV_TEMP}"
echo ""
log_info "E2B sandbox setup completed successfully!"
log_info "Sandbox: $SERVER_NAME (ID: $E2B_SANDBOX_ID)"
log_info "Sandbox: ${SERVER_NAME} (ID: ${E2B_SANDBOX_ID})"
echo ""
# 7. Start Gemini interactively

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=e2b/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/e2b/lib/common.sh)"
fi
@ -19,7 +19,7 @@ ensure_e2b_token
# 2. Get sandbox name and create sandbox
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 3. Wait for base tools
wait_for_cloud_init
@ -41,20 +41,20 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export GOOSE_PROVIDER=openrouter
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
EOF
upload_file "$ENV_TEMP" "/tmp/env_config"
upload_file "${ENV_TEMP}" "/tmp/env_config"
run_server "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
rm "${ENV_TEMP}"
echo ""
log_info "E2B sandbox setup completed successfully!"
log_info "Sandbox: $SERVER_NAME (ID: $E2B_SANDBOX_ID)"
log_info "Sandbox: ${SERVER_NAME} (ID: ${E2B_SANDBOX_ID})"
echo ""
# 7. Start Goose interactively

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=e2b/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/e2b/lib/common.sh)"
fi
@ -19,7 +19,7 @@ ensure_e2b_token
# 2. Get sandbox name and create sandbox
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 3. Wait for base tools
wait_for_cloud_init
@ -41,7 +41,7 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
@ -49,13 +49,13 @@ export OPENAI_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_BASE_URL="https://openrouter.ai/api/v1"
EOF
upload_file "$ENV_TEMP" "/tmp/env_config"
upload_file "${ENV_TEMP}" "/tmp/env_config"
run_server "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
rm "${ENV_TEMP}"
echo ""
log_info "E2B sandbox setup completed successfully!"
log_info "Sandbox: $SERVER_NAME (ID: $E2B_SANDBOX_ID)"
log_info "Sandbox: ${SERVER_NAME} (ID: ${E2B_SANDBOX_ID})"
echo ""
# 7. Start Open Interpreter interactively

View file

@ -98,8 +98,8 @@ wait_for_cloud_init() {
run_server "apt-get update -y && apt-get install -y curl unzip git zsh" >/dev/null 2>&1 || true
run_server "curl -fsSL https://bun.sh/install | bash" >/dev/null 2>&1 || true
run_server "curl -fsSL https://claude.ai/install.sh | bash" >/dev/null 2>&1 || true
run_server 'echo "export PATH=\"\$HOME/.claude/local/bin:\$HOME/.bun/bin:\$PATH\"" >> ~/.bashrc' >/dev/null 2>&1 || true
run_server 'echo "export PATH=\"\$HOME/.claude/local/bin:\$HOME/.bun/bin:\$PATH\"" >> ~/.zshrc' >/dev/null 2>&1 || true
run_server 'echo "export PATH=\"\${HOME}/.claude/local/bin:\${HOME}/.bun/bin:\${PATH}\"" >> ~/.bashrc' >/dev/null 2>&1 || true
run_server 'echo "export PATH=\"\${HOME}/.claude/local/bin:\${HOME}/.bun/bin:\${PATH}\"" >> ~/.zshrc' >/dev/null 2>&1 || true
log_info "Base tools installed"
}

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=e2b/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/e2b/lib/common.sh)"
fi
@ -19,7 +19,7 @@ ensure_e2b_token
# 2. Get sandbox name and create sandbox
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 3. Wait for base tools
wait_for_cloud_init
@ -44,7 +44,7 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
@ -52,24 +52,24 @@ export ANTHROPIC_API_KEY="${OPENROUTER_API_KEY}"
export ANTHROPIC_BASE_URL="https://openrouter.ai/api"
EOF
upload_file "$ENV_TEMP" "/tmp/env_config"
upload_file "${ENV_TEMP}" "/tmp/env_config"
run_server "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
rm "${ENV_TEMP}"
# 7. Create nanoclaw .env file
log_warn "Configuring nanoclaw..."
DOTENV_TEMP=$(mktemp)
cat > "$DOTENV_TEMP" << EOF
cat > "${DOTENV_TEMP}" << EOF
ANTHROPIC_API_KEY=${OPENROUTER_API_KEY}
EOF
upload_file "$DOTENV_TEMP" ~/nanoclaw/.env
rm "$DOTENV_TEMP"
upload_file "${DOTENV_TEMP}" ~/nanoclaw/.env
rm "${DOTENV_TEMP}"
echo ""
log_info "E2B sandbox setup completed successfully!"
log_info "Sandbox: $SERVER_NAME (ID: $E2B_SANDBOX_ID)"
log_info "Sandbox: ${SERVER_NAME} (ID: ${E2B_SANDBOX_ID})"
echo ""
# 8. Start nanoclaw

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=e2b/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/e2b/lib/common.sh)"
fi
@ -19,7 +19,7 @@ ensure_e2b_token
# 2. Get sandbox name and create sandbox
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 3. Wait for base tools
wait_for_cloud_init
@ -44,7 +44,7 @@ MODEL_ID=$(get_model_id_interactive "openrouter/auto" "Openclaw") || exit 1
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
@ -52,18 +52,18 @@ export ANTHROPIC_API_KEY="${OPENROUTER_API_KEY}"
export ANTHROPIC_BASE_URL="https://openrouter.ai/api"
EOF
upload_file "$ENV_TEMP" "/tmp/env_config"
upload_file "${ENV_TEMP}" "/tmp/env_config"
run_server "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
rm "${ENV_TEMP}"
# 8. Configure openclaw
setup_openclaw_config "$OPENROUTER_API_KEY" "$MODEL_ID" \
setup_openclaw_config "${OPENROUTER_API_KEY}" "${MODEL_ID}" \
upload_file \
run_server
echo ""
log_info "E2B sandbox setup completed successfully!"
log_info "Sandbox: $SERVER_NAME (ID: $E2B_SANDBOX_ID)"
log_info "Sandbox: ${SERVER_NAME} (ID: ${E2B_SANDBOX_ID})"
echo ""
# 9. Start openclaw gateway in background and launch TUI

114
fix_braces.py Normal file
View file

@ -0,0 +1,114 @@
#!/usr/bin/env python3
"""
Fix SC2250 shellcheck warnings by adding braces to variable references.
Converts $VAR to ${VAR} while preserving special variables.
"""
import re
import sys
import subprocess
from pathlib import Path
def should_skip_variable(var_name):
"""Check if a variable should not be braced."""
# Special shell variables that should remain unbraced
special_vars = {'@', '*', '!', '?', '$', '-', '#', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}
return var_name in special_vars
def add_braces_to_line(line):
"""Add braces to unbraced variable references in a line."""
# Skip comment lines
if line.lstrip().startswith('#'):
return line
result = []
i = 0
while i < len(line):
if line[i] == '$' and i + 1 < len(line):
# Check if already braced
if line[i + 1] == '{':
# Already braced, skip to closing brace
result.append(line[i:i+2])
i += 2
continue
# Check for special variables (single character)
if i + 1 < len(line) and line[i + 1] in '@*!?$-#0123456789':
result.append(line[i:i+2])
i += 2
continue
# Extract variable name (alphanumeric + underscore)
var_match = re.match(r'([A-Za-z_][A-Za-z0-9_]*)', line[i+1:])
if var_match:
var_name = var_match.group(1)
if not should_skip_variable(var_name):
# Add braces
result.append('${' + var_name + '}')
i += 1 + len(var_name)
continue
else:
result.append(line[i:i+1+len(var_name)])
i += 1 + len(var_name)
continue
result.append(line[i])
i += 1
return ''.join(result)
def fix_file(file_path):
"""Fix braces in a single file."""
try:
with open(file_path, 'r') as f:
lines = f.readlines()
fixed_lines = [add_braces_to_line(line) for line in lines]
# Check if anything changed
if lines == fixed_lines:
return False
# Write fixed content
with open(file_path, 'w') as f:
f.writelines(fixed_lines)
# Verify syntax
result = subprocess.run(['bash', '-n', str(file_path)],
capture_output=True, text=True)
if result.returncode != 0:
# Restore original if syntax check failed
with open(file_path, 'w') as f:
f.writelines(lines)
print(f" ✗ Syntax error in {file_path}, restored original")
return False
return True
except Exception as e:
print(f" ✗ Error processing {file_path}: {e}")
return False
def main():
spawn_dir = Path('/home/sprite/spawn')
shell_files = list(spawn_dir.rglob('*.sh'))
print(f"Found {len(shell_files)} shell scripts")
fixed_count = 0
for file_path in shell_files:
if fix_file(file_path):
print(f" ✓ Fixed: {file_path}")
fixed_count += 1
print(f"\nFixed {fixed_count} files")
# Count remaining warnings
print("\nChecking remaining SC2250 warnings...")
result = subprocess.run(
f"find {spawn_dir} -type f -name '*.sh' -exec shellcheck -f gcc {{}} \\; 2>&1 | grep -c SC2250 || true",
shell=True, capture_output=True, text=True
)
print(f"Remaining SC2250 warnings: {result.stdout.strip()}")
if __name__ == '__main__':
main()

46
fix_sc2250.sh Normal file
View file

@ -0,0 +1,46 @@
#!/bin/bash
# Script to fix SC2250 warnings by adding braces to variable references
set -euo pipefail
# Find all shell scripts and fix unbraced variables
# This script converts $VAR to ${VAR} but preserves special variables like $@ $* $$ $? $! $- $0-$9
find /home/sprite/spawn -type f -name "*.sh" | while read -r file; do
echo "Processing: ${file}"
# Create a backup
cp "${file}" "${file}.bak"
# Use sed to add braces to variables
# Pattern: Match $WORD where WORD is alphanumeric/underscore, not already in braces
# Exclude special variables: $@, $*, $!, $?, $$, $-, $#, $0-$9
sed -i -E '
# Skip lines that are comments
/^[[:space:]]*#/b
# Convert $VAR to ${VAR} in various contexts
# In double quotes: "$VAR" -> "${VAR}"
s/"\$([A-Za-z_][A-Za-z0-9_]*)([^A-Za-z0-9_{]|$)/"\${\1}\2/g
# In conditions and assignments: $VAR -> ${VAR}
s/([^$]|^)\$([A-Za-z_][A-Za-z0-9_]*)([^A-Za-z0-9_{]|$)/\1\${\2}\3/g
# At start of line: $VAR -> ${VAR}
s/^\$([A-Za-z_][A-Za-z0-9_]*)([^A-Za-z0-9_{]|$)/\${\1}\2/g
' "${file}"
# Verify the file still has valid syntax
if bash -n "${file}" 2>/dev/null; then
rm "${file}.bak"
echo " ✓ Fixed: ${file}"
else
# Restore backup if syntax check failed
mv "${file}.bak" "${file}"
echo " ✗ Syntax error, restored: ${file}"
fi
done
echo ""
echo "Done! Checking remaining SC2250 warnings..."
remaining=$(find /home/sprite/spawn -type f -name "*.sh" -exec shellcheck -f gcc {} \; 2>&1 | grep -c SC2250 || true)
echo "Remaining SC2250 warnings: ${remaining}"

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=gcp/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/gcp/lib/common.sh)"
fi
@ -21,15 +21,15 @@ ensure_ssh_key
# 3. Get server name and create server
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 4. Wait for SSH and cloud-init
verify_server_connectivity "$GCP_SERVER_IP"
wait_for_cloud_init "$GCP_SERVER_IP"
verify_server_connectivity "${GCP_SERVER_IP}"
wait_for_cloud_init "${GCP_SERVER_IP}"
# 5. Install Aider
log_warn "Installing Aider..."
run_server "$GCP_SERVER_IP" "pip install aider-chat 2>/dev/null || pip3 install aider-chat"
run_server "${GCP_SERVER_IP}" "pip install aider-chat 2>/dev/null || pip3 install aider-chat"
log_info "Aider installed"
# 6. Get OpenRouter API key
@ -51,23 +51,23 @@ MODEL_ID="${MODEL_ID:-openrouter/auto}"
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
EOF
upload_file "$GCP_SERVER_IP" "$ENV_TEMP" "/tmp/env_config"
run_server "$GCP_SERVER_IP" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
upload_file "${GCP_SERVER_IP}" "${ENV_TEMP}" "/tmp/env_config"
run_server "${GCP_SERVER_IP}" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "${ENV_TEMP}"
echo ""
log_info "GCP instance setup completed successfully!"
log_info "Instance: $GCP_INSTANCE_NAME_ACTUAL (Zone: $GCP_ZONE, IP: $GCP_SERVER_IP)"
log_info "Instance: ${GCP_INSTANCE_NAME_ACTUAL} (Zone: ${GCP_ZONE}, IP: ${GCP_SERVER_IP})"
echo ""
# 9. Start Aider interactively
log_warn "Starting Aider..."
sleep 1
clear
interactive_session "$GCP_SERVER_IP" "source ~/.zshrc && aider --model openrouter/${MODEL_ID}"
interactive_session "${GCP_SERVER_IP}" "source ~/.zshrc && aider --model openrouter/${MODEL_ID}"

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=gcp/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/gcp/lib/common.sh)"
fi
@ -21,15 +21,15 @@ ensure_ssh_key
# 3. Get server name and create server
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 4. Wait for SSH and cloud-init
verify_server_connectivity "$GCP_SERVER_IP"
wait_for_cloud_init "$GCP_SERVER_IP"
verify_server_connectivity "${GCP_SERVER_IP}"
wait_for_cloud_init "${GCP_SERVER_IP}"
# 5. Install Amazon Q CLI
log_warn "Installing Amazon Q CLI..."
run_server "$GCP_SERVER_IP" "curl -fsSL https://desktop-release.q.us-east-1.amazonaws.com/latest/amazon-q-cli-install.sh | bash"
run_server "${GCP_SERVER_IP}" "curl -fsSL https://desktop-release.q.us-east-1.amazonaws.com/latest/amazon-q-cli-install.sh | bash"
log_info "Amazon Q CLI installed"
# 6. Get OpenRouter API key
@ -44,7 +44,7 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
@ -52,17 +52,17 @@ export OPENAI_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_BASE_URL="https://openrouter.ai/api/v1"
EOF
upload_file "$GCP_SERVER_IP" "$ENV_TEMP" "/tmp/env_config"
run_server "$GCP_SERVER_IP" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
upload_file "${GCP_SERVER_IP}" "${ENV_TEMP}" "/tmp/env_config"
run_server "${GCP_SERVER_IP}" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "${ENV_TEMP}"
echo ""
log_info "GCP instance setup completed successfully!"
log_info "Instance: $GCP_INSTANCE_NAME_ACTUAL (Zone: $GCP_ZONE, IP: $GCP_SERVER_IP)"
log_info "Instance: ${GCP_INSTANCE_NAME_ACTUAL} (Zone: ${GCP_ZONE}, IP: ${GCP_SERVER_IP})"
echo ""
# 8. Start Amazon Q interactively
log_warn "Starting Amazon Q..."
sleep 1
clear
interactive_session "$GCP_SERVER_IP" "source ~/.zshrc && q chat"
interactive_session "${GCP_SERVER_IP}" "source ~/.zshrc && q chat"

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=gcp/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/gcp/lib/common.sh)"
fi
@ -21,17 +21,17 @@ ensure_ssh_key
# 3. Get server name and create server
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 4. Wait for SSH and cloud-init
verify_server_connectivity "$GCP_SERVER_IP"
wait_for_cloud_init "$GCP_SERVER_IP"
verify_server_connectivity "${GCP_SERVER_IP}"
wait_for_cloud_init "${GCP_SERVER_IP}"
# 5. Verify Claude Code is installed (fallback to manual install)
log_warn "Verifying Claude Code installation..."
if ! run_server "$GCP_SERVER_IP" "command -v claude" >/dev/null 2>&1; then
if ! run_server "${GCP_SERVER_IP}" "command -v claude" >/dev/null 2>&1; then
log_warn "Claude Code not found, installing manually..."
run_server "$GCP_SERVER_IP" "curl -fsSL https://claude.ai/install.sh | bash"
run_server "${GCP_SERVER_IP}" "curl -fsSL https://claude.ai/install.sh | bash"
fi
log_info "Claude Code is installed"
@ -47,7 +47,7 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
@ -58,22 +58,22 @@ export CLAUDE_CODE_SKIP_ONBOARDING="1"
export CLAUDE_CODE_ENABLE_TELEMETRY="0"
EOF
upload_file "$GCP_SERVER_IP" "$ENV_TEMP" "/tmp/env_config"
run_server "$GCP_SERVER_IP" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
upload_file "${GCP_SERVER_IP}" "${ENV_TEMP}" "/tmp/env_config"
run_server "${GCP_SERVER_IP}" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "${ENV_TEMP}"
# 8. Configure Claude Code settings
setup_claude_code_config "$OPENROUTER_API_KEY" \
"upload_file $GCP_SERVER_IP" \
"run_server $GCP_SERVER_IP"
setup_claude_code_config "${OPENROUTER_API_KEY}" \
"upload_file ${GCP_SERVER_IP}" \
"run_server ${GCP_SERVER_IP}"
echo ""
log_info "GCP instance setup completed successfully!"
log_info "Instance: $GCP_INSTANCE_NAME_ACTUAL (Zone: $GCP_ZONE, IP: $GCP_SERVER_IP)"
log_info "Instance: ${GCP_INSTANCE_NAME_ACTUAL} (Zone: ${GCP_ZONE}, IP: ${GCP_SERVER_IP})"
echo ""
# 9. Start Claude Code interactively
log_warn "Starting Claude Code..."
sleep 1
clear
interactive_session "$GCP_SERVER_IP" "source ~/.zshrc && claude"
interactive_session "${GCP_SERVER_IP}" "source ~/.zshrc && claude"

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=gcp/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/gcp/lib/common.sh)"
fi
@ -21,15 +21,15 @@ ensure_ssh_key
# 3. Get server name and create server
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 4. Wait for SSH and cloud-init
verify_server_connectivity "$GCP_SERVER_IP"
wait_for_cloud_init "$GCP_SERVER_IP"
verify_server_connectivity "${GCP_SERVER_IP}"
wait_for_cloud_init "${GCP_SERVER_IP}"
# 5. Install Cline
log_warn "Installing Cline..."
run_server "$GCP_SERVER_IP" "npm install -g cline"
run_server "${GCP_SERVER_IP}" "npm install -g cline"
log_info "Cline installed"
# 6. Get OpenRouter API key
@ -44,7 +44,7 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
@ -52,17 +52,17 @@ export OPENAI_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_BASE_URL="https://openrouter.ai/api/v1"
EOF
upload_file "$GCP_SERVER_IP" "$ENV_TEMP" "/tmp/env_config"
run_server "$GCP_SERVER_IP" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
upload_file "${GCP_SERVER_IP}" "${ENV_TEMP}" "/tmp/env_config"
run_server "${GCP_SERVER_IP}" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "${ENV_TEMP}"
echo ""
log_info "GCP instance setup completed successfully!"
log_info "Instance: $GCP_INSTANCE_NAME_ACTUAL (Zone: $GCP_ZONE, IP: $GCP_SERVER_IP)"
log_info "Instance: ${GCP_INSTANCE_NAME_ACTUAL} (Zone: ${GCP_ZONE}, IP: ${GCP_SERVER_IP})"
echo ""
# 8. Start Cline interactively
log_warn "Starting Cline..."
sleep 1
clear
interactive_session "$GCP_SERVER_IP" "source ~/.zshrc && cline"
interactive_session "${GCP_SERVER_IP}" "source ~/.zshrc && cline"

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=gcp/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/gcp/lib/common.sh)"
fi
@ -21,15 +21,15 @@ ensure_ssh_key
# 3. Get server name and create server
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 4. Wait for SSH and cloud-init
verify_server_connectivity "$GCP_SERVER_IP"
wait_for_cloud_init "$GCP_SERVER_IP"
verify_server_connectivity "${GCP_SERVER_IP}"
wait_for_cloud_init "${GCP_SERVER_IP}"
# 5. Install Codex CLI
log_warn "Installing Codex CLI..."
run_server "$GCP_SERVER_IP" "npm install -g @openai/codex"
run_server "${GCP_SERVER_IP}" "npm install -g @openai/codex"
log_info "Codex CLI installed"
# 6. Get OpenRouter API key
@ -44,7 +44,7 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
@ -52,17 +52,17 @@ export OPENAI_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_BASE_URL="https://openrouter.ai/api/v1"
EOF
upload_file "$GCP_SERVER_IP" "$ENV_TEMP" "/tmp/env_config"
run_server "$GCP_SERVER_IP" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
upload_file "${GCP_SERVER_IP}" "${ENV_TEMP}" "/tmp/env_config"
run_server "${GCP_SERVER_IP}" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "${ENV_TEMP}"
echo ""
log_info "GCP instance setup completed successfully!"
log_info "Instance: $GCP_INSTANCE_NAME_ACTUAL (Zone: $GCP_ZONE, IP: $GCP_SERVER_IP)"
log_info "Instance: ${GCP_INSTANCE_NAME_ACTUAL} (Zone: ${GCP_ZONE}, IP: ${GCP_SERVER_IP})"
echo ""
# 8. Start Codex interactively
log_warn "Starting Codex..."
sleep 1
clear
interactive_session "$GCP_SERVER_IP" "source ~/.zshrc && codex"
interactive_session "${GCP_SERVER_IP}" "source ~/.zshrc && codex"

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=gcp/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/gcp/lib/common.sh)"
fi
@ -21,15 +21,15 @@ ensure_ssh_key
# 3. Get server name and create server
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 4. Wait for SSH and cloud-init
verify_server_connectivity "$GCP_SERVER_IP"
wait_for_cloud_init "$GCP_SERVER_IP"
verify_server_connectivity "${GCP_SERVER_IP}"
wait_for_cloud_init "${GCP_SERVER_IP}"
# 5. Install Gemini CLI
log_warn "Installing Gemini CLI..."
run_server "$GCP_SERVER_IP" "npm install -g @google/gemini-cli"
run_server "${GCP_SERVER_IP}" "npm install -g @google/gemini-cli"
log_info "Gemini CLI installed"
# 6. Get OpenRouter API key
@ -44,7 +44,7 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
@ -53,17 +53,17 @@ export OPENAI_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_BASE_URL="https://openrouter.ai/api/v1"
EOF
upload_file "$GCP_SERVER_IP" "$ENV_TEMP" "/tmp/env_config"
run_server "$GCP_SERVER_IP" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
upload_file "${GCP_SERVER_IP}" "${ENV_TEMP}" "/tmp/env_config"
run_server "${GCP_SERVER_IP}" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "${ENV_TEMP}"
echo ""
log_info "GCP instance setup completed successfully!"
log_info "Instance: $GCP_INSTANCE_NAME_ACTUAL (Zone: $GCP_ZONE, IP: $GCP_SERVER_IP)"
log_info "Instance: ${GCP_INSTANCE_NAME_ACTUAL} (Zone: ${GCP_ZONE}, IP: ${GCP_SERVER_IP})"
echo ""
# 8. Start Gemini interactively
log_warn "Starting Gemini..."
sleep 1
clear
interactive_session "$GCP_SERVER_IP" "source ~/.zshrc && gemini"
interactive_session "${GCP_SERVER_IP}" "source ~/.zshrc && gemini"

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=gcp/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/gcp/lib/common.sh)"
fi
@ -21,15 +21,15 @@ ensure_ssh_key
# 3. Get server name and create server
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 4. Wait for SSH and cloud-init
verify_server_connectivity "$GCP_SERVER_IP"
wait_for_cloud_init "$GCP_SERVER_IP"
verify_server_connectivity "${GCP_SERVER_IP}"
wait_for_cloud_init "${GCP_SERVER_IP}"
# 5. Install Goose
log_warn "Installing Goose..."
run_server "$GCP_SERVER_IP" "CONFIGURE=false curl -fsSL https://github.com/block/goose/releases/latest/download/download_cli.sh | bash"
run_server "${GCP_SERVER_IP}" "CONFIGURE=false curl -fsSL https://github.com/block/goose/releases/latest/download/download_cli.sh | bash"
log_info "Goose installed"
# 6. Get OpenRouter API key
@ -44,24 +44,24 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export GOOSE_PROVIDER=openrouter
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
EOF
upload_file "$GCP_SERVER_IP" "$ENV_TEMP" "/tmp/env_config"
run_server "$GCP_SERVER_IP" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
upload_file "${GCP_SERVER_IP}" "${ENV_TEMP}" "/tmp/env_config"
run_server "${GCP_SERVER_IP}" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "${ENV_TEMP}"
echo ""
log_info "GCP instance setup completed successfully!"
log_info "Instance: $GCP_INSTANCE_NAME_ACTUAL (Zone: $GCP_ZONE, IP: $GCP_SERVER_IP)"
log_info "Instance: ${GCP_INSTANCE_NAME_ACTUAL} (Zone: ${GCP_ZONE}, IP: ${GCP_SERVER_IP})"
echo ""
# 8. Start Goose interactively
log_warn "Starting Goose..."
sleep 1
clear
interactive_session "$GCP_SERVER_IP" "source ~/.zshrc && goose"
interactive_session "${GCP_SERVER_IP}" "source ~/.zshrc && goose"

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=gcp/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/gcp/lib/common.sh)"
fi
@ -21,15 +21,15 @@ ensure_ssh_key
# 3. Get server name and create server
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 4. Wait for SSH and cloud-init
verify_server_connectivity "$GCP_SERVER_IP"
wait_for_cloud_init "$GCP_SERVER_IP"
verify_server_connectivity "${GCP_SERVER_IP}"
wait_for_cloud_init "${GCP_SERVER_IP}"
# 5. Install Open Interpreter
log_warn "Installing Open Interpreter..."
run_server "$GCP_SERVER_IP" "pip install open-interpreter 2>/dev/null || pip3 install open-interpreter"
run_server "${GCP_SERVER_IP}" "pip install open-interpreter 2>/dev/null || pip3 install open-interpreter"
log_info "Open Interpreter installed"
# 6. Get OpenRouter API key
@ -44,7 +44,7 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
@ -52,17 +52,17 @@ export OPENAI_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_BASE_URL="https://openrouter.ai/api/v1"
EOF
upload_file "$GCP_SERVER_IP" "$ENV_TEMP" "/tmp/env_config"
run_server "$GCP_SERVER_IP" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
upload_file "${GCP_SERVER_IP}" "${ENV_TEMP}" "/tmp/env_config"
run_server "${GCP_SERVER_IP}" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "${ENV_TEMP}"
echo ""
log_info "GCP instance setup completed successfully!"
log_info "Instance: $GCP_INSTANCE_NAME_ACTUAL (Zone: $GCP_ZONE, IP: $GCP_SERVER_IP)"
log_info "Instance: ${GCP_INSTANCE_NAME_ACTUAL} (Zone: ${GCP_ZONE}, IP: ${GCP_SERVER_IP})"
echo ""
# 8. Start Open Interpreter interactively
log_warn "Starting Open Interpreter..."
sleep 1
clear
interactive_session "$GCP_SERVER_IP" "source ~/.zshrc && interpreter"
interactive_session "${GCP_SERVER_IP}" "source ~/.zshrc && interpreter"

View file

@ -73,7 +73,7 @@ su - $(logname 2>/dev/null || echo "$(whoami)") -c 'curl -fsSL https://bun.sh/in
# Install Claude Code
su - $(logname 2>/dev/null || echo "$(whoami)") -c 'curl -fsSL https://claude.ai/install.sh | bash' || true
# Configure PATH for all users
echo 'export PATH="$HOME/.claude/local/bin:$HOME/.bun/bin:$PATH"' >> /etc/profile.d/spawn.sh
echo 'export PATH="${HOME}/.claude/local/bin:${HOME}/.bun/bin:${PATH}"' >> /etc/profile.d/spawn.sh
chmod +x /etc/profile.d/spawn.sh
touch /tmp/.cloud-init-complete
CLOUD_INIT_EOF

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=gcp/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/gcp/lib/common.sh)"
fi
@ -21,18 +21,18 @@ ensure_ssh_key
# 3. Get server name and create server
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 4. Wait for SSH and cloud-init
verify_server_connectivity "$GCP_SERVER_IP"
wait_for_cloud_init "$GCP_SERVER_IP"
verify_server_connectivity "${GCP_SERVER_IP}"
wait_for_cloud_init "${GCP_SERVER_IP}"
# 5. Install Node.js deps and clone nanoclaw
log_warn "Installing tsx..."
run_server "$GCP_SERVER_IP" "source ~/.bashrc && bun install -g tsx"
run_server "${GCP_SERVER_IP}" "source ~/.bashrc && bun install -g tsx"
log_warn "Cloning and building nanoclaw..."
run_server "$GCP_SERVER_IP" "git clone https://github.com/gavrielc/nanoclaw.git ~/nanoclaw && cd ~/nanoclaw && npm install && npm run build"
run_server "${GCP_SERVER_IP}" "git clone https://github.com/gavrielc/nanoclaw.git ~/nanoclaw && cd ~/nanoclaw && npm install && npm run build"
log_info "NanoClaw installed"
# 6. Get OpenRouter API key
@ -47,7 +47,7 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
@ -55,28 +55,28 @@ export ANTHROPIC_API_KEY="${OPENROUTER_API_KEY}"
export ANTHROPIC_BASE_URL="https://openrouter.ai/api"
EOF
upload_file "$GCP_SERVER_IP" "$ENV_TEMP" "/tmp/env_config"
run_server "$GCP_SERVER_IP" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
upload_file "${GCP_SERVER_IP}" "${ENV_TEMP}" "/tmp/env_config"
run_server "${GCP_SERVER_IP}" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "${ENV_TEMP}"
# 8. Create nanoclaw .env file
log_warn "Configuring nanoclaw..."
DOTENV_TEMP=$(mktemp)
cat > "$DOTENV_TEMP" << EOF
cat > "${DOTENV_TEMP}" << EOF
ANTHROPIC_API_KEY=${OPENROUTER_API_KEY}
EOF
upload_file "$GCP_SERVER_IP" "$DOTENV_TEMP" "$HOME/nanoclaw/.env"
rm "$DOTENV_TEMP"
upload_file "${GCP_SERVER_IP}" "${DOTENV_TEMP}" "${HOME}/nanoclaw/.env"
rm "${DOTENV_TEMP}"
echo ""
log_info "GCP instance setup completed successfully!"
log_info "Instance: $GCP_INSTANCE_NAME_ACTUAL (Zone: $GCP_ZONE, IP: $GCP_SERVER_IP)"
log_info "Instance: ${GCP_INSTANCE_NAME_ACTUAL} (Zone: ${GCP_ZONE}, IP: ${GCP_SERVER_IP})"
echo ""
# 9. Start nanoclaw
log_warn "Starting nanoclaw..."
log_warn "You will need to scan a WhatsApp QR code to authenticate."
echo ""
interactive_session "$GCP_SERVER_IP" "cd ~/nanoclaw && source ~/.zshrc && npm run dev"
interactive_session "${GCP_SERVER_IP}" "cd ~/nanoclaw && source ~/.zshrc && npm run dev"

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=gcp/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/gcp/lib/common.sh)"
fi
@ -21,15 +21,15 @@ ensure_ssh_key
# 3. Get server name and create server
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 4. Wait for SSH and cloud-init
verify_server_connectivity "$GCP_SERVER_IP"
wait_for_cloud_init "$GCP_SERVER_IP"
verify_server_connectivity "${GCP_SERVER_IP}"
wait_for_cloud_init "${GCP_SERVER_IP}"
# 5. Install openclaw via bun
log_warn "Installing openclaw..."
run_server "$GCP_SERVER_IP" "source ~/.bashrc && bun install -g openclaw"
run_server "${GCP_SERVER_IP}" "source ~/.bashrc && bun install -g openclaw"
log_info "OpenClaw installed"
# 6. Get OpenRouter API key
@ -45,23 +45,23 @@ MODEL_ID=$(get_model_id_interactive "openrouter/auto" "Openclaw") || exit 1
# 8. Inject environment variables into ~/.zshrc
log_warn "Setting up environment variables..."
inject_env_vars_ssh "$GCP_SERVER_IP" upload_file run_server \
"OPENROUTER_API_KEY=$OPENROUTER_API_KEY" \
"ANTHROPIC_API_KEY=$OPENROUTER_API_KEY" \
inject_env_vars_ssh "${GCP_SERVER_IP}" upload_file run_server \
"OPENROUTER_API_KEY=${OPENROUTER_API_KEY}" \
"ANTHROPIC_API_KEY=${OPENROUTER_API_KEY}" \
"ANTHROPIC_BASE_URL=https://openrouter.ai/api"
# 9. Configure openclaw
setup_openclaw_config "$OPENROUTER_API_KEY" "$MODEL_ID" \
"upload_file $GCP_SERVER_IP" \
"run_server $GCP_SERVER_IP"
setup_openclaw_config "${OPENROUTER_API_KEY}" "${MODEL_ID}" \
"upload_file ${GCP_SERVER_IP}" \
"run_server ${GCP_SERVER_IP}"
echo ""
log_info "GCP instance setup completed successfully!"
log_info "Instance: $GCP_INSTANCE_NAME_ACTUAL (Zone: $GCP_ZONE, IP: $GCP_SERVER_IP)"
log_info "Instance: ${GCP_INSTANCE_NAME_ACTUAL} (Zone: ${GCP_ZONE}, IP: ${GCP_SERVER_IP})"
echo ""
# 10. Start openclaw gateway in background and launch TUI
log_warn "Starting openclaw..."
run_server "$GCP_SERVER_IP" "source ~/.zshrc && nohup openclaw gateway > /tmp/openclaw-gateway.log 2>&1 &"
run_server "${GCP_SERVER_IP}" "source ~/.zshrc && nohup openclaw gateway > /tmp/openclaw-gateway.log 2>&1 &"
sleep 2
interactive_session "$GCP_SERVER_IP" "source ~/.zshrc && openclaw tui"
interactive_session "${GCP_SERVER_IP}" "source ~/.zshrc && openclaw tui"

View file

@ -4,8 +4,8 @@ set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=hetzner/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/hetzner/lib/common.sh)"
fi
@ -21,20 +21,20 @@ ensure_ssh_key
# 3. Get server name and create server
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 4. Wait for SSH and cloud-init
verify_server_connectivity "$HETZNER_SERVER_IP"
wait_for_cloud_init "$HETZNER_SERVER_IP"
verify_server_connectivity "${HETZNER_SERVER_IP}"
wait_for_cloud_init "${HETZNER_SERVER_IP}"
# 5. Install Aider
log_warn "Installing Aider..."
run_server "$HETZNER_SERVER_IP" "pip install aider-chat 2>/dev/null || pip3 install aider-chat"
run_server "${HETZNER_SERVER_IP}" "pip install aider-chat 2>/dev/null || pip3 install aider-chat"
# Verify installation succeeded
if ! run_server "$HETZNER_SERVER_IP" "command -v aider &> /dev/null && aider --version &> /dev/null"; then
if ! run_server "${HETZNER_SERVER_IP}" "command -v aider &> /dev/null && aider --version &> /dev/null"; then
log_error "Aider installation verification failed"
log_error "The 'aider' command is not available or not working properly on server $HETZNER_SERVER_IP"
log_error "The 'aider' command is not available or not working properly on server ${HETZNER_SERVER_IP}"
exit 1
fi
log_info "Aider installation verified successfully"
@ -51,16 +51,16 @@ fi
MODEL_ID=$(get_model_id_interactive "openrouter/auto" "Aider") || exit 1
log_warn "Setting up environment variables..."
inject_env_vars_ssh "$HETZNER_SERVER_IP" upload_file run_server \
"OPENROUTER_API_KEY=$OPENROUTER_API_KEY"
inject_env_vars_ssh "${HETZNER_SERVER_IP}" upload_file run_server \
"OPENROUTER_API_KEY=${OPENROUTER_API_KEY}"
echo ""
log_info "Hetzner server setup completed successfully!"
log_info "Server: $SERVER_NAME (ID: $HETZNER_SERVER_ID, IP: $HETZNER_SERVER_IP)"
log_info "Server: ${SERVER_NAME} (ID: ${HETZNER_SERVER_ID}, IP: ${HETZNER_SERVER_IP})"
echo ""
# 9. Start Aider interactively
log_warn "Starting Aider..."
sleep 1
clear
interactive_session "$HETZNER_SERVER_IP" "source ~/.zshrc && aider --model openrouter/${MODEL_ID}"
interactive_session "${HETZNER_SERVER_IP}" "source ~/.zshrc && aider --model openrouter/${MODEL_ID}"

View file

@ -1,10 +1,10 @@
#!/bin/bash
set -e
set -eo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=hetzner/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/hetzner/lib/common.sh)"
fi
@ -16,12 +16,12 @@ ensure_hcloud_token
ensure_ssh_key
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
verify_server_connectivity "$HETZNER_SERVER_IP"
wait_for_cloud_init "$HETZNER_SERVER_IP"
create_server "${SERVER_NAME}"
verify_server_connectivity "${HETZNER_SERVER_IP}"
wait_for_cloud_init "${HETZNER_SERVER_IP}"
log_warn "Installing Amazon Q CLI..."
run_server "$HETZNER_SERVER_IP" "curl -fsSL https://desktop-release.q.us-east-1.amazonaws.com/latest/amazon-q-cli-install.sh | bash"
run_server "${HETZNER_SERVER_IP}" "curl -fsSL https://desktop-release.q.us-east-1.amazonaws.com/latest/amazon-q-cli-install.sh | bash"
log_info "Amazon Q CLI installed"
echo ""
@ -33,23 +33,23 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_BASE_URL="https://openrouter.ai/api/v1"
EOF
upload_file "$HETZNER_SERVER_IP" "$ENV_TEMP" "/tmp/env_config"
run_server "$HETZNER_SERVER_IP" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
upload_file "${HETZNER_SERVER_IP}" "${ENV_TEMP}" "/tmp/env_config"
run_server "${HETZNER_SERVER_IP}" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "${ENV_TEMP}"
echo ""
log_info "Hetzner server setup completed successfully!"
log_info "Server: $SERVER_NAME (ID: $HETZNER_SERVER_ID, IP: $HETZNER_SERVER_IP)"
log_info "Server: ${SERVER_NAME} (ID: ${HETZNER_SERVER_ID}, IP: ${HETZNER_SERVER_IP})"
echo ""
log_warn "Starting Amazon Q..."
sleep 1
clear
interactive_session "$HETZNER_SERVER_IP" "source ~/.zshrc && q chat"
interactive_session "${HETZNER_SERVER_IP}" "source ~/.zshrc && q chat"

View file

@ -4,8 +4,8 @@ set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=hetzner/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/hetzner/lib/common.sh)"
fi
@ -21,23 +21,23 @@ ensure_ssh_key
# 3. Get server name and create server
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 4. Wait for SSH and cloud-init
verify_server_connectivity "$HETZNER_SERVER_IP"
wait_for_cloud_init "$HETZNER_SERVER_IP"
verify_server_connectivity "${HETZNER_SERVER_IP}"
wait_for_cloud_init "${HETZNER_SERVER_IP}"
# 5. Verify Claude Code is installed (fallback to manual install)
log_warn "Verifying Claude Code installation..."
if ! run_server "$HETZNER_SERVER_IP" "command -v claude" >/dev/null 2>&1; then
if ! run_server "${HETZNER_SERVER_IP}" "command -v claude" >/dev/null 2>&1; then
log_warn "Claude Code not found, installing manually..."
run_server "$HETZNER_SERVER_IP" "curl -fsSL https://claude.ai/install.sh | bash"
run_server "${HETZNER_SERVER_IP}" "curl -fsSL https://claude.ai/install.sh | bash"
fi
# Verify installation succeeded
if ! run_server "$HETZNER_SERVER_IP" "command -v claude &> /dev/null && claude --version &> /dev/null"; then
if ! run_server "${HETZNER_SERVER_IP}" "command -v claude &> /dev/null && claude --version &> /dev/null"; then
log_error "Claude Code installation verification failed"
log_error "The 'claude' command is not available or not working properly on server $HETZNER_SERVER_IP"
log_error "The 'claude' command is not available or not working properly on server ${HETZNER_SERVER_IP}"
exit 1
fi
log_info "Claude Code installation verified successfully"
@ -51,26 +51,26 @@ else
fi
log_warn "Setting up environment variables..."
inject_env_vars_ssh "$HETZNER_SERVER_IP" upload_file run_server \
"OPENROUTER_API_KEY=$OPENROUTER_API_KEY" \
inject_env_vars_ssh "${HETZNER_SERVER_IP}" upload_file run_server \
"OPENROUTER_API_KEY=${OPENROUTER_API_KEY}" \
"ANTHROPIC_BASE_URL=https://openrouter.ai/api" \
"ANTHROPIC_AUTH_TOKEN=$OPENROUTER_API_KEY" \
"ANTHROPIC_AUTH_TOKEN=${OPENROUTER_API_KEY}" \
"ANTHROPIC_API_KEY=" \
"CLAUDE_CODE_SKIP_ONBOARDING=1" \
"CLAUDE_CODE_ENABLE_TELEMETRY=0"
# 8. Configure Claude Code settings
setup_claude_code_config "$OPENROUTER_API_KEY" \
"upload_file $HETZNER_SERVER_IP" \
"run_server $HETZNER_SERVER_IP"
setup_claude_code_config "${OPENROUTER_API_KEY}" \
"upload_file ${HETZNER_SERVER_IP}" \
"run_server ${HETZNER_SERVER_IP}"
echo ""
log_info "Hetzner server setup completed successfully!"
log_info "Server: $SERVER_NAME (ID: $HETZNER_SERVER_ID, IP: $HETZNER_SERVER_IP)"
log_info "Server: ${SERVER_NAME} (ID: ${HETZNER_SERVER_ID}, IP: ${HETZNER_SERVER_IP})"
echo ""
# 9. Start Claude Code interactively
log_warn "Starting Claude Code..."
sleep 1
clear
interactive_session "$HETZNER_SERVER_IP" "source ~/.zshrc && claude"
interactive_session "${HETZNER_SERVER_IP}" "source ~/.zshrc && claude"

View file

@ -1,10 +1,10 @@
#!/bin/bash
set -e
set -eo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=hetzner/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/hetzner/lib/common.sh)"
fi
@ -16,12 +16,12 @@ ensure_hcloud_token
ensure_ssh_key
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
verify_server_connectivity "$HETZNER_SERVER_IP"
wait_for_cloud_init "$HETZNER_SERVER_IP"
create_server "${SERVER_NAME}"
verify_server_connectivity "${HETZNER_SERVER_IP}"
wait_for_cloud_init "${HETZNER_SERVER_IP}"
log_warn "Installing Cline..."
run_server "$HETZNER_SERVER_IP" "npm install -g cline"
run_server "${HETZNER_SERVER_IP}" "npm install -g cline"
log_info "Cline installed"
echo ""
@ -33,23 +33,23 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_BASE_URL="https://openrouter.ai/api/v1"
EOF
upload_file "$HETZNER_SERVER_IP" "$ENV_TEMP" "/tmp/env_config"
run_server "$HETZNER_SERVER_IP" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
upload_file "${HETZNER_SERVER_IP}" "${ENV_TEMP}" "/tmp/env_config"
run_server "${HETZNER_SERVER_IP}" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "${ENV_TEMP}"
echo ""
log_info "Hetzner server setup completed successfully!"
log_info "Server: $SERVER_NAME (ID: $HETZNER_SERVER_ID, IP: $HETZNER_SERVER_IP)"
log_info "Server: ${SERVER_NAME} (ID: ${HETZNER_SERVER_ID}, IP: ${HETZNER_SERVER_IP})"
echo ""
log_warn "Starting Cline..."
sleep 1
clear
interactive_session "$HETZNER_SERVER_IP" "source ~/.zshrc && cline"
interactive_session "${HETZNER_SERVER_IP}" "source ~/.zshrc && cline"

View file

@ -3,8 +3,8 @@ set -eo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=hetzner/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/hetzner/lib/common.sh)"
fi
@ -16,12 +16,12 @@ ensure_hcloud_token
ensure_ssh_key
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
verify_server_connectivity "$HETZNER_SERVER_IP"
wait_for_cloud_init "$HETZNER_SERVER_IP"
create_server "${SERVER_NAME}"
verify_server_connectivity "${HETZNER_SERVER_IP}"
wait_for_cloud_init "${HETZNER_SERVER_IP}"
log_warn "Installing Codex CLI..."
run_server "$HETZNER_SERVER_IP" "npm install -g @openai/codex"
run_server "${HETZNER_SERVER_IP}" "npm install -g @openai/codex"
log_info "Codex CLI installed"
echo ""
@ -32,17 +32,17 @@ else
fi
log_warn "Setting up environment variables..."
inject_env_vars_ssh "$HETZNER_SERVER_IP" upload_file run_server \
"OPENROUTER_API_KEY=$OPENROUTER_API_KEY" \
"OPENAI_API_KEY=$OPENROUTER_API_KEY" \
inject_env_vars_ssh "${HETZNER_SERVER_IP}" upload_file run_server \
"OPENROUTER_API_KEY=${OPENROUTER_API_KEY}" \
"OPENAI_API_KEY=${OPENROUTER_API_KEY}" \
"OPENAI_BASE_URL=https://openrouter.ai/api/v1"
echo ""
log_info "Hetzner server setup completed successfully!"
log_info "Server: $SERVER_NAME (ID: $HETZNER_SERVER_ID, IP: $HETZNER_SERVER_IP)"
log_info "Server: ${SERVER_NAME} (ID: ${HETZNER_SERVER_ID}, IP: ${HETZNER_SERVER_IP})"
echo ""
log_warn "Starting Codex..."
sleep 1
clear
interactive_session "$HETZNER_SERVER_IP" "source ~/.zshrc && codex"
interactive_session "${HETZNER_SERVER_IP}" "source ~/.zshrc && codex"

View file

@ -1,10 +1,10 @@
#!/bin/bash
set -e
set -eo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=hetzner/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/hetzner/lib/common.sh)"
fi
@ -16,12 +16,12 @@ ensure_hcloud_token
ensure_ssh_key
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
verify_server_connectivity "$HETZNER_SERVER_IP"
wait_for_cloud_init "$HETZNER_SERVER_IP"
create_server "${SERVER_NAME}"
verify_server_connectivity "${HETZNER_SERVER_IP}"
wait_for_cloud_init "${HETZNER_SERVER_IP}"
log_warn "Installing Gemini CLI..."
run_server "$HETZNER_SERVER_IP" "npm install -g @google/gemini-cli"
run_server "${HETZNER_SERVER_IP}" "npm install -g @google/gemini-cli"
log_info "Gemini CLI installed"
echo ""
@ -33,7 +33,7 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
@ -41,16 +41,16 @@ export GEMINI_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_BASE_URL="https://openrouter.ai/api/v1"
EOF
upload_file "$HETZNER_SERVER_IP" "$ENV_TEMP" "/tmp/env_config"
run_server "$HETZNER_SERVER_IP" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
upload_file "${HETZNER_SERVER_IP}" "${ENV_TEMP}" "/tmp/env_config"
run_server "${HETZNER_SERVER_IP}" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "${ENV_TEMP}"
echo ""
log_info "Hetzner server setup completed successfully!"
log_info "Server: $SERVER_NAME (ID: $HETZNER_SERVER_ID, IP: $HETZNER_SERVER_IP)"
log_info "Server: ${SERVER_NAME} (ID: ${HETZNER_SERVER_ID}, IP: ${HETZNER_SERVER_IP})"
echo ""
log_warn "Starting Gemini..."
sleep 1
clear
interactive_session "$HETZNER_SERVER_IP" "source ~/.zshrc && gemini"
interactive_session "${HETZNER_SERVER_IP}" "source ~/.zshrc && gemini"

View file

@ -4,8 +4,8 @@ set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=hetzner/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/hetzner/lib/common.sh)"
fi
@ -21,20 +21,20 @@ ensure_ssh_key
# 3. Get server name and create server
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 4. Wait for SSH and cloud-init
verify_server_connectivity "$HETZNER_SERVER_IP"
wait_for_cloud_init "$HETZNER_SERVER_IP"
verify_server_connectivity "${HETZNER_SERVER_IP}"
wait_for_cloud_init "${HETZNER_SERVER_IP}"
# 5. Install Goose
log_warn "Installing Goose..."
run_server "$HETZNER_SERVER_IP" "CONFIGURE=false curl -fsSL https://github.com/block/goose/releases/latest/download/download_cli.sh | bash"
run_server "${HETZNER_SERVER_IP}" "CONFIGURE=false curl -fsSL https://github.com/block/goose/releases/latest/download/download_cli.sh | bash"
# Verify installation succeeded
if ! run_server "$HETZNER_SERVER_IP" "command -v goose &> /dev/null && goose --version &> /dev/null"; then
if ! run_server "${HETZNER_SERVER_IP}" "command -v goose &> /dev/null && goose --version &> /dev/null"; then
log_error "Goose installation verification failed"
log_error "The 'goose' command is not available or not working properly on server $HETZNER_SERVER_IP"
log_error "The 'goose' command is not available or not working properly on server ${HETZNER_SERVER_IP}"
exit 1
fi
log_info "Goose installation verified successfully"
@ -48,17 +48,17 @@ else
fi
log_warn "Setting up environment variables..."
inject_env_vars_ssh "$HETZNER_SERVER_IP" upload_file run_server \
inject_env_vars_ssh "${HETZNER_SERVER_IP}" upload_file run_server \
"GOOSE_PROVIDER=openrouter" \
"OPENROUTER_API_KEY=$OPENROUTER_API_KEY"
"OPENROUTER_API_KEY=${OPENROUTER_API_KEY}"
echo ""
log_info "Hetzner server setup completed successfully!"
log_info "Server: $SERVER_NAME (ID: $HETZNER_SERVER_ID, IP: $HETZNER_SERVER_IP)"
log_info "Server: ${SERVER_NAME} (ID: ${HETZNER_SERVER_ID}, IP: ${HETZNER_SERVER_IP})"
echo ""
# 8. Start Goose interactively
log_warn "Starting Goose..."
sleep 1
clear
interactive_session "$HETZNER_SERVER_IP" "source ~/.zshrc && goose"
interactive_session "${HETZNER_SERVER_IP}" "source ~/.zshrc && goose"

View file

@ -3,8 +3,8 @@ set -eo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=hetzner/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/hetzner/lib/common.sh)"
fi
@ -16,12 +16,12 @@ ensure_hcloud_token
ensure_ssh_key
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
verify_server_connectivity "$HETZNER_SERVER_IP"
wait_for_cloud_init "$HETZNER_SERVER_IP"
create_server "${SERVER_NAME}"
verify_server_connectivity "${HETZNER_SERVER_IP}"
wait_for_cloud_init "${HETZNER_SERVER_IP}"
log_warn "Installing Open Interpreter..."
run_server "$HETZNER_SERVER_IP" "pip install open-interpreter 2>/dev/null || pip3 install open-interpreter"
run_server "${HETZNER_SERVER_IP}" "pip install open-interpreter 2>/dev/null || pip3 install open-interpreter"
log_info "Open Interpreter installed"
echo ""
@ -32,17 +32,17 @@ else
fi
log_warn "Setting up environment variables..."
inject_env_vars_ssh "$HETZNER_SERVER_IP" upload_file run_server \
"OPENROUTER_API_KEY=$OPENROUTER_API_KEY" \
"OPENAI_API_KEY=$OPENROUTER_API_KEY" \
inject_env_vars_ssh "${HETZNER_SERVER_IP}" upload_file run_server \
"OPENROUTER_API_KEY=${OPENROUTER_API_KEY}" \
"OPENAI_API_KEY=${OPENROUTER_API_KEY}" \
"OPENAI_BASE_URL=https://openrouter.ai/api/v1"
echo ""
log_info "Hetzner server setup completed successfully!"
log_info "Server: $SERVER_NAME (ID: $HETZNER_SERVER_ID, IP: $HETZNER_SERVER_IP)"
log_info "Server: ${SERVER_NAME} (ID: ${HETZNER_SERVER_ID}, IP: ${HETZNER_SERVER_IP})"
echo ""
log_warn "Starting Open Interpreter..."
sleep 1
clear
interactive_session "$HETZNER_SERVER_IP" "source ~/.zshrc && interpreter"
interactive_session "${HETZNER_SERVER_IP}" "source ~/.zshrc && interpreter"

View file

@ -4,8 +4,8 @@ set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=hetzner/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/hetzner/lib/common.sh)"
fi
@ -21,18 +21,18 @@ ensure_ssh_key
# 3. Get server name and create server
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 4. Wait for SSH and cloud-init
verify_server_connectivity "$HETZNER_SERVER_IP"
wait_for_cloud_init "$HETZNER_SERVER_IP"
verify_server_connectivity "${HETZNER_SERVER_IP}"
wait_for_cloud_init "${HETZNER_SERVER_IP}"
# 5. Install Node.js deps and clone nanoclaw
log_warn "Installing tsx..."
run_server "$HETZNER_SERVER_IP" "source ~/.bashrc && bun install -g tsx"
run_server "${HETZNER_SERVER_IP}" "source ~/.bashrc && bun install -g tsx"
log_warn "Cloning and building nanoclaw..."
run_server "$HETZNER_SERVER_IP" "git clone https://github.com/gavrielc/nanoclaw.git ~/nanoclaw && cd ~/nanoclaw && npm install && npm run build"
run_server "${HETZNER_SERVER_IP}" "git clone https://github.com/gavrielc/nanoclaw.git ~/nanoclaw && cd ~/nanoclaw && npm install && npm run build"
log_info "NanoClaw installed"
# 6. Get OpenRouter API key
@ -44,30 +44,30 @@ else
fi
log_warn "Setting up environment variables..."
inject_env_vars_ssh "$HETZNER_SERVER_IP" upload_file run_server \
"OPENROUTER_API_KEY=$OPENROUTER_API_KEY" \
"ANTHROPIC_API_KEY=$OPENROUTER_API_KEY" \
inject_env_vars_ssh "${HETZNER_SERVER_IP}" upload_file run_server \
"OPENROUTER_API_KEY=${OPENROUTER_API_KEY}" \
"ANTHROPIC_API_KEY=${OPENROUTER_API_KEY}" \
"ANTHROPIC_BASE_URL=https://openrouter.ai/api"
# 8. Create nanoclaw .env file
log_warn "Configuring nanoclaw..."
DOTENV_TEMP=$(mktemp)
chmod 600 "$DOTENV_TEMP"
cat > "$DOTENV_TEMP" << EOF
chmod 600 "${DOTENV_TEMP}"
cat > "${DOTENV_TEMP}" << EOF
ANTHROPIC_API_KEY=${OPENROUTER_API_KEY}
EOF
upload_file "$HETZNER_SERVER_IP" "$DOTENV_TEMP" "/root/nanoclaw/.env"
rm "$DOTENV_TEMP"
upload_file "${HETZNER_SERVER_IP}" "${DOTENV_TEMP}" "/root/nanoclaw/.env"
rm "${DOTENV_TEMP}"
echo ""
log_info "Hetzner server setup completed successfully!"
log_info "Server: $SERVER_NAME (ID: $HETZNER_SERVER_ID, IP: $HETZNER_SERVER_IP)"
log_info "Server: ${SERVER_NAME} (ID: ${HETZNER_SERVER_ID}, IP: ${HETZNER_SERVER_IP})"
echo ""
# 9. Start nanoclaw
log_warn "Starting nanoclaw..."
log_warn "You will need to scan a WhatsApp QR code to authenticate."
echo ""
interactive_session "$HETZNER_SERVER_IP" "cd ~/nanoclaw && source ~/.zshrc && npm run dev"
interactive_session "${HETZNER_SERVER_IP}" "cd ~/nanoclaw && source ~/.zshrc && npm run dev"

View file

@ -4,8 +4,8 @@ set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=hetzner/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/hetzner/lib/common.sh)"
fi
@ -21,15 +21,15 @@ ensure_ssh_key
# 3. Get server name and create server
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 4. Wait for SSH and cloud-init
verify_server_connectivity "$HETZNER_SERVER_IP"
wait_for_cloud_init "$HETZNER_SERVER_IP"
verify_server_connectivity "${HETZNER_SERVER_IP}"
wait_for_cloud_init "${HETZNER_SERVER_IP}"
# 5. Install openclaw via bun
log_warn "Installing openclaw..."
run_server "$HETZNER_SERVER_IP" "source ~/.bashrc && bun install -g openclaw"
run_server "${HETZNER_SERVER_IP}" "source ~/.bashrc && bun install -g openclaw"
log_info "OpenClaw installed"
# 6. Get OpenRouter API key
@ -44,23 +44,23 @@ fi
MODEL_ID=$(get_model_id_interactive "openrouter/auto" "Openclaw") || exit 1
log_warn "Setting up environment variables..."
inject_env_vars_ssh "$HETZNER_SERVER_IP" upload_file run_server \
"OPENROUTER_API_KEY=$OPENROUTER_API_KEY" \
"ANTHROPIC_API_KEY=$OPENROUTER_API_KEY" \
inject_env_vars_ssh "${HETZNER_SERVER_IP}" upload_file run_server \
"OPENROUTER_API_KEY=${OPENROUTER_API_KEY}" \
"ANTHROPIC_API_KEY=${OPENROUTER_API_KEY}" \
"ANTHROPIC_BASE_URL=https://openrouter.ai/api"
# 9. Configure openclaw
setup_openclaw_config "$OPENROUTER_API_KEY" "$MODEL_ID" \
"upload_file $HETZNER_SERVER_IP" \
"run_server $HETZNER_SERVER_IP"
setup_openclaw_config "${OPENROUTER_API_KEY}" "${MODEL_ID}" \
"upload_file ${HETZNER_SERVER_IP}" \
"run_server ${HETZNER_SERVER_IP}"
echo ""
log_info "Hetzner server setup completed successfully!"
log_info "Server: $SERVER_NAME (ID: $HETZNER_SERVER_ID, IP: $HETZNER_SERVER_IP)"
log_info "Server: ${SERVER_NAME} (ID: ${HETZNER_SERVER_ID}, IP: ${HETZNER_SERVER_IP})"
echo ""
# 10. Start openclaw gateway in background and launch TUI
log_warn "Starting openclaw..."
run_server "$HETZNER_SERVER_IP" "source ~/.zshrc && nohup openclaw gateway > /tmp/openclaw-gateway.log 2>&1 &"
run_server "${HETZNER_SERVER_IP}" "source ~/.zshrc && nohup openclaw gateway > /tmp/openclaw-gateway.log 2>&1 &"
sleep 2
interactive_session "$HETZNER_SERVER_IP" "source ~/.zshrc && openclaw tui"
interactive_session "${HETZNER_SERVER_IP}" "source ~/.zshrc && openclaw tui"

View file

@ -19,7 +19,7 @@
set -uo pipefail
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MANIFEST="$REPO_ROOT/manifest.json"
MANIFEST="${REPO_ROOT}/manifest.json"
MODE="${1:-once}"
RED='\033[0;31m'
@ -42,8 +42,8 @@ if ! command -v python3 &>/dev/null; then
exit 1
fi
if [[ ! -f "$MANIFEST" ]]; then
log_error "manifest.json not found at $MANIFEST"
if [[ ! -f "${MANIFEST}" ]]; then
log_error "manifest.json not found at ${MANIFEST}"
exit 1
fi
@ -54,7 +54,7 @@ export CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1
get_matrix_summary() {
python3 -c "
import json
m = json.load(open('$MANIFEST'))
m = json.load(open('${MANIFEST}'))
agents = list(m['agents'].keys())
clouds = list(m['clouds'].keys())
gaps = [k for k, v in m.get('matrix', {}).items() if v == 'missing']
@ -73,7 +73,7 @@ print(f'Clouds: {', '.join(clouds)}')
count_gaps() {
python3 -c "
import json
m = json.load(open('$MANIFEST'))
m = json.load(open('${MANIFEST}'))
print(sum(1 for v in m.get('matrix', {}).values() if v == 'missing'))
"
}
@ -89,7 +89,7 @@ build_team_prompt() {
You are the lead of a spawn improvement team. Read CLAUDE.md and manifest.json first.
Current state:
$summary
${summary}
Your job: coordinate teammates to expand the spawn matrix. Use delegate mode — do NOT implement anything yourself. Only coordinate.
@ -130,22 +130,22 @@ build_single_prompt() {
local gap
gap=$(python3 -c "
import json
m = json.load(open('$MANIFEST'))
m = json.load(open('${MANIFEST}'))
for key, status in m.get('matrix', {}).items():
if status == 'missing':
print(key)
break
")
if [[ -n "$gap" && "$MODE" != "--discover" ]]; then
if [[ -n "${gap}" && "${MODE}" != "--discover" ]]; then
local cloud="${gap%%/*}"
local agent="${gap##*/}"
cat <<EOF
Read CLAUDE.md and manifest.json. Implement "$cloud/$agent.sh":
1. Read $cloud/lib/common.sh for cloud primitives
2. Read an existing $agent.sh on another cloud for the install pattern
3. Write $cloud/$agent.sh combining the two
4. Update manifest.json to mark "$cloud/$agent" as "implemented"
Read CLAUDE.md and manifest.json. Implement "${cloud}/${agent}.sh":
1. Read ${cloud}/lib/common.sh for cloud primitives
2. Read an existing ${agent}.sh on another cloud for the install pattern
3. Write ${cloud}/${agent}.sh combining the two
4. Update manifest.json to mark "${cloud}/${agent}" as "implemented"
5. Update README.md
6. Commit
OpenRouter injection is mandatory.
@ -162,7 +162,7 @@ run_team_cycle() {
prompt=$(build_team_prompt)
log_info "Launching agent team..."
echo ""
(cd "$REPO_ROOT" && claude -p "$prompt" --dangerously-skip-permissions)
(cd "${REPO_ROOT}" && claude -p "${prompt}" --dangerously-skip-permissions)
return $?
}
@ -171,23 +171,23 @@ run_single_cycle() {
prompt=$(build_single_prompt)
log_info "Launching single agent..."
echo ""
(cd "$REPO_ROOT" && claude --print -p "$prompt")
(cd "${REPO_ROOT}" && claude --print -p "${prompt}")
return $?
}
# Main
log_info "Spawn Improvement System"
log_info "Mode: $MODE"
log_info "Mode: ${MODE}"
get_matrix_summary
echo ""
case "$MODE" in
case "${MODE}" in
--loop)
cycle=1
while true; do
log_info "=== Team Cycle $cycle ==="
log_info "=== Team Cycle ${cycle} ==="
run_team_cycle || {
log_error "Cycle $cycle failed, pausing 10s..."
log_error "Cycle ${cycle} failed, pausing 10s..."
sleep 10
}
((cycle++))

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=lambda/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/lambda/lib/common.sh)"
fi
@ -21,15 +21,15 @@ ensure_ssh_key
# 3. Get instance name and create server
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 4. Wait for SSH and cloud-init
verify_server_connectivity "$LAMBDA_SERVER_IP"
wait_for_cloud_init "$LAMBDA_SERVER_IP"
verify_server_connectivity "${LAMBDA_SERVER_IP}"
wait_for_cloud_init "${LAMBDA_SERVER_IP}"
# 5. Install Aider
log_warn "Installing Aider..."
run_server "$LAMBDA_SERVER_IP" "pip install aider-chat 2>/dev/null || pip3 install aider-chat"
run_server "${LAMBDA_SERVER_IP}" "pip install aider-chat 2>/dev/null || pip3 install aider-chat"
log_info "Aider installed"
# 6. Get OpenRouter API key
@ -51,23 +51,23 @@ MODEL_ID="${MODEL_ID:-openrouter/auto}"
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
EOF
upload_file "$LAMBDA_SERVER_IP" "$ENV_TEMP" "/tmp/env_config"
run_server "$LAMBDA_SERVER_IP" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
upload_file "${LAMBDA_SERVER_IP}" "${ENV_TEMP}" "/tmp/env_config"
run_server "${LAMBDA_SERVER_IP}" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "${ENV_TEMP}"
echo ""
log_info "Lambda Cloud instance setup completed successfully!"
log_info "Instance: $SERVER_NAME (IP: $LAMBDA_SERVER_IP)"
log_info "Instance: ${SERVER_NAME} (IP: ${LAMBDA_SERVER_IP})"
echo ""
# 9. Start Aider interactively
log_warn "Starting Aider..."
sleep 1
clear
interactive_session "$LAMBDA_SERVER_IP" "source ~/.zshrc && aider --model openrouter/${MODEL_ID}"
interactive_session "${LAMBDA_SERVER_IP}" "source ~/.zshrc && aider --model openrouter/${MODEL_ID}"

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=lambda/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/lambda/lib/common.sh)"
fi
@ -21,15 +21,15 @@ ensure_ssh_key
# 3. Get instance name and create server
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 4. Wait for SSH and cloud-init
verify_server_connectivity "$LAMBDA_SERVER_IP"
wait_for_cloud_init "$LAMBDA_SERVER_IP"
verify_server_connectivity "${LAMBDA_SERVER_IP}"
wait_for_cloud_init "${LAMBDA_SERVER_IP}"
# 5. Install Amazon Q CLI
log_warn "Installing Amazon Q CLI..."
run_server "$LAMBDA_SERVER_IP" "curl -fsSL https://desktop-release.q.us-east-1.amazonaws.com/latest/amazon-q-cli-install.sh | bash"
run_server "${LAMBDA_SERVER_IP}" "curl -fsSL https://desktop-release.q.us-east-1.amazonaws.com/latest/amazon-q-cli-install.sh | bash"
log_info "Amazon Q CLI installed"
# 6. Get OpenRouter API key
@ -44,7 +44,7 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
@ -52,17 +52,17 @@ export OPENAI_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_BASE_URL="https://openrouter.ai/api/v1"
EOF
upload_file "$LAMBDA_SERVER_IP" "$ENV_TEMP" "/tmp/env_config"
run_server "$LAMBDA_SERVER_IP" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
upload_file "${LAMBDA_SERVER_IP}" "${ENV_TEMP}" "/tmp/env_config"
run_server "${LAMBDA_SERVER_IP}" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "${ENV_TEMP}"
echo ""
log_info "Lambda Cloud instance setup completed successfully!"
log_info "Instance: $SERVER_NAME (IP: $LAMBDA_SERVER_IP)"
log_info "Instance: ${SERVER_NAME} (IP: ${LAMBDA_SERVER_IP})"
echo ""
# 8. Start Amazon Q interactively
log_warn "Starting Amazon Q..."
sleep 1
clear
interactive_session "$LAMBDA_SERVER_IP" "source ~/.zshrc && q chat"
interactive_session "${LAMBDA_SERVER_IP}" "source ~/.zshrc && q chat"

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=lambda/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/lambda/lib/common.sh)"
fi
@ -21,17 +21,17 @@ ensure_ssh_key
# 3. Get instance name and create server
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 4. Wait for SSH and cloud-init
verify_server_connectivity "$LAMBDA_SERVER_IP"
wait_for_cloud_init "$LAMBDA_SERVER_IP"
verify_server_connectivity "${LAMBDA_SERVER_IP}"
wait_for_cloud_init "${LAMBDA_SERVER_IP}"
# 5. Verify Claude Code is installed (fallback to manual install)
log_warn "Verifying Claude Code installation..."
if ! run_server "$LAMBDA_SERVER_IP" "command -v claude" >/dev/null 2>&1; then
if ! run_server "${LAMBDA_SERVER_IP}" "command -v claude" >/dev/null 2>&1; then
log_warn "Claude Code not found, installing manually..."
run_server "$LAMBDA_SERVER_IP" "curl -fsSL https://claude.ai/install.sh | bash"
run_server "${LAMBDA_SERVER_IP}" "curl -fsSL https://claude.ai/install.sh | bash"
fi
log_info "Claude Code is installed"
@ -47,7 +47,7 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
@ -58,22 +58,22 @@ export CLAUDE_CODE_SKIP_ONBOARDING="1"
export CLAUDE_CODE_ENABLE_TELEMETRY="0"
EOF
upload_file "$LAMBDA_SERVER_IP" "$ENV_TEMP" "/tmp/env_config"
run_server "$LAMBDA_SERVER_IP" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
upload_file "${LAMBDA_SERVER_IP}" "${ENV_TEMP}" "/tmp/env_config"
run_server "${LAMBDA_SERVER_IP}" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "${ENV_TEMP}"
# 8. Configure Claude Code settings
setup_claude_code_config "$OPENROUTER_API_KEY" \
"upload_file $LAMBDA_SERVER_IP" \
"run_server $LAMBDA_SERVER_IP"
setup_claude_code_config "${OPENROUTER_API_KEY}" \
"upload_file ${LAMBDA_SERVER_IP}" \
"run_server ${LAMBDA_SERVER_IP}"
echo ""
log_info "Lambda Cloud instance setup completed successfully!"
log_info "Instance: $SERVER_NAME (IP: $LAMBDA_SERVER_IP)"
log_info "Instance: ${SERVER_NAME} (IP: ${LAMBDA_SERVER_IP})"
echo ""
# 9. Start Claude Code interactively
log_warn "Starting Claude Code..."
sleep 1
clear
interactive_session "$LAMBDA_SERVER_IP" "source ~/.zshrc && claude"
interactive_session "${LAMBDA_SERVER_IP}" "source ~/.zshrc && claude"

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=lambda/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/lambda/lib/common.sh)"
fi
@ -21,15 +21,15 @@ ensure_ssh_key
# 3. Get instance name and create server
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 4. Wait for SSH and cloud-init
verify_server_connectivity "$LAMBDA_SERVER_IP"
wait_for_cloud_init "$LAMBDA_SERVER_IP"
verify_server_connectivity "${LAMBDA_SERVER_IP}"
wait_for_cloud_init "${LAMBDA_SERVER_IP}"
# 5. Install Cline
log_warn "Installing Cline..."
run_server "$LAMBDA_SERVER_IP" "npm install -g cline"
run_server "${LAMBDA_SERVER_IP}" "npm install -g cline"
log_info "Cline installed"
# 6. Get OpenRouter API key
@ -44,7 +44,7 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
@ -52,17 +52,17 @@ export OPENAI_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_BASE_URL="https://openrouter.ai/api/v1"
EOF
upload_file "$LAMBDA_SERVER_IP" "$ENV_TEMP" "/tmp/env_config"
run_server "$LAMBDA_SERVER_IP" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
upload_file "${LAMBDA_SERVER_IP}" "${ENV_TEMP}" "/tmp/env_config"
run_server "${LAMBDA_SERVER_IP}" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "${ENV_TEMP}"
echo ""
log_info "Lambda Cloud instance setup completed successfully!"
log_info "Instance: $SERVER_NAME (IP: $LAMBDA_SERVER_IP)"
log_info "Instance: ${SERVER_NAME} (IP: ${LAMBDA_SERVER_IP})"
echo ""
# 8. Start Cline interactively
log_warn "Starting Cline..."
sleep 1
clear
interactive_session "$LAMBDA_SERVER_IP" "source ~/.zshrc && cline"
interactive_session "${LAMBDA_SERVER_IP}" "source ~/.zshrc && cline"

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=lambda/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/lambda/lib/common.sh)"
fi
@ -21,15 +21,15 @@ ensure_ssh_key
# 3. Get instance name and create server
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 4. Wait for SSH and cloud-init
verify_server_connectivity "$LAMBDA_SERVER_IP"
wait_for_cloud_init "$LAMBDA_SERVER_IP"
verify_server_connectivity "${LAMBDA_SERVER_IP}"
wait_for_cloud_init "${LAMBDA_SERVER_IP}"
# 5. Install Codex CLI
log_warn "Installing Codex CLI..."
run_server "$LAMBDA_SERVER_IP" "npm install -g @openai/codex"
run_server "${LAMBDA_SERVER_IP}" "npm install -g @openai/codex"
log_info "Codex CLI installed"
# 6. Get OpenRouter API key
@ -44,7 +44,7 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
@ -52,17 +52,17 @@ export OPENAI_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_BASE_URL="https://openrouter.ai/api/v1"
EOF
upload_file "$LAMBDA_SERVER_IP" "$ENV_TEMP" "/tmp/env_config"
run_server "$LAMBDA_SERVER_IP" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
upload_file "${LAMBDA_SERVER_IP}" "${ENV_TEMP}" "/tmp/env_config"
run_server "${LAMBDA_SERVER_IP}" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "${ENV_TEMP}"
echo ""
log_info "Lambda Cloud instance setup completed successfully!"
log_info "Instance: $SERVER_NAME (IP: $LAMBDA_SERVER_IP)"
log_info "Instance: ${SERVER_NAME} (IP: ${LAMBDA_SERVER_IP})"
echo ""
# 8. Start Codex interactively
log_warn "Starting Codex..."
sleep 1
clear
interactive_session "$LAMBDA_SERVER_IP" "source ~/.zshrc && codex"
interactive_session "${LAMBDA_SERVER_IP}" "source ~/.zshrc && codex"

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=lambda/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/lambda/lib/common.sh)"
fi
@ -21,15 +21,15 @@ ensure_ssh_key
# 3. Get instance name and create server
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 4. Wait for SSH and cloud-init
verify_server_connectivity "$LAMBDA_SERVER_IP"
wait_for_cloud_init "$LAMBDA_SERVER_IP"
verify_server_connectivity "${LAMBDA_SERVER_IP}"
wait_for_cloud_init "${LAMBDA_SERVER_IP}"
# 5. Install Gemini CLI
log_warn "Installing Gemini CLI..."
run_server "$LAMBDA_SERVER_IP" "npm install -g @google/gemini-cli"
run_server "${LAMBDA_SERVER_IP}" "npm install -g @google/gemini-cli"
log_info "Gemini CLI installed"
# 6. Get OpenRouter API key
@ -44,7 +44,7 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
@ -53,17 +53,17 @@ export OPENAI_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_BASE_URL="https://openrouter.ai/api/v1"
EOF
upload_file "$LAMBDA_SERVER_IP" "$ENV_TEMP" "/tmp/env_config"
run_server "$LAMBDA_SERVER_IP" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
upload_file "${LAMBDA_SERVER_IP}" "${ENV_TEMP}" "/tmp/env_config"
run_server "${LAMBDA_SERVER_IP}" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "${ENV_TEMP}"
echo ""
log_info "Lambda Cloud instance setup completed successfully!"
log_info "Instance: $SERVER_NAME (IP: $LAMBDA_SERVER_IP)"
log_info "Instance: ${SERVER_NAME} (IP: ${LAMBDA_SERVER_IP})"
echo ""
# 8. Start Gemini interactively
log_warn "Starting Gemini..."
sleep 1
clear
interactive_session "$LAMBDA_SERVER_IP" "source ~/.zshrc && gemini"
interactive_session "${LAMBDA_SERVER_IP}" "source ~/.zshrc && gemini"

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=lambda/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/lambda/lib/common.sh)"
fi
@ -21,15 +21,15 @@ ensure_ssh_key
# 3. Get instance name and create server
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 4. Wait for SSH and cloud-init
verify_server_connectivity "$LAMBDA_SERVER_IP"
wait_for_cloud_init "$LAMBDA_SERVER_IP"
verify_server_connectivity "${LAMBDA_SERVER_IP}"
wait_for_cloud_init "${LAMBDA_SERVER_IP}"
# 5. Install Goose
log_warn "Installing Goose..."
run_server "$LAMBDA_SERVER_IP" "CONFIGURE=false curl -fsSL https://github.com/block/goose/releases/latest/download/download_cli.sh | bash"
run_server "${LAMBDA_SERVER_IP}" "CONFIGURE=false curl -fsSL https://github.com/block/goose/releases/latest/download/download_cli.sh | bash"
log_info "Goose installed"
# 6. Get OpenRouter API key
@ -44,24 +44,24 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export GOOSE_PROVIDER=openrouter
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
EOF
upload_file "$LAMBDA_SERVER_IP" "$ENV_TEMP" "/tmp/env_config"
run_server "$LAMBDA_SERVER_IP" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
upload_file "${LAMBDA_SERVER_IP}" "${ENV_TEMP}" "/tmp/env_config"
run_server "${LAMBDA_SERVER_IP}" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "${ENV_TEMP}"
echo ""
log_info "Lambda Cloud instance setup completed successfully!"
log_info "Instance: $SERVER_NAME (IP: $LAMBDA_SERVER_IP)"
log_info "Instance: ${SERVER_NAME} (IP: ${LAMBDA_SERVER_IP})"
echo ""
# 8. Start Goose interactively
log_warn "Starting Goose..."
sleep 1
clear
interactive_session "$LAMBDA_SERVER_IP" "source ~/.zshrc && goose"
interactive_session "${LAMBDA_SERVER_IP}" "source ~/.zshrc && goose"

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=lambda/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/lambda/lib/common.sh)"
fi
@ -21,15 +21,15 @@ ensure_ssh_key
# 3. Get instance name and create server
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 4. Wait for SSH and cloud-init
verify_server_connectivity "$LAMBDA_SERVER_IP"
wait_for_cloud_init "$LAMBDA_SERVER_IP"
verify_server_connectivity "${LAMBDA_SERVER_IP}"
wait_for_cloud_init "${LAMBDA_SERVER_IP}"
# 5. Install Open Interpreter
log_warn "Installing Open Interpreter..."
run_server "$LAMBDA_SERVER_IP" "pip install open-interpreter 2>/dev/null || pip3 install open-interpreter"
run_server "${LAMBDA_SERVER_IP}" "pip install open-interpreter 2>/dev/null || pip3 install open-interpreter"
log_info "Open Interpreter installed"
# 6. Get OpenRouter API key
@ -44,7 +44,7 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
@ -52,17 +52,17 @@ export OPENAI_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_BASE_URL="https://openrouter.ai/api/v1"
EOF
upload_file "$LAMBDA_SERVER_IP" "$ENV_TEMP" "/tmp/env_config"
run_server "$LAMBDA_SERVER_IP" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
upload_file "${LAMBDA_SERVER_IP}" "${ENV_TEMP}" "/tmp/env_config"
run_server "${LAMBDA_SERVER_IP}" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "${ENV_TEMP}"
echo ""
log_info "Lambda Cloud instance setup completed successfully!"
log_info "Instance: $SERVER_NAME (IP: $LAMBDA_SERVER_IP)"
log_info "Instance: ${SERVER_NAME} (IP: ${LAMBDA_SERVER_IP})"
echo ""
# 8. Start Open Interpreter interactively
log_warn "Starting Open Interpreter..."
sleep 1
clear
interactive_session "$LAMBDA_SERVER_IP" "source ~/.zshrc && interpreter"
interactive_session "${LAMBDA_SERVER_IP}" "source ~/.zshrc && interpreter"

View file

@ -200,7 +200,7 @@ wait_for_cloud_init() {
# Configure PATH
# shellcheck disable=SC2086
ssh ${SSH_OPTS} "ubuntu@${ip}" "echo 'export PATH=\"\$HOME/.claude/local/bin:\$HOME/.bun/bin:\$PATH\"' >> ~/.bashrc && echo 'export PATH=\"\$HOME/.claude/local/bin:\$HOME/.bun/bin:\$PATH\"' >> ~/.zshrc" >/dev/null 2>&1
ssh ${SSH_OPTS} "ubuntu@${ip}" "echo 'export PATH=\"\${HOME}/.claude/local/bin:\${HOME}/.bun/bin:\${PATH}\"' >> ~/.bashrc && echo 'export PATH=\"\${HOME}/.claude/local/bin:\${HOME}/.bun/bin:\${PATH}\"' >> ~/.zshrc" >/dev/null 2>&1
log_info "Base tools installed"
}

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=lambda/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/lambda/lib/common.sh)"
fi
@ -21,18 +21,18 @@ ensure_ssh_key
# 3. Get instance name and create server
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 4. Wait for SSH and cloud-init
verify_server_connectivity "$LAMBDA_SERVER_IP"
wait_for_cloud_init "$LAMBDA_SERVER_IP"
verify_server_connectivity "${LAMBDA_SERVER_IP}"
wait_for_cloud_init "${LAMBDA_SERVER_IP}"
# 5. Install Node.js deps and clone nanoclaw
log_warn "Installing tsx..."
run_server "$LAMBDA_SERVER_IP" "source ~/.bashrc && bun install -g tsx"
run_server "${LAMBDA_SERVER_IP}" "source ~/.bashrc && bun install -g tsx"
log_warn "Cloning and building nanoclaw..."
run_server "$LAMBDA_SERVER_IP" "git clone https://github.com/gavrielc/nanoclaw.git ~/nanoclaw && cd ~/nanoclaw && npm install && npm run build"
run_server "${LAMBDA_SERVER_IP}" "git clone https://github.com/gavrielc/nanoclaw.git ~/nanoclaw && cd ~/nanoclaw && npm install && npm run build"
log_info "NanoClaw installed"
# 6. Get OpenRouter API key
@ -47,7 +47,7 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
@ -55,28 +55,28 @@ export ANTHROPIC_API_KEY="${OPENROUTER_API_KEY}"
export ANTHROPIC_BASE_URL="https://openrouter.ai/api"
EOF
upload_file "$LAMBDA_SERVER_IP" "$ENV_TEMP" "/tmp/env_config"
run_server "$LAMBDA_SERVER_IP" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
upload_file "${LAMBDA_SERVER_IP}" "${ENV_TEMP}" "/tmp/env_config"
run_server "${LAMBDA_SERVER_IP}" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "${ENV_TEMP}"
# 8. Create nanoclaw .env file
log_warn "Configuring nanoclaw..."
DOTENV_TEMP=$(mktemp)
cat > "$DOTENV_TEMP" << EOF
cat > "${DOTENV_TEMP}" << EOF
ANTHROPIC_API_KEY=${OPENROUTER_API_KEY}
EOF
upload_file "$LAMBDA_SERVER_IP" "$DOTENV_TEMP" "/home/ubuntu/nanoclaw/.env"
rm "$DOTENV_TEMP"
upload_file "${LAMBDA_SERVER_IP}" "${DOTENV_TEMP}" "/home/ubuntu/nanoclaw/.env"
rm "${DOTENV_TEMP}"
echo ""
log_info "Lambda Cloud instance setup completed successfully!"
log_info "Instance: $SERVER_NAME (IP: $LAMBDA_SERVER_IP)"
log_info "Instance: ${SERVER_NAME} (IP: ${LAMBDA_SERVER_IP})"
echo ""
# 9. Start nanoclaw
log_warn "Starting nanoclaw..."
log_warn "You will need to scan a WhatsApp QR code to authenticate."
echo ""
interactive_session "$LAMBDA_SERVER_IP" "cd ~/nanoclaw && source ~/.zshrc && npm run dev"
interactive_session "${LAMBDA_SERVER_IP}" "cd ~/nanoclaw && source ~/.zshrc && npm run dev"

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=lambda/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/lambda/lib/common.sh)"
fi
@ -21,15 +21,15 @@ ensure_ssh_key
# 3. Get instance name and create server
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
create_server "${SERVER_NAME}"
# 4. Wait for SSH and cloud-init
verify_server_connectivity "$LAMBDA_SERVER_IP"
wait_for_cloud_init "$LAMBDA_SERVER_IP"
verify_server_connectivity "${LAMBDA_SERVER_IP}"
wait_for_cloud_init "${LAMBDA_SERVER_IP}"
# 5. Install openclaw via bun
log_warn "Installing openclaw..."
run_server "$LAMBDA_SERVER_IP" "source ~/.bashrc && bun install -g openclaw"
run_server "${LAMBDA_SERVER_IP}" "source ~/.bashrc && bun install -g openclaw"
log_info "OpenClaw installed"
# 6. Get OpenRouter API key
@ -45,23 +45,23 @@ MODEL_ID=$(get_model_id_interactive "openrouter/auto" "Openclaw") || exit 1
# 8. Inject environment variables into ~/.zshrc
log_warn "Setting up environment variables..."
inject_env_vars_ssh "$LAMBDA_SERVER_IP" upload_file run_server \
"OPENROUTER_API_KEY=$OPENROUTER_API_KEY" \
"ANTHROPIC_API_KEY=$OPENROUTER_API_KEY" \
inject_env_vars_ssh "${LAMBDA_SERVER_IP}" upload_file run_server \
"OPENROUTER_API_KEY=${OPENROUTER_API_KEY}" \
"ANTHROPIC_API_KEY=${OPENROUTER_API_KEY}" \
"ANTHROPIC_BASE_URL=https://openrouter.ai/api"
# 9. Configure openclaw
setup_openclaw_config "$OPENROUTER_API_KEY" "$MODEL_ID" \
"upload_file $LAMBDA_SERVER_IP" \
"run_server $LAMBDA_SERVER_IP"
setup_openclaw_config "${OPENROUTER_API_KEY}" "${MODEL_ID}" \
"upload_file ${LAMBDA_SERVER_IP}" \
"run_server ${LAMBDA_SERVER_IP}"
echo ""
log_info "Lambda Cloud instance setup completed successfully!"
log_info "Instance: $SERVER_NAME (IP: $LAMBDA_SERVER_IP)"
log_info "Instance: ${SERVER_NAME} (IP: ${LAMBDA_SERVER_IP})"
echo ""
# 10. Start openclaw gateway in background and launch TUI
log_warn "Starting openclaw..."
run_server "$LAMBDA_SERVER_IP" "source ~/.zshrc && nohup openclaw gateway > /tmp/openclaw-gateway.log 2>&1 &"
run_server "${LAMBDA_SERVER_IP}" "source ~/.zshrc && nohup openclaw gateway > /tmp/openclaw-gateway.log 2>&1 &"
sleep 2
interactive_session "$LAMBDA_SERVER_IP" "source ~/.zshrc && openclaw tui"
interactive_session "${LAMBDA_SERVER_IP}" "source ~/.zshrc && openclaw tui"

View file

@ -2,30 +2,30 @@
set -eo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=linode/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then source "${SCRIPT_DIR}/lib/common.sh"
else eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/linode/lib/common.sh)"; fi
log_info "Aider on Linode"
echo ""
ensure_linode_token
ensure_ssh_key
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
verify_server_connectivity "$LINODE_SERVER_IP"
wait_for_cloud_init "$LINODE_SERVER_IP"
create_server "${SERVER_NAME}"
verify_server_connectivity "${LINODE_SERVER_IP}"
wait_for_cloud_init "${LINODE_SERVER_IP}"
log_warn "Installing Aider..."
run_server "$LINODE_SERVER_IP" "pip install aider-chat 2>/dev/null || pip3 install aider-chat"
run_server "${LINODE_SERVER_IP}" "pip install aider-chat 2>/dev/null || pip3 install aider-chat"
log_info "Aider installed"
echo ""
if [[ -n "${OPENROUTER_API_KEY:-}" ]]; then log_info "Using OpenRouter API key from environment"
else OPENROUTER_API_KEY=$(get_openrouter_api_key_oauth 5180); fi
MODEL_ID=$(get_model_id_interactive "openrouter/auto" "Aider") || exit 1
log_warn "Setting up environment variables..."
inject_env_vars_ssh "$LINODE_SERVER_IP" upload_file run_server \
"OPENROUTER_API_KEY=$OPENROUTER_API_KEY"
inject_env_vars_ssh "${LINODE_SERVER_IP}" upload_file run_server \
"OPENROUTER_API_KEY=${OPENROUTER_API_KEY}"
echo ""
log_info "Linode setup completed successfully!"
echo ""
log_warn "Starting Aider..."
sleep 1
clear
interactive_session "$LINODE_SERVER_IP" "source ~/.zshrc && aider --model openrouter/${MODEL_ID}"
interactive_session "${LINODE_SERVER_IP}" "source ~/.zshrc && aider --model openrouter/${MODEL_ID}"

View file

@ -1,39 +1,39 @@
#!/bin/bash
set -e
set -eo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=linode/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then source "${SCRIPT_DIR}/lib/common.sh"
else eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/linode/lib/common.sh)"; fi
log_info "Amazon Q on Linode"
echo ""
ensure_linode_token
ensure_ssh_key
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
verify_server_connectivity "$LINODE_SERVER_IP"
wait_for_cloud_init "$LINODE_SERVER_IP"
create_server "${SERVER_NAME}"
verify_server_connectivity "${LINODE_SERVER_IP}"
wait_for_cloud_init "${LINODE_SERVER_IP}"
log_warn "Installing Amazon Q CLI..."
run_server "$LINODE_SERVER_IP" "curl -fsSL https://desktop-release.q.us-east-1.amazonaws.com/latest/amazon-q-cli-install.sh | bash"
run_server "${LINODE_SERVER_IP}" "curl -fsSL https://desktop-release.q.us-east-1.amazonaws.com/latest/amazon-q-cli-install.sh | bash"
log_info "Amazon Q CLI installed"
echo ""
if [[ -n "${OPENROUTER_API_KEY:-}" ]]; then log_info "Using OpenRouter API key from environment"
else OPENROUTER_API_KEY=$(get_openrouter_api_key_oauth 5180); fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_BASE_URL="https://openrouter.ai/api/v1"
EOF
upload_file "$LINODE_SERVER_IP" "$ENV_TEMP" "/tmp/env_config"
run_server "$LINODE_SERVER_IP" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
upload_file "${LINODE_SERVER_IP}" "${ENV_TEMP}" "/tmp/env_config"
run_server "${LINODE_SERVER_IP}" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "${ENV_TEMP}"
echo ""
log_info "Linode setup completed successfully!"
echo ""
log_warn "Starting Amazon Q..."
sleep 1
clear
interactive_session "$LINODE_SERVER_IP" "source ~/.zshrc && q chat"
interactive_session "${LINODE_SERVER_IP}" "source ~/.zshrc && q chat"

View file

@ -2,41 +2,41 @@
set -eo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=linode/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then source "${SCRIPT_DIR}/lib/common.sh"
else eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/linode/lib/common.sh)"; fi
log_info "Claude Code on Linode"
echo ""
ensure_linode_token
ensure_ssh_key
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
verify_server_connectivity "$LINODE_SERVER_IP"
wait_for_cloud_init "$LINODE_SERVER_IP"
create_server "${SERVER_NAME}"
verify_server_connectivity "${LINODE_SERVER_IP}"
wait_for_cloud_init "${LINODE_SERVER_IP}"
log_warn "Verifying Claude Code installation..."
if ! run_server "$LINODE_SERVER_IP" "command -v claude" >/dev/null 2>&1; then
if ! run_server "${LINODE_SERVER_IP}" "command -v claude" >/dev/null 2>&1; then
log_warn "Claude Code not found, installing manually..."
run_server "$LINODE_SERVER_IP" "curl -fsSL https://claude.ai/install.sh | bash"
run_server "${LINODE_SERVER_IP}" "curl -fsSL https://claude.ai/install.sh | bash"
fi
log_info "Claude Code is installed"
echo ""
if [[ -n "${OPENROUTER_API_KEY:-}" ]]; then log_info "Using OpenRouter API key from environment"
else OPENROUTER_API_KEY=$(get_openrouter_api_key_oauth 5180); fi
log_warn "Setting up environment variables..."
inject_env_vars_ssh "$LINODE_SERVER_IP" upload_file run_server \
"OPENROUTER_API_KEY=$OPENROUTER_API_KEY" \
inject_env_vars_ssh "${LINODE_SERVER_IP}" upload_file run_server \
"OPENROUTER_API_KEY=${OPENROUTER_API_KEY}" \
"ANTHROPIC_BASE_URL=https://openrouter.ai/api" \
"ANTHROPIC_AUTH_TOKEN=$OPENROUTER_API_KEY" \
"ANTHROPIC_AUTH_TOKEN=${OPENROUTER_API_KEY}" \
"ANTHROPIC_API_KEY=" \
"CLAUDE_CODE_SKIP_ONBOARDING=1" \
"CLAUDE_CODE_ENABLE_TELEMETRY=0"
setup_claude_code_config "$OPENROUTER_API_KEY" \
"upload_file $LINODE_SERVER_IP" \
"run_server $LINODE_SERVER_IP"
setup_claude_code_config "${OPENROUTER_API_KEY}" \
"upload_file ${LINODE_SERVER_IP}" \
"run_server ${LINODE_SERVER_IP}"
echo ""
log_info "Linode setup completed successfully!"
log_info "Server: $SERVER_NAME (ID: $LINODE_SERVER_ID, IP: $LINODE_SERVER_IP)"
log_info "Server: ${SERVER_NAME} (ID: ${LINODE_SERVER_ID}, IP: ${LINODE_SERVER_IP})"
echo ""
log_warn "Starting Claude Code..."
sleep 1
clear
interactive_session "$LINODE_SERVER_IP" "source ~/.zshrc && claude"
interactive_session "${LINODE_SERVER_IP}" "source ~/.zshrc && claude"

View file

@ -1,39 +1,39 @@
#!/bin/bash
set -e
set -eo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=linode/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then source "${SCRIPT_DIR}/lib/common.sh"
else eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/linode/lib/common.sh)"; fi
log_info "Cline on Linode"
echo ""
ensure_linode_token
ensure_ssh_key
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
verify_server_connectivity "$LINODE_SERVER_IP"
wait_for_cloud_init "$LINODE_SERVER_IP"
create_server "${SERVER_NAME}"
verify_server_connectivity "${LINODE_SERVER_IP}"
wait_for_cloud_init "${LINODE_SERVER_IP}"
log_warn "Installing Cline..."
run_server "$LINODE_SERVER_IP" "npm install -g cline"
run_server "${LINODE_SERVER_IP}" "npm install -g cline"
log_info "Cline installed"
echo ""
if [[ -n "${OPENROUTER_API_KEY:-}" ]]; then log_info "Using OpenRouter API key from environment"
else OPENROUTER_API_KEY=$(get_openrouter_api_key_oauth 5180); fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_BASE_URL="https://openrouter.ai/api/v1"
EOF
upload_file "$LINODE_SERVER_IP" "$ENV_TEMP" "/tmp/env_config"
run_server "$LINODE_SERVER_IP" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
upload_file "${LINODE_SERVER_IP}" "${ENV_TEMP}" "/tmp/env_config"
run_server "${LINODE_SERVER_IP}" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "${ENV_TEMP}"
echo ""
log_info "Linode setup completed successfully!"
echo ""
log_warn "Starting Cline..."
sleep 1
clear
interactive_session "$LINODE_SERVER_IP" "source ~/.zshrc && cline"
interactive_session "${LINODE_SERVER_IP}" "source ~/.zshrc && cline"

View file

@ -2,26 +2,26 @@
set -eo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=linode/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then source "${SCRIPT_DIR}/lib/common.sh"
else eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/linode/lib/common.sh)"; fi
log_info "Codex CLI on Linode"
echo ""
ensure_linode_token
ensure_ssh_key
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
verify_server_connectivity "$LINODE_SERVER_IP"
wait_for_cloud_init "$LINODE_SERVER_IP"
create_server "${SERVER_NAME}"
verify_server_connectivity "${LINODE_SERVER_IP}"
wait_for_cloud_init "${LINODE_SERVER_IP}"
log_warn "Installing Codex CLI..."
run_server "$LINODE_SERVER_IP" "npm install -g @openai/codex"
run_server "${LINODE_SERVER_IP}" "npm install -g @openai/codex"
log_info "Codex CLI installed"
echo ""
if [[ -n "${OPENROUTER_API_KEY:-}" ]]; then log_info "Using OpenRouter API key from environment"
else OPENROUTER_API_KEY=$(get_openrouter_api_key_oauth 5180); fi
log_warn "Setting up environment variables..."
inject_env_vars_ssh "$LINODE_SERVER_IP" upload_file run_server \
"OPENROUTER_API_KEY=$OPENROUTER_API_KEY" \
"OPENAI_API_KEY=$OPENROUTER_API_KEY" \
inject_env_vars_ssh "${LINODE_SERVER_IP}" upload_file run_server \
"OPENROUTER_API_KEY=${OPENROUTER_API_KEY}" \
"OPENAI_API_KEY=${OPENROUTER_API_KEY}" \
"OPENAI_BASE_URL=https://openrouter.ai/api/v1"
echo ""
log_info "Linode setup completed successfully!"
@ -29,4 +29,4 @@ echo ""
log_warn "Starting Codex..."
sleep 1
clear
interactive_session "$LINODE_SERVER_IP" "source ~/.zshrc && codex"
interactive_session "${LINODE_SERVER_IP}" "source ~/.zshrc && codex"

View file

@ -1,26 +1,26 @@
#!/bin/bash
set -e
set -eo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=linode/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then source "${SCRIPT_DIR}/lib/common.sh"
else eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/linode/lib/common.sh)"; fi
log_info "Gemini CLI on Linode"
echo ""
ensure_linode_token
ensure_ssh_key
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
verify_server_connectivity "$LINODE_SERVER_IP"
wait_for_cloud_init "$LINODE_SERVER_IP"
create_server "${SERVER_NAME}"
verify_server_connectivity "${LINODE_SERVER_IP}"
wait_for_cloud_init "${LINODE_SERVER_IP}"
log_warn "Installing Gemini CLI..."
run_server "$LINODE_SERVER_IP" "npm install -g @google/gemini-cli"
run_server "${LINODE_SERVER_IP}" "npm install -g @google/gemini-cli"
log_info "Gemini CLI installed"
echo ""
if [[ -n "${OPENROUTER_API_KEY:-}" ]]; then log_info "Using OpenRouter API key from environment"
else OPENROUTER_API_KEY=$(get_openrouter_api_key_oauth 5180); fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
@ -28,13 +28,13 @@ export GEMINI_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_BASE_URL="https://openrouter.ai/api/v1"
EOF
upload_file "$LINODE_SERVER_IP" "$ENV_TEMP" "/tmp/env_config"
run_server "$LINODE_SERVER_IP" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
upload_file "${LINODE_SERVER_IP}" "${ENV_TEMP}" "/tmp/env_config"
run_server "${LINODE_SERVER_IP}" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "${ENV_TEMP}"
echo ""
log_info "Linode setup completed successfully!"
echo ""
log_warn "Starting Gemini..."
sleep 1
clear
interactive_session "$LINODE_SERVER_IP" "source ~/.zshrc && gemini"
interactive_session "${LINODE_SERVER_IP}" "source ~/.zshrc && gemini"

View file

@ -2,30 +2,30 @@
set -eo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=linode/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then source "${SCRIPT_DIR}/lib/common.sh"
else eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/linode/lib/common.sh)"; fi
log_info "Goose on Linode"
echo ""
ensure_linode_token
ensure_ssh_key
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
verify_server_connectivity "$LINODE_SERVER_IP"
wait_for_cloud_init "$LINODE_SERVER_IP"
create_server "${SERVER_NAME}"
verify_server_connectivity "${LINODE_SERVER_IP}"
wait_for_cloud_init "${LINODE_SERVER_IP}"
log_warn "Installing Goose..."
run_server "$LINODE_SERVER_IP" "CONFIGURE=false curl -fsSL https://github.com/block/goose/releases/latest/download/download_cli.sh | bash"
run_server "${LINODE_SERVER_IP}" "CONFIGURE=false curl -fsSL https://github.com/block/goose/releases/latest/download/download_cli.sh | bash"
log_info "Goose installed"
echo ""
if [[ -n "${OPENROUTER_API_KEY:-}" ]]; then log_info "Using OpenRouter API key from environment"
else OPENROUTER_API_KEY=$(get_openrouter_api_key_oauth 5180); fi
log_warn "Setting up environment variables..."
inject_env_vars_ssh "$LINODE_SERVER_IP" upload_file run_server \
inject_env_vars_ssh "${LINODE_SERVER_IP}" upload_file run_server \
"GOOSE_PROVIDER=openrouter" \
"OPENROUTER_API_KEY=$OPENROUTER_API_KEY"
"OPENROUTER_API_KEY=${OPENROUTER_API_KEY}"
echo ""
log_info "Linode setup completed successfully!"
echo ""
log_warn "Starting Goose..."
sleep 1
clear
interactive_session "$LINODE_SERVER_IP" "source ~/.zshrc && goose"
interactive_session "${LINODE_SERVER_IP}" "source ~/.zshrc && goose"

View file

@ -2,26 +2,26 @@
set -eo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=linode/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then source "${SCRIPT_DIR}/lib/common.sh"
else eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/linode/lib/common.sh)"; fi
log_info "Open Interpreter on Linode"
echo ""
ensure_linode_token
ensure_ssh_key
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
verify_server_connectivity "$LINODE_SERVER_IP"
wait_for_cloud_init "$LINODE_SERVER_IP"
create_server "${SERVER_NAME}"
verify_server_connectivity "${LINODE_SERVER_IP}"
wait_for_cloud_init "${LINODE_SERVER_IP}"
log_warn "Installing Open Interpreter..."
run_server "$LINODE_SERVER_IP" "pip install open-interpreter 2>/dev/null || pip3 install open-interpreter"
run_server "${LINODE_SERVER_IP}" "pip install open-interpreter 2>/dev/null || pip3 install open-interpreter"
log_info "Open Interpreter installed"
echo ""
if [[ -n "${OPENROUTER_API_KEY:-}" ]]; then log_info "Using OpenRouter API key from environment"
else OPENROUTER_API_KEY=$(get_openrouter_api_key_oauth 5180); fi
log_warn "Setting up environment variables..."
inject_env_vars_ssh "$LINODE_SERVER_IP" upload_file run_server \
"OPENROUTER_API_KEY=$OPENROUTER_API_KEY" \
"OPENAI_API_KEY=$OPENROUTER_API_KEY" \
inject_env_vars_ssh "${LINODE_SERVER_IP}" upload_file run_server \
"OPENROUTER_API_KEY=${OPENROUTER_API_KEY}" \
"OPENAI_API_KEY=${OPENROUTER_API_KEY}" \
"OPENAI_BASE_URL=https://openrouter.ai/api/v1"
echo ""
log_info "Linode setup completed successfully!"
@ -29,4 +29,4 @@ echo ""
log_warn "Starting Open Interpreter..."
sleep 1
clear
interactive_session "$LINODE_SERVER_IP" "source ~/.zshrc && interpreter"
interactive_session "${LINODE_SERVER_IP}" "source ~/.zshrc && interpreter"

View file

@ -2,41 +2,41 @@
set -eo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=linode/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then source "${SCRIPT_DIR}/lib/common.sh"
else eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/linode/lib/common.sh)"; fi
log_info "NanoClaw on Linode"
echo ""
ensure_linode_token
ensure_ssh_key
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
verify_server_connectivity "$LINODE_SERVER_IP"
wait_for_cloud_init "$LINODE_SERVER_IP"
create_server "${SERVER_NAME}"
verify_server_connectivity "${LINODE_SERVER_IP}"
wait_for_cloud_init "${LINODE_SERVER_IP}"
log_warn "Installing tsx..."
run_server "$LINODE_SERVER_IP" "source ~/.bashrc && bun install -g tsx"
run_server "${LINODE_SERVER_IP}" "source ~/.bashrc && bun install -g tsx"
log_warn "Cloning and building nanoclaw..."
run_server "$LINODE_SERVER_IP" "git clone https://github.com/gavrielc/nanoclaw.git ~/nanoclaw && cd ~/nanoclaw && npm install && npm run build"
run_server "${LINODE_SERVER_IP}" "git clone https://github.com/gavrielc/nanoclaw.git ~/nanoclaw && cd ~/nanoclaw && npm install && npm run build"
log_info "NanoClaw installed"
echo ""
if [[ -n "${OPENROUTER_API_KEY:-}" ]]; then log_info "Using OpenRouter API key from environment"
else OPENROUTER_API_KEY=$(get_openrouter_api_key_oauth 5180); fi
log_warn "Setting up environment variables..."
inject_env_vars_ssh "$LINODE_SERVER_IP" upload_file run_server \
"OPENROUTER_API_KEY=$OPENROUTER_API_KEY" \
"ANTHROPIC_API_KEY=$OPENROUTER_API_KEY" \
inject_env_vars_ssh "${LINODE_SERVER_IP}" upload_file run_server \
"OPENROUTER_API_KEY=${OPENROUTER_API_KEY}" \
"ANTHROPIC_API_KEY=${OPENROUTER_API_KEY}" \
"ANTHROPIC_BASE_URL=https://openrouter.ai/api"
log_warn "Configuring nanoclaw..."
DOTENV_TEMP=$(mktemp)
chmod 600 "$DOTENV_TEMP"
cat > "$DOTENV_TEMP" << EOF
chmod 600 "${DOTENV_TEMP}"
cat > "${DOTENV_TEMP}" << EOF
ANTHROPIC_API_KEY=${OPENROUTER_API_KEY}
EOF
upload_file "$LINODE_SERVER_IP" "$DOTENV_TEMP" "/root/nanoclaw/.env"
rm "$DOTENV_TEMP"
upload_file "${LINODE_SERVER_IP}" "${DOTENV_TEMP}" "/root/nanoclaw/.env"
rm "${DOTENV_TEMP}"
echo ""
log_info "Linode setup completed successfully!"
echo ""
log_warn "Starting nanoclaw..."
log_warn "You will need to scan a WhatsApp QR code to authenticate."
echo ""
interactive_session "$LINODE_SERVER_IP" "cd ~/nanoclaw && source ~/.zshrc && npm run dev"
interactive_session "${LINODE_SERVER_IP}" "cd ~/nanoclaw && source ~/.zshrc && npm run dev"

View file

@ -2,36 +2,36 @@
set -eo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=linode/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then source "${SCRIPT_DIR}/lib/common.sh"
else eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/linode/lib/common.sh)"; fi
log_info "OpenClaw on Linode"
echo ""
ensure_linode_token
ensure_ssh_key
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
verify_server_connectivity "$LINODE_SERVER_IP"
wait_for_cloud_init "$LINODE_SERVER_IP"
create_server "${SERVER_NAME}"
verify_server_connectivity "${LINODE_SERVER_IP}"
wait_for_cloud_init "${LINODE_SERVER_IP}"
log_warn "Installing openclaw..."
run_server "$LINODE_SERVER_IP" "source ~/.bashrc && bun install -g openclaw"
run_server "${LINODE_SERVER_IP}" "source ~/.bashrc && bun install -g openclaw"
log_info "OpenClaw installed"
echo ""
if [[ -n "${OPENROUTER_API_KEY:-}" ]]; then log_info "Using OpenRouter API key from environment"
else OPENROUTER_API_KEY=$(get_openrouter_api_key_oauth 5180); fi
MODEL_ID=$(get_model_id_interactive "openrouter/auto" "Openclaw") || exit 1
log_warn "Setting up environment variables..."
inject_env_vars_ssh "$LINODE_SERVER_IP" upload_file run_server \
"OPENROUTER_API_KEY=$OPENROUTER_API_KEY" \
"ANTHROPIC_API_KEY=$OPENROUTER_API_KEY" \
inject_env_vars_ssh "${LINODE_SERVER_IP}" upload_file run_server \
"OPENROUTER_API_KEY=${OPENROUTER_API_KEY}" \
"ANTHROPIC_API_KEY=${OPENROUTER_API_KEY}" \
"ANTHROPIC_BASE_URL=https://openrouter.ai/api"
setup_openclaw_config "$OPENROUTER_API_KEY" "$MODEL_ID" \
"upload_file $LINODE_SERVER_IP" \
"run_server $LINODE_SERVER_IP"
setup_openclaw_config "${OPENROUTER_API_KEY}" "${MODEL_ID}" \
"upload_file ${LINODE_SERVER_IP}" \
"run_server ${LINODE_SERVER_IP}"
echo ""
log_info "Linode setup completed successfully!"
log_info "Server: $SERVER_NAME (ID: $LINODE_SERVER_ID, IP: $LINODE_SERVER_IP)"
log_info "Server: ${SERVER_NAME} (ID: ${LINODE_SERVER_ID}, IP: ${LINODE_SERVER_IP})"
echo ""
log_warn "Starting openclaw..."
run_server "$LINODE_SERVER_IP" "source ~/.zshrc && nohup openclaw gateway > /tmp/openclaw-gateway.log 2>&1 &"
run_server "${LINODE_SERVER_IP}" "source ~/.zshrc && nohup openclaw gateway > /tmp/openclaw-gateway.log 2>&1 &"
sleep 2
interactive_session "$LINODE_SERVER_IP" "source ~/.zshrc && openclaw tui"
interactive_session "${LINODE_SERVER_IP}" "source ~/.zshrc && openclaw tui"

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=modal/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/modal/lib/common.sh)"
fi
@ -18,11 +18,11 @@ ensure_modal_cli
# 2. Get sandbox name and create sandbox
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME" || {
create_server "${SERVER_NAME}" || {
log_error "Failed to create Modal sandbox"
exit 1
}
if [[ -z "$MODAL_SANDBOX_ID" ]]; then
if [[ -z "${MODAL_SANDBOX_ID}" ]]; then
log_error "MODAL_SANDBOX_ID not set after create_server"
exit 1
fi
@ -54,19 +54,19 @@ MODEL_ID="${MODEL_ID:-openrouter/auto}"
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
EOF
upload_file "$ENV_TEMP" "/tmp/env_config"
upload_file "${ENV_TEMP}" "/tmp/env_config"
run_server "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
rm "${ENV_TEMP}"
echo ""
log_info "Modal sandbox setup completed successfully!"
log_info "Sandbox: $SERVER_NAME (ID: $MODAL_SANDBOX_ID)"
log_info "Sandbox: ${SERVER_NAME} (ID: ${MODAL_SANDBOX_ID})"
echo ""
# 8. Start Aider interactively

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=modal/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/modal/lib/common.sh)"
fi
@ -18,11 +18,11 @@ ensure_modal_cli
# 2. Get sandbox name and create sandbox
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME" || {
create_server "${SERVER_NAME}" || {
log_error "Failed to create Modal sandbox"
exit 1
}
if [[ -z "$MODAL_SANDBOX_ID" ]]; then
if [[ -z "${MODAL_SANDBOX_ID}" ]]; then
log_error "MODAL_SANDBOX_ID not set after create_server"
exit 1
fi
@ -47,7 +47,7 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
@ -55,13 +55,13 @@ export OPENAI_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_BASE_URL="https://openrouter.ai/api/v1"
EOF
upload_file "$ENV_TEMP" "/tmp/env_config"
upload_file "${ENV_TEMP}" "/tmp/env_config"
run_server "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
rm "${ENV_TEMP}"
echo ""
log_info "Modal sandbox setup completed successfully!"
log_info "Sandbox: $SERVER_NAME (ID: $MODAL_SANDBOX_ID)"
log_info "Sandbox: ${SERVER_NAME} (ID: ${MODAL_SANDBOX_ID})"
echo ""
# 7. Start Amazon Q interactively

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=modal/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/modal/lib/common.sh)"
fi
@ -18,11 +18,11 @@ ensure_modal_cli
# 2. Get sandbox name and create sandbox
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME" || {
create_server "${SERVER_NAME}" || {
log_error "Failed to create Modal sandbox"
exit 1
}
if [[ -z "$MODAL_SANDBOX_ID" ]]; then
if [[ -z "${MODAL_SANDBOX_ID}" ]]; then
log_error "MODAL_SANDBOX_ID not set after create_server"
exit 1
fi
@ -50,7 +50,7 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
@ -61,18 +61,18 @@ export CLAUDE_CODE_SKIP_ONBOARDING="1"
export CLAUDE_CODE_ENABLE_TELEMETRY="0"
EOF
upload_file "$ENV_TEMP" "/tmp/env_config"
upload_file "${ENV_TEMP}" "/tmp/env_config"
run_server "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
rm "${ENV_TEMP}"
# 7. Configure Claude Code settings
setup_claude_code_config "$OPENROUTER_API_KEY" \
setup_claude_code_config "${OPENROUTER_API_KEY}" \
"upload_file" \
"run_server"
echo ""
log_info "Modal sandbox setup completed successfully!"
log_info "Sandbox: $SERVER_NAME (ID: $MODAL_SANDBOX_ID)"
log_info "Sandbox: ${SERVER_NAME} (ID: ${MODAL_SANDBOX_ID})"
echo ""
# 8. Start Claude Code interactively

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=modal/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/modal/lib/common.sh)"
fi
@ -18,11 +18,11 @@ ensure_modal_cli
# 2. Get sandbox name and create sandbox
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME" || {
create_server "${SERVER_NAME}" || {
log_error "Failed to create Modal sandbox"
exit 1
}
if [[ -z "$MODAL_SANDBOX_ID" ]]; then
if [[ -z "${MODAL_SANDBOX_ID}" ]]; then
log_error "MODAL_SANDBOX_ID not set after create_server"
exit 1
fi
@ -47,7 +47,7 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
@ -55,13 +55,13 @@ export OPENAI_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_BASE_URL="https://openrouter.ai/api/v1"
EOF
upload_file "$ENV_TEMP" "/tmp/env_config"
upload_file "${ENV_TEMP}" "/tmp/env_config"
run_server "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
rm "${ENV_TEMP}"
echo ""
log_info "Modal sandbox setup completed successfully!"
log_info "Sandbox: $SERVER_NAME (ID: $MODAL_SANDBOX_ID)"
log_info "Sandbox: ${SERVER_NAME} (ID: ${MODAL_SANDBOX_ID})"
echo ""
# 7. Start Cline interactively

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=modal/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/modal/lib/common.sh)"
fi
@ -18,11 +18,11 @@ ensure_modal_cli
# 2. Get sandbox name and create sandbox
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME" || {
create_server "${SERVER_NAME}" || {
log_error "Failed to create Modal sandbox"
exit 1
}
if [[ -z "$MODAL_SANDBOX_ID" ]]; then
if [[ -z "${MODAL_SANDBOX_ID}" ]]; then
log_error "MODAL_SANDBOX_ID not set after create_server"
exit 1
fi
@ -47,7 +47,7 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
@ -55,13 +55,13 @@ export OPENAI_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_BASE_URL="https://openrouter.ai/api/v1"
EOF
upload_file "$ENV_TEMP" "/tmp/env_config"
upload_file "${ENV_TEMP}" "/tmp/env_config"
run_server "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
rm "${ENV_TEMP}"
echo ""
log_info "Modal sandbox setup completed successfully!"
log_info "Sandbox: $SERVER_NAME (ID: $MODAL_SANDBOX_ID)"
log_info "Sandbox: ${SERVER_NAME} (ID: ${MODAL_SANDBOX_ID})"
echo ""
# 7. Start Codex interactively

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=modal/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/modal/lib/common.sh)"
fi
@ -18,11 +18,11 @@ ensure_modal_cli
# 2. Get sandbox name and create sandbox
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME" || {
create_server "${SERVER_NAME}" || {
log_error "Failed to create Modal sandbox"
exit 1
}
if [[ -z "$MODAL_SANDBOX_ID" ]]; then
if [[ -z "${MODAL_SANDBOX_ID}" ]]; then
log_error "MODAL_SANDBOX_ID not set after create_server"
exit 1
fi
@ -47,7 +47,7 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
@ -56,13 +56,13 @@ export OPENAI_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_BASE_URL="https://openrouter.ai/api/v1"
EOF
upload_file "$ENV_TEMP" "/tmp/env_config"
upload_file "${ENV_TEMP}" "/tmp/env_config"
run_server "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
rm "${ENV_TEMP}"
echo ""
log_info "Modal sandbox setup completed successfully!"
log_info "Sandbox: $SERVER_NAME (ID: $MODAL_SANDBOX_ID)"
log_info "Sandbox: ${SERVER_NAME} (ID: ${MODAL_SANDBOX_ID})"
echo ""
# 7. Start Gemini interactively

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=modal/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/modal/lib/common.sh)"
fi
@ -18,11 +18,11 @@ ensure_modal_cli
# 2. Get sandbox name and create sandbox
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME" || {
create_server "${SERVER_NAME}" || {
log_error "Failed to create Modal sandbox"
exit 1
}
if [[ -z "$MODAL_SANDBOX_ID" ]]; then
if [[ -z "${MODAL_SANDBOX_ID}" ]]; then
log_error "MODAL_SANDBOX_ID not set after create_server"
exit 1
fi
@ -47,20 +47,20 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export GOOSE_PROVIDER=openrouter
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
EOF
upload_file "$ENV_TEMP" "/tmp/env_config"
upload_file "${ENV_TEMP}" "/tmp/env_config"
run_server "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
rm "${ENV_TEMP}"
echo ""
log_info "Modal sandbox setup completed successfully!"
log_info "Sandbox: $SERVER_NAME (ID: $MODAL_SANDBOX_ID)"
log_info "Sandbox: ${SERVER_NAME} (ID: ${MODAL_SANDBOX_ID})"
echo ""
# 7. Start Goose interactively

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=modal/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/modal/lib/common.sh)"
fi
@ -18,11 +18,11 @@ ensure_modal_cli
# 2. Get sandbox name and create sandbox
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME" || {
create_server "${SERVER_NAME}" || {
log_error "Failed to create Modal sandbox"
exit 1
}
if [[ -z "$MODAL_SANDBOX_ID" ]]; then
if [[ -z "${MODAL_SANDBOX_ID}" ]]; then
log_error "MODAL_SANDBOX_ID not set after create_server"
exit 1
fi
@ -47,7 +47,7 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
@ -55,13 +55,13 @@ export OPENAI_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_BASE_URL="https://openrouter.ai/api/v1"
EOF
upload_file "$ENV_TEMP" "/tmp/env_config"
upload_file "${ENV_TEMP}" "/tmp/env_config"
run_server "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
rm "${ENV_TEMP}"
echo ""
log_info "Modal sandbox setup completed successfully!"
log_info "Sandbox: $SERVER_NAME (ID: $MODAL_SANDBOX_ID)"
log_info "Sandbox: ${SERVER_NAME} (ID: ${MODAL_SANDBOX_ID})"
echo ""
# 7. Start Open Interpreter interactively

View file

@ -79,8 +79,8 @@ wait_for_cloud_init() {
log_warn "Installing tools in sandbox..."
run_server "curl -fsSL https://bun.sh/install | bash" >/dev/null 2>&1 || true
run_server "curl -fsSL https://claude.ai/install.sh | bash" >/dev/null 2>&1 || true
run_server 'echo "export PATH=\"\$HOME/.claude/local/bin:\$HOME/.bun/bin:\$PATH\"" >> ~/.bashrc' >/dev/null 2>&1 || true
run_server 'echo "export PATH=\"\$HOME/.claude/local/bin:\$HOME/.bun/bin:\$PATH\"" >> ~/.zshrc' >/dev/null 2>&1 || true
run_server 'echo "export PATH=\"\${HOME}/.claude/local/bin:\${HOME}/.bun/bin:\${PATH}\"" >> ~/.bashrc' >/dev/null 2>&1 || true
run_server 'echo "export PATH=\"\${HOME}/.claude/local/bin:\${HOME}/.bun/bin:\${PATH}\"" >> ~/.zshrc' >/dev/null 2>&1 || true
log_info "Tools installed"
}

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=modal/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/modal/lib/common.sh)"
fi
@ -18,11 +18,11 @@ ensure_modal_cli
# 2. Get sandbox name and create sandbox
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME" || {
create_server "${SERVER_NAME}" || {
log_error "Failed to create Modal sandbox"
exit 1
}
if [[ -z "$MODAL_SANDBOX_ID" ]]; then
if [[ -z "${MODAL_SANDBOX_ID}" ]]; then
log_error "MODAL_SANDBOX_ID not set after create_server"
exit 1
fi
@ -50,7 +50,7 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
@ -58,24 +58,24 @@ export ANTHROPIC_API_KEY="${OPENROUTER_API_KEY}"
export ANTHROPIC_BASE_URL="https://openrouter.ai/api"
EOF
upload_file "$ENV_TEMP" "/tmp/env_config"
upload_file "${ENV_TEMP}" "/tmp/env_config"
run_server "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
rm "${ENV_TEMP}"
# 7. Create nanoclaw .env file
log_warn "Configuring nanoclaw..."
DOTENV_TEMP=$(mktemp)
cat > "$DOTENV_TEMP" << EOF
cat > "${DOTENV_TEMP}" << EOF
ANTHROPIC_API_KEY=${OPENROUTER_API_KEY}
EOF
upload_file "$DOTENV_TEMP" ~/nanoclaw/.env
rm "$DOTENV_TEMP"
upload_file "${DOTENV_TEMP}" ~/nanoclaw/.env
rm "${DOTENV_TEMP}"
echo ""
log_info "Modal sandbox setup completed successfully!"
log_info "Sandbox: $SERVER_NAME (ID: $MODAL_SANDBOX_ID)"
log_info "Sandbox: ${SERVER_NAME} (ID: ${MODAL_SANDBOX_ID})"
echo ""
# 8. Start nanoclaw

View file

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
# shellcheck source=modal/lib/common.sh
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/modal/lib/common.sh)"
fi
@ -18,11 +18,11 @@ ensure_modal_cli
# 2. Get sandbox name and create sandbox
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME" || {
create_server "${SERVER_NAME}" || {
log_error "Failed to create Modal sandbox"
exit 1
}
if [[ -z "$MODAL_SANDBOX_ID" ]]; then
if [[ -z "${MODAL_SANDBOX_ID}" ]]; then
log_error "MODAL_SANDBOX_ID not set after create_server"
exit 1
fi
@ -50,7 +50,7 @@ MODEL_ID=$(get_model_id_interactive "openrouter/auto" "Openclaw") || exit 1
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
@ -58,18 +58,18 @@ export ANTHROPIC_API_KEY="${OPENROUTER_API_KEY}"
export ANTHROPIC_BASE_URL="https://openrouter.ai/api"
EOF
upload_file "$ENV_TEMP" "/tmp/env_config"
upload_file "${ENV_TEMP}" "/tmp/env_config"
run_server "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
rm "${ENV_TEMP}"
# 8. Configure openclaw
setup_openclaw_config "$OPENROUTER_API_KEY" "$MODEL_ID" \
setup_openclaw_config "${OPENROUTER_API_KEY}" "${MODEL_ID}" \
upload_file \
run_server
echo ""
log_info "Modal sandbox setup completed successfully!"
log_info "Sandbox: $SERVER_NAME (ID: $MODAL_SANDBOX_ID)"
log_info "Sandbox: ${SERVER_NAME} (ID: ${MODAL_SANDBOX_ID})"
echo ""
# 9. Start openclaw gateway in background and launch TUI

View file

@ -692,9 +692,9 @@ runcmd:
# Install Claude Code
- su - root -c 'curl -fsSL https://claude.ai/install.sh | bash'
# Configure PATH in .bashrc
- echo 'export PATH="$HOME/.claude/local/bin:$HOME/.bun/bin:$PATH"' >> /root/.bashrc
- echo 'export PATH="${HOME}/.claude/local/bin:${HOME}/.bun/bin:${PATH}"' >> /root/.bashrc
# Configure PATH in .zshrc
- echo 'export PATH="$HOME/.claude/local/bin:$HOME/.bun/bin:$PATH"' >> /root/.zshrc
- echo 'export PATH="${HOME}/.claude/local/bin:${HOME}/.bun/bin:${PATH}"' >> /root/.zshrc
# Signal completion
- touch /root/.cloud-init-complete
CLOUD_INIT_EOF

View file

@ -3,8 +3,8 @@ set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/sprite/lib/common.sh)"
fi
@ -17,20 +17,20 @@ ensure_sprite_installed
ensure_sprite_authenticated
SPRITE_NAME=$(get_sprite_name)
ensure_sprite_exists "$SPRITE_NAME" 5
verify_sprite_connectivity "$SPRITE_NAME"
ensure_sprite_exists "${SPRITE_NAME}" 5
verify_sprite_connectivity "${SPRITE_NAME}"
log_warn "Setting up sprite environment..."
# Configure shell environment
setup_shell_environment "$SPRITE_NAME"
setup_shell_environment "${SPRITE_NAME}"
# Install Aider
log_warn "Installing Aider..."
run_sprite "$SPRITE_NAME" "pip install aider-chat 2>/dev/null || pip3 install aider-chat"
run_sprite "${SPRITE_NAME}" "pip install aider-chat 2>/dev/null || pip3 install aider-chat"
# Verify installation succeeded
if ! run_sprite "$SPRITE_NAME" "command -v aider &> /dev/null && aider --version &> /dev/null"; then
if ! run_sprite "${SPRITE_NAME}" "command -v aider &> /dev/null && aider --version &> /dev/null"; then
log_error "Aider installation verification failed"
log_error "The 'aider' command is not available or not working properly"
exit 1
@ -49,8 +49,8 @@ fi
MODEL_ID=$(get_model_id_interactive "openrouter/auto" "Aider") || exit 1
log_warn "Setting up environment variables..."
inject_env_vars_sprite "$SPRITE_NAME" \
"OPENROUTER_API_KEY=$OPENROUTER_API_KEY"
inject_env_vars_sprite "${SPRITE_NAME}" \
"OPENROUTER_API_KEY=${OPENROUTER_API_KEY}"
echo ""
log_info "Sprite setup completed successfully!"
@ -60,4 +60,4 @@ echo ""
log_warn "Starting Aider..."
sleep 1
clear
sprite exec -s "$SPRITE_NAME" -tty -- zsh -c "source ~/.zshrc && aider --model openrouter/${MODEL_ID}"
sprite exec -s "${SPRITE_NAME}" -tty -- zsh -c "source ~/.zshrc && aider --model openrouter/${MODEL_ID}"

View file

@ -1,9 +1,9 @@
#!/bin/bash
set -e
set -eo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/sprite/lib/common.sh)"
fi
@ -15,14 +15,14 @@ ensure_sprite_installed
ensure_sprite_authenticated
SPRITE_NAME=$(get_sprite_name)
ensure_sprite_exists "$SPRITE_NAME" 5
verify_sprite_connectivity "$SPRITE_NAME"
ensure_sprite_exists "${SPRITE_NAME}" 5
verify_sprite_connectivity "${SPRITE_NAME}"
log_warn "Setting up sprite environment..."
setup_shell_environment "$SPRITE_NAME"
setup_shell_environment "${SPRITE_NAME}"
log_warn "Installing Amazon Q CLI..."
run_sprite "$SPRITE_NAME" "curl -fsSL https://desktop-release.q.us-east-1.amazonaws.com/latest/amazon-q-cli-install.sh | bash"
run_sprite "${SPRITE_NAME}" "curl -fsSL https://desktop-release.q.us-east-1.amazonaws.com/latest/amazon-q-cli-install.sh | bash"
echo ""
if [[ -n "${OPENROUTER_API_KEY:-}" ]]; then
@ -33,15 +33,15 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_BASE_URL="https://openrouter.ai/api/v1"
EOF
sprite exec -s "$SPRITE_NAME" -file "$ENV_TEMP:/tmp/env_config" -- bash -c "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
sprite exec -s "${SPRITE_NAME}" -file "${ENV_TEMP}:/tmp/env_config" -- bash -c "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "${ENV_TEMP}"
echo ""
log_info "Sprite setup completed successfully!"
@ -50,4 +50,4 @@ echo ""
log_warn "Starting Amazon Q..."
sleep 1
clear
sprite exec -s "$SPRITE_NAME" -tty -- zsh -c "source ~/.zshrc && q chat"
sprite exec -s "${SPRITE_NAME}" -tty -- zsh -c "source ~/.zshrc && q chat"

View file

@ -3,8 +3,8 @@ set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/sprite/lib/common.sh)"
fi
@ -17,20 +17,20 @@ ensure_sprite_installed
ensure_sprite_authenticated
SPRITE_NAME=$(get_sprite_name)
ensure_sprite_exists "$SPRITE_NAME" 5
verify_sprite_connectivity "$SPRITE_NAME"
ensure_sprite_exists "${SPRITE_NAME}" 5
verify_sprite_connectivity "${SPRITE_NAME}"
log_warn "Setting up sprite environment..."
# Configure shell environment
setup_shell_environment "$SPRITE_NAME"
setup_shell_environment "${SPRITE_NAME}"
# Install Claude Code using claude install
log_warn "Installing Claude Code..."
run_sprite "$SPRITE_NAME" "claude install > /dev/null 2>&1"
run_sprite "${SPRITE_NAME}" "claude install > /dev/null 2>&1"
# Verify installation succeeded
if ! run_sprite "$SPRITE_NAME" "command -v claude &> /dev/null && claude --version &> /dev/null"; then
if ! run_sprite "${SPRITE_NAME}" "command -v claude &> /dev/null && claude --version &> /dev/null"; then
log_error "Claude Code installation verification failed"
log_error "The 'claude' command is not available or not working properly"
exit 1
@ -42,18 +42,18 @@ echo ""
OPENROUTER_API_KEY=$(get_openrouter_api_key_oauth 5180)
log_warn "Setting up environment variables..."
inject_env_vars_sprite "$SPRITE_NAME" \
"OPENROUTER_API_KEY=$OPENROUTER_API_KEY" \
inject_env_vars_sprite "${SPRITE_NAME}" \
"OPENROUTER_API_KEY=${OPENROUTER_API_KEY}" \
"ANTHROPIC_BASE_URL=https://openrouter.ai/api" \
"ANTHROPIC_AUTH_TOKEN=$OPENROUTER_API_KEY" \
"ANTHROPIC_AUTH_TOKEN=${OPENROUTER_API_KEY}" \
"ANTHROPIC_API_KEY=" \
"CLAUDE_CODE_SKIP_ONBOARDING=1" \
"CLAUDE_CODE_ENABLE_TELEMETRY=0"
# Setup Claude Code settings to bypass initial setup
setup_claude_code_config "$OPENROUTER_API_KEY" \
"upload_file_sprite $SPRITE_NAME" \
"run_sprite $SPRITE_NAME"
setup_claude_code_config "${OPENROUTER_API_KEY}" \
"upload_file_sprite ${SPRITE_NAME}" \
"run_sprite ${SPRITE_NAME}"
echo ""
log_info "✅ Sprite setup completed successfully!"
@ -63,4 +63,4 @@ echo ""
log_warn "Starting Claude Code..."
sleep 1
clear
sprite exec -s "$SPRITE_NAME" -tty -- zsh -c "source ~/.zshrc && claude"
sprite exec -s "${SPRITE_NAME}" -tty -- zsh -c "source ~/.zshrc && claude"

View file

@ -1,9 +1,9 @@
#!/bin/bash
set -e
set -eo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/sprite/lib/common.sh)"
fi
@ -15,14 +15,14 @@ ensure_sprite_installed
ensure_sprite_authenticated
SPRITE_NAME=$(get_sprite_name)
ensure_sprite_exists "$SPRITE_NAME" 5
verify_sprite_connectivity "$SPRITE_NAME"
ensure_sprite_exists "${SPRITE_NAME}" 5
verify_sprite_connectivity "${SPRITE_NAME}"
log_warn "Setting up sprite environment..."
setup_shell_environment "$SPRITE_NAME"
setup_shell_environment "${SPRITE_NAME}"
log_warn "Installing Cline..."
run_sprite "$SPRITE_NAME" "npm install -g cline"
run_sprite "${SPRITE_NAME}" "npm install -g cline"
echo ""
if [[ -n "${OPENROUTER_API_KEY:-}" ]]; then
@ -33,15 +33,15 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_BASE_URL="https://openrouter.ai/api/v1"
EOF
sprite exec -s "$SPRITE_NAME" -file "$ENV_TEMP:/tmp/env_config" -- bash -c "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
sprite exec -s "${SPRITE_NAME}" -file "${ENV_TEMP}:/tmp/env_config" -- bash -c "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "${ENV_TEMP}"
echo ""
log_info "Sprite setup completed successfully!"
@ -50,4 +50,4 @@ echo ""
log_warn "Starting Cline..."
sleep 1
clear
sprite exec -s "$SPRITE_NAME" -tty -- zsh -c "source ~/.zshrc && cline"
sprite exec -s "${SPRITE_NAME}" -tty -- zsh -c "source ~/.zshrc && cline"

View file

@ -2,8 +2,8 @@
set -eo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/sprite/lib/common.sh)"
fi
@ -15,14 +15,14 @@ ensure_sprite_installed
ensure_sprite_authenticated
SPRITE_NAME=$(get_sprite_name)
ensure_sprite_exists "$SPRITE_NAME" 5
verify_sprite_connectivity "$SPRITE_NAME"
ensure_sprite_exists "${SPRITE_NAME}" 5
verify_sprite_connectivity "${SPRITE_NAME}"
log_warn "Setting up sprite environment..."
setup_shell_environment "$SPRITE_NAME"
setup_shell_environment "${SPRITE_NAME}"
log_warn "Installing Codex CLI..."
run_sprite "$SPRITE_NAME" "npm install -g @openai/codex"
run_sprite "${SPRITE_NAME}" "npm install -g @openai/codex"
echo ""
if [[ -n "${OPENROUTER_API_KEY:-}" ]]; then
@ -32,9 +32,9 @@ else
fi
log_warn "Setting up environment variables..."
inject_env_vars_sprite "$SPRITE_NAME" \
"OPENROUTER_API_KEY=$OPENROUTER_API_KEY" \
"OPENAI_API_KEY=$OPENROUTER_API_KEY" \
inject_env_vars_sprite "${SPRITE_NAME}" \
"OPENROUTER_API_KEY=${OPENROUTER_API_KEY}" \
"OPENAI_API_KEY=${OPENROUTER_API_KEY}" \
"OPENAI_BASE_URL=https://openrouter.ai/api/v1"
echo ""
@ -44,4 +44,4 @@ echo ""
log_warn "Starting Codex..."
sleep 1
clear
sprite exec -s "$SPRITE_NAME" -tty -- zsh -c "source ~/.zshrc && codex"
sprite exec -s "${SPRITE_NAME}" -tty -- zsh -c "source ~/.zshrc && codex"

View file

@ -1,9 +1,9 @@
#!/bin/bash
set -e
set -eo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/sprite/lib/common.sh)"
fi
@ -15,14 +15,14 @@ ensure_sprite_installed
ensure_sprite_authenticated
SPRITE_NAME=$(get_sprite_name)
ensure_sprite_exists "$SPRITE_NAME" 5
verify_sprite_connectivity "$SPRITE_NAME"
ensure_sprite_exists "${SPRITE_NAME}" 5
verify_sprite_connectivity "${SPRITE_NAME}"
log_warn "Setting up sprite environment..."
setup_shell_environment "$SPRITE_NAME"
setup_shell_environment "${SPRITE_NAME}"
log_warn "Installing Gemini CLI..."
run_sprite "$SPRITE_NAME" "npm install -g @google/gemini-cli"
run_sprite "${SPRITE_NAME}" "npm install -g @google/gemini-cli"
echo ""
if [[ -n "${OPENROUTER_API_KEY:-}" ]]; then
@ -33,7 +33,7 @@ fi
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
cat > "${ENV_TEMP}" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
@ -41,8 +41,8 @@ export GEMINI_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_API_KEY="${OPENROUTER_API_KEY}"
export OPENAI_BASE_URL="https://openrouter.ai/api/v1"
EOF
sprite exec -s "$SPRITE_NAME" -file "$ENV_TEMP:/tmp/env_config" -- bash -c "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
sprite exec -s "${SPRITE_NAME}" -file "${ENV_TEMP}:/tmp/env_config" -- bash -c "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "${ENV_TEMP}"
echo ""
log_info "Sprite setup completed successfully!"
@ -51,4 +51,4 @@ echo ""
log_warn "Starting Gemini..."
sleep 1
clear
sprite exec -s "$SPRITE_NAME" -tty -- zsh -c "source ~/.zshrc && gemini"
sprite exec -s "${SPRITE_NAME}" -tty -- zsh -c "source ~/.zshrc && gemini"

View file

@ -3,8 +3,8 @@ set -eo pipefail
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/sprite/lib/common.sh)"
fi
@ -17,20 +17,20 @@ ensure_sprite_installed
ensure_sprite_authenticated
SPRITE_NAME=$(get_sprite_name)
ensure_sprite_exists "$SPRITE_NAME" 5
verify_sprite_connectivity "$SPRITE_NAME"
ensure_sprite_exists "${SPRITE_NAME}" 5
verify_sprite_connectivity "${SPRITE_NAME}"
log_warn "Setting up sprite environment..."
# Configure shell environment
setup_shell_environment "$SPRITE_NAME"
setup_shell_environment "${SPRITE_NAME}"
# Install Goose
log_warn "Installing Goose..."
run_sprite "$SPRITE_NAME" "CONFIGURE=false curl -fsSL https://github.com/block/goose/releases/latest/download/download_cli.sh | bash"
run_sprite "${SPRITE_NAME}" "CONFIGURE=false curl -fsSL https://github.com/block/goose/releases/latest/download/download_cli.sh | bash"
# Verify installation succeeded
if ! run_sprite "$SPRITE_NAME" "command -v goose &> /dev/null && goose --version &> /dev/null"; then
if ! run_sprite "${SPRITE_NAME}" "command -v goose &> /dev/null && goose --version &> /dev/null"; then
log_error "Goose installation verification failed"
log_error "The 'goose' command is not available or not working properly"
exit 1
@ -46,9 +46,9 @@ else
fi
log_warn "Setting up environment variables..."
inject_env_vars_sprite "$SPRITE_NAME" \
inject_env_vars_sprite "${SPRITE_NAME}" \
"GOOSE_PROVIDER=openrouter" \
"OPENROUTER_API_KEY=$OPENROUTER_API_KEY"
"OPENROUTER_API_KEY=${OPENROUTER_API_KEY}"
echo ""
log_info "Sprite setup completed successfully!"
@ -58,4 +58,4 @@ echo ""
log_warn "Starting Goose..."
sleep 1
clear
sprite exec -s "$SPRITE_NAME" -tty -- zsh -c "source ~/.zshrc && goose"
sprite exec -s "${SPRITE_NAME}" -tty -- zsh -c "source ~/.zshrc && goose"

View file

@ -2,8 +2,8 @@
set -eo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
if [[ -f "${SCRIPT_DIR}/lib/common.sh" ]]; then
source "${SCRIPT_DIR}/lib/common.sh"
else
eval "$(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/sprite/lib/common.sh)"
fi
@ -15,14 +15,14 @@ ensure_sprite_installed
ensure_sprite_authenticated
SPRITE_NAME=$(get_sprite_name)
ensure_sprite_exists "$SPRITE_NAME" 5
verify_sprite_connectivity "$SPRITE_NAME"
ensure_sprite_exists "${SPRITE_NAME}" 5
verify_sprite_connectivity "${SPRITE_NAME}"
log_warn "Setting up sprite environment..."
setup_shell_environment "$SPRITE_NAME"
setup_shell_environment "${SPRITE_NAME}"
log_warn "Installing Open Interpreter..."
run_sprite "$SPRITE_NAME" "pip install open-interpreter 2>/dev/null || pip3 install open-interpreter"
run_sprite "${SPRITE_NAME}" "pip install open-interpreter 2>/dev/null || pip3 install open-interpreter"
echo ""
if [[ -n "${OPENROUTER_API_KEY:-}" ]]; then
@ -32,9 +32,9 @@ else
fi
log_warn "Setting up environment variables..."
inject_env_vars_sprite "$SPRITE_NAME" \
"OPENROUTER_API_KEY=$OPENROUTER_API_KEY" \
"OPENAI_API_KEY=$OPENROUTER_API_KEY" \
inject_env_vars_sprite "${SPRITE_NAME}" \
"OPENROUTER_API_KEY=${OPENROUTER_API_KEY}" \
"OPENAI_API_KEY=${OPENROUTER_API_KEY}" \
"OPENAI_BASE_URL=https://openrouter.ai/api/v1"
echo ""
@ -44,4 +44,4 @@ echo ""
log_warn "Starting Open Interpreter..."
sleep 1
clear
sprite exec -s "$SPRITE_NAME" -tty -- zsh -c "source ~/.zshrc && interpreter"
sprite exec -s "${SPRITE_NAME}" -tty -- zsh -c "source ~/.zshrc && interpreter"

View file

@ -93,7 +93,7 @@ setup_shell_environment() {
cat > "${path_temp}" << 'EOF'
# [spawn:path]
export PATH="$HOME/.bun/bin:/.sprite/languages/bun/bin:$PATH"
export PATH="${HOME}/.bun/bin:/.sprite/languages/bun/bin:${PATH}"
EOF
# Upload and append to shell configs

Some files were not shown because too many files have changed in this diff Show more