diff --git a/aws-lightsail/aider.sh b/aws-lightsail/aider.sh index 1c293fd9..34e1c2b9 100755 --- a/aws-lightsail/aider.sh +++ b/aws-lightsail/aider.sh @@ -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}" diff --git a/aws-lightsail/amazonq.sh b/aws-lightsail/amazonq.sh index d8d77b21..bc96b85d 100755 --- a/aws-lightsail/amazonq.sh +++ b/aws-lightsail/amazonq.sh @@ -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" diff --git a/aws-lightsail/claude.sh b/aws-lightsail/claude.sh index 0e88de95..41774e41 100755 --- a/aws-lightsail/claude.sh +++ b/aws-lightsail/claude.sh @@ -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" diff --git a/aws-lightsail/cline.sh b/aws-lightsail/cline.sh index e09eb88c..8b105978 100755 --- a/aws-lightsail/cline.sh +++ b/aws-lightsail/cline.sh @@ -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" diff --git a/aws-lightsail/codex.sh b/aws-lightsail/codex.sh index fc0680ac..479af5a0 100755 --- a/aws-lightsail/codex.sh +++ b/aws-lightsail/codex.sh @@ -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" diff --git a/aws-lightsail/gemini.sh b/aws-lightsail/gemini.sh index c9477773..4d4e57ce 100755 --- a/aws-lightsail/gemini.sh +++ b/aws-lightsail/gemini.sh @@ -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" diff --git a/aws-lightsail/goose.sh b/aws-lightsail/goose.sh index 0ac15d5d..8aec9b8a 100755 --- a/aws-lightsail/goose.sh +++ b/aws-lightsail/goose.sh @@ -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" diff --git a/aws-lightsail/interpreter.sh b/aws-lightsail/interpreter.sh index e65757f5..c780ffe7 100755 --- a/aws-lightsail/interpreter.sh +++ b/aws-lightsail/interpreter.sh @@ -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" diff --git a/aws-lightsail/lib/common.sh b/aws-lightsail/lib/common.sh index f61bf545..a1fec8ac 100644 --- a/aws-lightsail/lib/common.sh +++ b/aws-lightsail/lib/common.sh @@ -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 diff --git a/aws-lightsail/nanoclaw.sh b/aws-lightsail/nanoclaw.sh index cf6ab5a6..f335bcd0 100755 --- a/aws-lightsail/nanoclaw.sh +++ b/aws-lightsail/nanoclaw.sh @@ -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" diff --git a/aws-lightsail/openclaw.sh b/aws-lightsail/openclaw.sh index e8de1ea2..22dcf826 100755 --- a/aws-lightsail/openclaw.sh +++ b/aws-lightsail/openclaw.sh @@ -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" diff --git a/cli/install.sh b/cli/install.sh index 37e32961..7db84f87 100755 --- a/cli/install.sh +++ b/cli/install.sh @@ -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 diff --git a/cli/spawn.sh b/cli/spawn.sh index 973811a7..bc6cf18f 100755 --- a/cli/spawn.sh +++ b/cli/spawn.sh @@ -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 = 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 diff --git a/digitalocean/aider.sh b/digitalocean/aider.sh index 0d10197b..b9117d49 100755 --- a/digitalocean/aider.sh +++ b/digitalocean/aider.sh @@ -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}" diff --git a/digitalocean/amazonq.sh b/digitalocean/amazonq.sh index 2c9d17b8..4b03b360 100755 --- a/digitalocean/amazonq.sh +++ b/digitalocean/amazonq.sh @@ -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" diff --git a/digitalocean/claude.sh b/digitalocean/claude.sh index 4bf2d84a..ddaacba6 100755 --- a/digitalocean/claude.sh +++ b/digitalocean/claude.sh @@ -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" diff --git a/digitalocean/cline.sh b/digitalocean/cline.sh index c532d974..8cf18045 100755 --- a/digitalocean/cline.sh +++ b/digitalocean/cline.sh @@ -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" diff --git a/digitalocean/codex.sh b/digitalocean/codex.sh index 885d1538..1b7ded6c 100755 --- a/digitalocean/codex.sh +++ b/digitalocean/codex.sh @@ -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" diff --git a/digitalocean/gemini.sh b/digitalocean/gemini.sh index 91c9e6eb..7aac212f 100755 --- a/digitalocean/gemini.sh +++ b/digitalocean/gemini.sh @@ -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" diff --git a/digitalocean/goose.sh b/digitalocean/goose.sh index 69989c5f..18809dab 100755 --- a/digitalocean/goose.sh +++ b/digitalocean/goose.sh @@ -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" diff --git a/digitalocean/interpreter.sh b/digitalocean/interpreter.sh index a09fcfac..f8aa517d 100755 --- a/digitalocean/interpreter.sh +++ b/digitalocean/interpreter.sh @@ -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" diff --git a/digitalocean/nanoclaw.sh b/digitalocean/nanoclaw.sh index 187429d3..2057a87e 100755 --- a/digitalocean/nanoclaw.sh +++ b/digitalocean/nanoclaw.sh @@ -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" diff --git a/digitalocean/openclaw.sh b/digitalocean/openclaw.sh index 875b87d6..a8049e3b 100755 --- a/digitalocean/openclaw.sh +++ b/digitalocean/openclaw.sh @@ -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" diff --git a/e2b/aider.sh b/e2b/aider.sh index 31ef87e4..7b4c4786 100755 --- a/e2b/aider.sh +++ b/e2b/aider.sh @@ -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 diff --git a/e2b/amazonq.sh b/e2b/amazonq.sh index d9cc1619..8fdeeb64 100755 --- a/e2b/amazonq.sh +++ b/e2b/amazonq.sh @@ -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 diff --git a/e2b/claude.sh b/e2b/claude.sh index 1686b513..d1fa4a57 100755 --- a/e2b/claude.sh +++ b/e2b/claude.sh @@ -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 diff --git a/e2b/cline.sh b/e2b/cline.sh index 0e0b1eb8..ce5073e7 100755 --- a/e2b/cline.sh +++ b/e2b/cline.sh @@ -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 diff --git a/e2b/codex.sh b/e2b/codex.sh index 592b264f..20e360a5 100755 --- a/e2b/codex.sh +++ b/e2b/codex.sh @@ -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 diff --git a/e2b/gemini.sh b/e2b/gemini.sh index fa169a63..57612f27 100755 --- a/e2b/gemini.sh +++ b/e2b/gemini.sh @@ -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 diff --git a/e2b/goose.sh b/e2b/goose.sh index a36442f8..5a795185 100755 --- a/e2b/goose.sh +++ b/e2b/goose.sh @@ -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 diff --git a/e2b/interpreter.sh b/e2b/interpreter.sh index dc97ccd0..e31a493c 100755 --- a/e2b/interpreter.sh +++ b/e2b/interpreter.sh @@ -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 diff --git a/e2b/lib/common.sh b/e2b/lib/common.sh index 9918fa6b..ac41d48f 100644 --- a/e2b/lib/common.sh +++ b/e2b/lib/common.sh @@ -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" } diff --git a/e2b/nanoclaw.sh b/e2b/nanoclaw.sh index a3942fd4..f7646640 100755 --- a/e2b/nanoclaw.sh +++ b/e2b/nanoclaw.sh @@ -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 diff --git a/e2b/openclaw.sh b/e2b/openclaw.sh index 88c50fe5..af365cd1 100755 --- a/e2b/openclaw.sh +++ b/e2b/openclaw.sh @@ -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 diff --git a/fix_braces.py b/fix_braces.py new file mode 100644 index 00000000..b1548dec --- /dev/null +++ b/fix_braces.py @@ -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() diff --git a/fix_sc2250.sh b/fix_sc2250.sh new file mode 100644 index 00000000..9efb0177 --- /dev/null +++ b/fix_sc2250.sh @@ -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}" diff --git a/gcp/aider.sh b/gcp/aider.sh index b9a999dd..2affcc4a 100755 --- a/gcp/aider.sh +++ b/gcp/aider.sh @@ -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}" diff --git a/gcp/amazonq.sh b/gcp/amazonq.sh index a0050447..e583224f 100755 --- a/gcp/amazonq.sh +++ b/gcp/amazonq.sh @@ -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" diff --git a/gcp/claude.sh b/gcp/claude.sh index 9364cb81..ea679520 100755 --- a/gcp/claude.sh +++ b/gcp/claude.sh @@ -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" diff --git a/gcp/cline.sh b/gcp/cline.sh index 9b349e87..746db8a3 100755 --- a/gcp/cline.sh +++ b/gcp/cline.sh @@ -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" diff --git a/gcp/codex.sh b/gcp/codex.sh index 0faf8793..3716f40e 100755 --- a/gcp/codex.sh +++ b/gcp/codex.sh @@ -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" diff --git a/gcp/gemini.sh b/gcp/gemini.sh index b52c04b9..0edc5a52 100755 --- a/gcp/gemini.sh +++ b/gcp/gemini.sh @@ -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" diff --git a/gcp/goose.sh b/gcp/goose.sh index 7cbac8d5..d56d795a 100755 --- a/gcp/goose.sh +++ b/gcp/goose.sh @@ -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" diff --git a/gcp/interpreter.sh b/gcp/interpreter.sh index 02c23aed..012c2e89 100755 --- a/gcp/interpreter.sh +++ b/gcp/interpreter.sh @@ -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" diff --git a/gcp/lib/common.sh b/gcp/lib/common.sh index 561a7cab..bf6c51ac 100644 --- a/gcp/lib/common.sh +++ b/gcp/lib/common.sh @@ -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 diff --git a/gcp/nanoclaw.sh b/gcp/nanoclaw.sh index b8a43c6f..23aa21a2 100755 --- a/gcp/nanoclaw.sh +++ b/gcp/nanoclaw.sh @@ -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" diff --git a/gcp/openclaw.sh b/gcp/openclaw.sh index b7cf9b60..b09a9f94 100755 --- a/gcp/openclaw.sh +++ b/gcp/openclaw.sh @@ -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" diff --git a/hetzner/aider.sh b/hetzner/aider.sh index 965e66c2..63582429 100755 --- a/hetzner/aider.sh +++ b/hetzner/aider.sh @@ -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}" diff --git a/hetzner/amazonq.sh b/hetzner/amazonq.sh index e638b834..8ff732ad 100755 --- a/hetzner/amazonq.sh +++ b/hetzner/amazonq.sh @@ -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" diff --git a/hetzner/claude.sh b/hetzner/claude.sh index 99a2596a..40f9a993 100755 --- a/hetzner/claude.sh +++ b/hetzner/claude.sh @@ -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" diff --git a/hetzner/cline.sh b/hetzner/cline.sh index 620e0e71..2f64f2f4 100755 --- a/hetzner/cline.sh +++ b/hetzner/cline.sh @@ -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" diff --git a/hetzner/codex.sh b/hetzner/codex.sh index 1b7deee5..3e2691b7 100755 --- a/hetzner/codex.sh +++ b/hetzner/codex.sh @@ -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" diff --git a/hetzner/gemini.sh b/hetzner/gemini.sh index 6ec50d03..403bae1f 100755 --- a/hetzner/gemini.sh +++ b/hetzner/gemini.sh @@ -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" diff --git a/hetzner/goose.sh b/hetzner/goose.sh index ca33b8af..d6a11b9d 100755 --- a/hetzner/goose.sh +++ b/hetzner/goose.sh @@ -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" diff --git a/hetzner/interpreter.sh b/hetzner/interpreter.sh index 1291920d..ea583391 100755 --- a/hetzner/interpreter.sh +++ b/hetzner/interpreter.sh @@ -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" diff --git a/hetzner/nanoclaw.sh b/hetzner/nanoclaw.sh index b161a9ac..08c7930b 100755 --- a/hetzner/nanoclaw.sh +++ b/hetzner/nanoclaw.sh @@ -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" diff --git a/hetzner/openclaw.sh b/hetzner/openclaw.sh index 33cd5493..6a21a3a7 100755 --- a/hetzner/openclaw.sh +++ b/hetzner/openclaw.sh @@ -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" diff --git a/improve.sh b/improve.sh index 09e2618e..d088a71b 100755 --- a/improve.sh +++ b/improve.sh @@ -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 </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}" diff --git a/lambda/amazonq.sh b/lambda/amazonq.sh index 763fb840..83bdb613 100755 --- a/lambda/amazonq.sh +++ b/lambda/amazonq.sh @@ -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" diff --git a/lambda/claude.sh b/lambda/claude.sh index 2367e250..09e40af5 100755 --- a/lambda/claude.sh +++ b/lambda/claude.sh @@ -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" diff --git a/lambda/cline.sh b/lambda/cline.sh index 094b7044..5a69244e 100755 --- a/lambda/cline.sh +++ b/lambda/cline.sh @@ -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" diff --git a/lambda/codex.sh b/lambda/codex.sh index f9cd0c1f..82d4863f 100755 --- a/lambda/codex.sh +++ b/lambda/codex.sh @@ -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" diff --git a/lambda/gemini.sh b/lambda/gemini.sh index 73672743..bc27dc57 100755 --- a/lambda/gemini.sh +++ b/lambda/gemini.sh @@ -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" diff --git a/lambda/goose.sh b/lambda/goose.sh index 78e1a811..1514528e 100755 --- a/lambda/goose.sh +++ b/lambda/goose.sh @@ -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" diff --git a/lambda/interpreter.sh b/lambda/interpreter.sh index 8cbf7373..71b03ad0 100755 --- a/lambda/interpreter.sh +++ b/lambda/interpreter.sh @@ -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" diff --git a/lambda/lib/common.sh b/lambda/lib/common.sh index 371da42b..30eda73a 100644 --- a/lambda/lib/common.sh +++ b/lambda/lib/common.sh @@ -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" } diff --git a/lambda/nanoclaw.sh b/lambda/nanoclaw.sh index a3bf8942..7b5b0cc5 100755 --- a/lambda/nanoclaw.sh +++ b/lambda/nanoclaw.sh @@ -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" diff --git a/lambda/openclaw.sh b/lambda/openclaw.sh index 3edb6fa4..5cec6098 100755 --- a/lambda/openclaw.sh +++ b/lambda/openclaw.sh @@ -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" diff --git a/linode/aider.sh b/linode/aider.sh index c21e6863..38dc97da 100755 --- a/linode/aider.sh +++ b/linode/aider.sh @@ -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}" diff --git a/linode/amazonq.sh b/linode/amazonq.sh index 3b59f656..5838abb7 100755 --- a/linode/amazonq.sh +++ b/linode/amazonq.sh @@ -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" diff --git a/linode/claude.sh b/linode/claude.sh index 311a4739..8d4284f5 100755 --- a/linode/claude.sh +++ b/linode/claude.sh @@ -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" diff --git a/linode/cline.sh b/linode/cline.sh index 4659725d..03159adf 100755 --- a/linode/cline.sh +++ b/linode/cline.sh @@ -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" diff --git a/linode/codex.sh b/linode/codex.sh index b9da356e..fb0dfc3d 100755 --- a/linode/codex.sh +++ b/linode/codex.sh @@ -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" diff --git a/linode/gemini.sh b/linode/gemini.sh index 63622e88..ded7d7b4 100755 --- a/linode/gemini.sh +++ b/linode/gemini.sh @@ -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" diff --git a/linode/goose.sh b/linode/goose.sh index 4ca1ba84..69fa5eab 100755 --- a/linode/goose.sh +++ b/linode/goose.sh @@ -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" diff --git a/linode/interpreter.sh b/linode/interpreter.sh index 7ebad147..bfaa41f4 100755 --- a/linode/interpreter.sh +++ b/linode/interpreter.sh @@ -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" diff --git a/linode/nanoclaw.sh b/linode/nanoclaw.sh index 27f4d9b1..548b8963 100755 --- a/linode/nanoclaw.sh +++ b/linode/nanoclaw.sh @@ -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" diff --git a/linode/openclaw.sh b/linode/openclaw.sh index a12a9b6b..f82e30e5 100755 --- a/linode/openclaw.sh +++ b/linode/openclaw.sh @@ -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" diff --git a/modal/aider.sh b/modal/aider.sh index 92f89bbd..d806f35a 100755 --- a/modal/aider.sh +++ b/modal/aider.sh @@ -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 diff --git a/modal/amazonq.sh b/modal/amazonq.sh index 85231ab5..229f3305 100755 --- a/modal/amazonq.sh +++ b/modal/amazonq.sh @@ -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 diff --git a/modal/claude.sh b/modal/claude.sh index f51a6a45..227f773d 100755 --- a/modal/claude.sh +++ b/modal/claude.sh @@ -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 diff --git a/modal/cline.sh b/modal/cline.sh index 78d052ab..46c02679 100755 --- a/modal/cline.sh +++ b/modal/cline.sh @@ -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 diff --git a/modal/codex.sh b/modal/codex.sh index ded2711d..9e7d6c93 100755 --- a/modal/codex.sh +++ b/modal/codex.sh @@ -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 diff --git a/modal/gemini.sh b/modal/gemini.sh index 8f99e0e8..3c64d116 100755 --- a/modal/gemini.sh +++ b/modal/gemini.sh @@ -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 diff --git a/modal/goose.sh b/modal/goose.sh index da203d2d..271bbbee 100755 --- a/modal/goose.sh +++ b/modal/goose.sh @@ -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 diff --git a/modal/interpreter.sh b/modal/interpreter.sh index 34716510..4b49d968 100755 --- a/modal/interpreter.sh +++ b/modal/interpreter.sh @@ -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 diff --git a/modal/lib/common.sh b/modal/lib/common.sh index 88bfa500..6a1aa23d 100644 --- a/modal/lib/common.sh +++ b/modal/lib/common.sh @@ -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" } diff --git a/modal/nanoclaw.sh b/modal/nanoclaw.sh index 9663fe99..75fefedf 100755 --- a/modal/nanoclaw.sh +++ b/modal/nanoclaw.sh @@ -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 diff --git a/modal/openclaw.sh b/modal/openclaw.sh index b8939556..1bdd6f4a 100755 --- a/modal/openclaw.sh +++ b/modal/openclaw.sh @@ -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 diff --git a/shared/common.sh b/shared/common.sh index e4c0c085..821eefaf 100644 --- a/shared/common.sh +++ b/shared/common.sh @@ -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 diff --git a/sprite/aider.sh b/sprite/aider.sh index fc708877..43babe65 100755 --- a/sprite/aider.sh +++ b/sprite/aider.sh @@ -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}" diff --git a/sprite/amazonq.sh b/sprite/amazonq.sh index 39a2924e..dc72f446 100755 --- a/sprite/amazonq.sh +++ b/sprite/amazonq.sh @@ -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" diff --git a/sprite/claude.sh b/sprite/claude.sh index 67a2f7b5..362c6cbd 100755 --- a/sprite/claude.sh +++ b/sprite/claude.sh @@ -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" diff --git a/sprite/cline.sh b/sprite/cline.sh index 1f99ee08..6b87e01f 100755 --- a/sprite/cline.sh +++ b/sprite/cline.sh @@ -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" diff --git a/sprite/codex.sh b/sprite/codex.sh index 4dd74820..c6b4a9c6 100755 --- a/sprite/codex.sh +++ b/sprite/codex.sh @@ -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" diff --git a/sprite/gemini.sh b/sprite/gemini.sh index 3b8bfa4d..9908ef23 100755 --- a/sprite/gemini.sh +++ b/sprite/gemini.sh @@ -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" diff --git a/sprite/goose.sh b/sprite/goose.sh index f38b6738..fb309e7c 100755 --- a/sprite/goose.sh +++ b/sprite/goose.sh @@ -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" diff --git a/sprite/interpreter.sh b/sprite/interpreter.sh index 9a85385b..ae462ded 100755 --- a/sprite/interpreter.sh +++ b/sprite/interpreter.sh @@ -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" diff --git a/sprite/lib/common.sh b/sprite/lib/common.sh index cb3be6bc..7802b116 100644 --- a/sprite/lib/common.sh +++ b/sprite/lib/common.sh @@ -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 diff --git a/sprite/nanoclaw.sh b/sprite/nanoclaw.sh index a241ce03..7b6325b6 100644 --- a/sprite/nanoclaw.sh +++ b/sprite/nanoclaw.sh @@ -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,43 +17,43 @@ 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 Node.js dependencies log_warn "Installing Node.js..." -run_sprite "$SPRITE_NAME" "/.sprite/languages/bun/bin/bun install -g tsx" +run_sprite "${SPRITE_NAME}" "/.sprite/languages/bun/bin/bun install -g tsx" # Clone nanoclaw log_warn "Cloning nanoclaw..." -run_sprite "$SPRITE_NAME" "git clone https://github.com/gavrielc/nanoclaw.git ~/nanoclaw && cd ~/nanoclaw && npm install && npm run build" +run_sprite "${SPRITE_NAME}" "git clone https://github.com/gavrielc/nanoclaw.git ~/nanoclaw && cd ~/nanoclaw && npm install && npm run build" # Get OpenRouter API key via OAuth 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" \ - "ANTHROPIC_API_KEY=$OPENROUTER_API_KEY" \ +inject_env_vars_sprite "${SPRITE_NAME}" \ + "OPENROUTER_API_KEY=${OPENROUTER_API_KEY}" \ + "ANTHROPIC_API_KEY=${OPENROUTER_API_KEY}" \ "ANTHROPIC_BASE_URL=https://openrouter.ai/api" # 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 -sprite exec -s "$SPRITE_NAME" -file "$DOTENV_TEMP:/tmp/nanoclaw_env" -- bash -c "mv /tmp/nanoclaw_env ~/nanoclaw/.env" -rm "$DOTENV_TEMP" +sprite exec -s "${SPRITE_NAME}" -file "${DOTENV_TEMP}:/tmp/nanoclaw_env" -- bash -c "mv /tmp/nanoclaw_env ~/nanoclaw/.env" +rm "${DOTENV_TEMP}" echo "" log_info "✅ Sprite setup completed successfully!" @@ -63,4 +63,4 @@ echo "" log_warn "Starting nanoclaw..." log_warn "You will need to scan a WhatsApp QR code to authenticate." echo "" -sprite exec -s "$SPRITE_NAME" -tty -- zsh -c "cd ~/nanoclaw && source ~/.zshrc && npm run dev" +sprite exec -s "${SPRITE_NAME}" -tty -- zsh -c "cd ~/nanoclaw && source ~/.zshrc && npm run dev" diff --git a/sprite/openclaw.sh b/sprite/openclaw.sh index 3be3131f..d26f7e63 100755 --- a/sprite/openclaw.sh +++ b/sprite/openclaw.sh @@ -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,16 +17,16 @@ ensure_sprite_installed ensure_sprite_authenticated SPRITE_NAME=$(get_sprite_name) -ensure_sprite_exists "$SPRITE_NAME" 3 +ensure_sprite_exists "${SPRITE_NAME}" 3 log_warn "Setting up sprite environment..." # Configure shell environment -setup_shell_environment "$SPRITE_NAME" +setup_shell_environment "${SPRITE_NAME}" # Install openclaw using bun log_warn "Installing openclaw..." -run_sprite "$SPRITE_NAME" "/.sprite/languages/bun/bin/bun install -g openclaw" +run_sprite "${SPRITE_NAME}" "/.sprite/languages/bun/bin/bun install -g openclaw" # Get OpenRouter API key via OAuth echo "" @@ -36,15 +36,15 @@ OPENROUTER_API_KEY=$(get_openrouter_api_key_oauth 5180) MODEL_ID=$(get_model_id_interactive "openrouter/auto" "Openclaw") || exit 1 log_warn "Setting up environment variables..." -inject_env_vars_sprite "$SPRITE_NAME" \ - "OPENROUTER_API_KEY=$OPENROUTER_API_KEY" \ - "ANTHROPIC_API_KEY=$OPENROUTER_API_KEY" \ +inject_env_vars_sprite "${SPRITE_NAME}" \ + "OPENROUTER_API_KEY=${OPENROUTER_API_KEY}" \ + "ANTHROPIC_API_KEY=${OPENROUTER_API_KEY}" \ "ANTHROPIC_BASE_URL=https://openrouter.ai/api" # Setup openclaw to bypass initial settings -setup_openclaw_config "$OPENROUTER_API_KEY" "$MODEL_ID" \ - "upload_file_sprite $SPRITE_NAME" \ - "run_sprite $SPRITE_NAME" +setup_openclaw_config "${OPENROUTER_API_KEY}" "${MODEL_ID}" \ + "upload_file_sprite ${SPRITE_NAME}" \ + "run_sprite ${SPRITE_NAME}" echo "" log_info "✅ Sprite setup completed successfully!" @@ -52,6 +52,6 @@ echo "" # Start openclaw gateway in background and run openclaw tui log_warn "Starting openclaw..." -sprite exec -s "$SPRITE_NAME" -- zsh -c "source ~/.zshrc && nohup openclaw gateway > /tmp/openclaw-gateway.log 2>&1 &" +sprite exec -s "${SPRITE_NAME}" -- zsh -c "source ~/.zshrc && nohup openclaw gateway > /tmp/openclaw-gateway.log 2>&1 &" sleep 2 -sprite exec -s "$SPRITE_NAME" -tty -- zsh -c "source ~/.zshrc && openclaw tui" +sprite exec -s "${SPRITE_NAME}" -tty -- zsh -c "source ~/.zshrc && openclaw tui" diff --git a/test/run.sh b/test/run.sh index 9c035b13..8b79b021 100644 --- a/test/run.sh +++ b/test/run.sh @@ -18,13 +18,13 @@ set -uo pipefail REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" TEST_DIR=$(mktemp -d) -MOCK_LOG="$TEST_DIR/sprite_calls.log" +MOCK_LOG="${TEST_DIR}/sprite_calls.log" PASSED=0 FAILED=0 FILTER="${1:-}" REMOTE=false -if [[ "$FILTER" == "--remote" ]]; then +if [[ "${FILTER}" == "--remote" ]]; then REMOTE=true FILTER="${2:-}" fi @@ -36,16 +36,16 @@ YELLOW='\033[1;33m' NC='\033[0m' cleanup() { - rm -rf "$TEST_DIR" + rm -rf "${TEST_DIR}" } trap 'cleanup' EXIT # --- Mock sprite CLI --- # Records every call to a log, returns success for expected commands setup_mocks() { - cat > "$TEST_DIR/sprite" << 'MOCK' + cat > "${TEST_DIR}/sprite" << 'MOCK' #!/bin/bash -echo "sprite $*" >> "$MOCK_LOG" +echo "sprite $*" >> "${MOCK_LOG}" case "$1" in org) exit 0 ;; # auth check passes @@ -58,7 +58,7 @@ case "$1" in fi # If -tty, this is the final interactive launch — signal success and exit if [[ "$*" == *"-tty"* ]]; then - echo "[MOCK] Would launch interactive session: $*" >> "$MOCK_LOG" + echo "[MOCK] Would launch interactive session: $*" >> "${MOCK_LOG}" exit 0 fi # Regular exec — just succeed @@ -68,59 +68,59 @@ case "$1" in *) exit 0 ;; esac MOCK - chmod +x "$TEST_DIR/sprite" + chmod +x "${TEST_DIR}/sprite" } # --- Mock other commands that shouldn't run for real --- setup_extra_mocks() { # mock claude (for claude.sh install step) - cat > "$TEST_DIR/claude" << 'MOCK' + cat > "${TEST_DIR}/claude" << 'MOCK' #!/bin/bash -echo "claude $*" >> "$MOCK_LOG" +echo "claude $*" >> "${MOCK_LOG}" exit 0 MOCK - chmod +x "$TEST_DIR/claude" + chmod +x "${TEST_DIR}/claude" # mock openssl - cat > "$TEST_DIR/openssl" << 'MOCK' + cat > "${TEST_DIR}/openssl" << 'MOCK' #!/bin/bash echo "mock-gateway-token-abc123" MOCK - chmod +x "$TEST_DIR/openssl" + chmod +x "${TEST_DIR}/openssl" } # --- Assertions --- assert_contains() { local file="$1" pattern="$2" msg="$3" - if grep -qE "$pattern" "$file" 2>/dev/null; then - echo -e " ${GREEN}✓${NC} $msg" + if grep -qE "${pattern}" "${file}" 2>/dev/null; then + echo -e " ${GREEN}✓${NC} ${msg}" ((PASSED++)) else - echo -e " ${RED}✗${NC} $msg" - echo -e " expected pattern: $pattern" - echo -e " in: $file" + echo -e " ${RED}✗${NC} ${msg}" + echo -e " expected pattern: ${pattern}" + echo -e " in: ${file}" ((FAILED++)) fi } assert_not_contains() { local file="$1" pattern="$2" msg="$3" - if ! grep -qE "$pattern" "$file" 2>/dev/null; then - echo -e " ${GREEN}✓${NC} $msg" + if ! grep -qE "${pattern}" "${file}" 2>/dev/null; then + echo -e " ${GREEN}✓${NC} ${msg}" ((PASSED++)) else - echo -e " ${RED}✗${NC} $msg" + echo -e " ${RED}✗${NC} ${msg}" ((FAILED++)) fi } assert_exit_code() { local actual="$1" expected="$2" msg="$3" - if [[ "$actual" -eq "$expected" ]]; then - echo -e " ${GREEN}✓${NC} $msg" + if [[ "${actual}" -eq "${expected}" ]]; then + echo -e " ${GREEN}✓${NC} ${msg}" ((PASSED++)) else - echo -e " ${RED}✗${NC} $msg (got exit code $actual, expected $expected)" + echo -e " ${RED}✗${NC} ${msg} (got exit code ${actual}, expected ${expected})" ((FAILED++)) fi } @@ -128,57 +128,57 @@ assert_exit_code() { # --- Test runner for a single script --- run_script_test() { local script_name="$1" - local script_path="$REPO_ROOT/sprite/${script_name}.sh" - local output_file="$TEST_DIR/${script_name}_output.log" + local script_path="${REPO_ROOT}/sprite/${script_name}.sh" + local output_file="${TEST_DIR}/${script_name}_output.log" echo "" echo -e "${YELLOW}━━━ Testing ${script_name}.sh ━━━${NC}" # Reset mock log - > "$MOCK_LOG" + > "${MOCK_LOG}" # Run the script with mocked PATH and env vars (timeout 30s) local exit_code=0 - MOCK_LOG="$MOCK_LOG" \ + MOCK_LOG="${MOCK_LOG}" \ SPRITE_NAME="test-sprite-${script_name}" \ OPENROUTER_API_KEY="sk-or-v1-0000000000000000000000000000000000000000000000000000000000000000" \ - PATH="$TEST_DIR:$PATH" \ - timeout 30 bash "$script_path" > "$output_file" 2>&1 || exit_code=$? + PATH="${TEST_DIR}:${PATH}" \ + timeout 30 bash "${script_path}" > "${output_file}" 2>&1 || exit_code=$? - assert_exit_code "$exit_code" 0 "Script exits successfully" + assert_exit_code "${exit_code}" 0 "Script exits successfully" # Common assertions for all scripts - assert_contains "$MOCK_LOG" "sprite org list" "Checks sprite authentication" - assert_contains "$MOCK_LOG" "sprite list" "Checks if sprite exists" - assert_contains "$MOCK_LOG" "sprite create.*test-sprite-${script_name}" "Creates sprite with correct name" - assert_contains "$MOCK_LOG" "sprite exec.*test-sprite-${script_name}" "Runs commands on sprite" + assert_contains "${MOCK_LOG}" "sprite org list" "Checks sprite authentication" + assert_contains "${MOCK_LOG}" "sprite list" "Checks if sprite exists" + assert_contains "${MOCK_LOG}" "sprite create.*test-sprite-${script_name}" "Creates sprite with correct name" + assert_contains "${MOCK_LOG}" "sprite exec.*test-sprite-${script_name}" "Runs commands on sprite" # Check env var injection (temp file upload) - assert_contains "$MOCK_LOG" "sprite exec.*-file.*/tmp/env_config" "Uploads env config to sprite" + assert_contains "${MOCK_LOG}" "sprite exec.*-file.*/tmp/env_config" "Uploads env config to sprite" # Check final interactive launch (flag order varies: -s NAME -tty or -tty -s NAME) - assert_contains "$MOCK_LOG" "sprite exec.*-tty.*" "Launches interactive session" + assert_contains "${MOCK_LOG}" "sprite exec.*-tty.*" "Launches interactive session" # Script-specific assertions - case "$script_name" in + case "${script_name}" in claude) - assert_contains "$MOCK_LOG" "claude install" "Installs Claude Code" - assert_contains "$MOCK_LOG" "sprite exec.*-file.*/tmp/claude_settings" "Uploads Claude settings" - assert_contains "$MOCK_LOG" "sprite exec.*-file.*/tmp/claude_global" "Uploads Claude global state" + assert_contains "${MOCK_LOG}" "claude install" "Installs Claude Code" + assert_contains "${MOCK_LOG}" "sprite exec.*-file.*/tmp/claude_settings" "Uploads Claude settings" + assert_contains "${MOCK_LOG}" "sprite exec.*-file.*/tmp/claude_global" "Uploads Claude global state" ;; openclaw) - assert_contains "$MOCK_LOG" "sprite exec.*bun install -g openclaw" "Installs openclaw via bun" - assert_contains "$MOCK_LOG" "sprite exec.*openclaw gateway" "Starts openclaw gateway" + assert_contains "${MOCK_LOG}" "sprite exec.*bun install -g openclaw" "Installs openclaw via bun" + assert_contains "${MOCK_LOG}" "sprite exec.*openclaw gateway" "Starts openclaw gateway" ;; nanoclaw) - assert_contains "$MOCK_LOG" "sprite exec.*git clone.*nanoclaw" "Clones nanoclaw repo" - assert_contains "$MOCK_LOG" "sprite exec.*-file.*/tmp/nanoclaw_env" "Uploads nanoclaw .env" + assert_contains "${MOCK_LOG}" "sprite exec.*git clone.*nanoclaw" "Clones nanoclaw repo" + assert_contains "${MOCK_LOG}" "sprite exec.*-file.*/tmp/nanoclaw_env" "Uploads nanoclaw .env" ;; esac # Check no temp files leaked - local leaked_temps=$(find /tmp -maxdepth 1 -name "tmp.*" -newer "$MOCK_LOG" 2>/dev/null | wc -l) - if [[ "$leaked_temps" -eq 0 ]]; then + local leaked_temps=$(find /tmp -maxdepth 1 -name "tmp.*" -newer "${MOCK_LOG}" 2>/dev/null | wc -l) + if [[ "${leaked_temps}" -eq 0 ]]; then echo -e " ${GREEN}✓${NC} No temp files leaked" ((PASSED++)) fi @@ -192,31 +192,31 @@ test_common_source() { # Test 1: Source locally and check all functions exist local output output=$(bash -c ' - source "'"$REPO_ROOT"'/sprite/lib/common.sh" + source "'"${REPO_ROOT}"'/sprite/lib/common.sh" for fn in log_info log_warn log_error safe_read \ ensure_sprite_installed ensure_sprite_authenticated \ get_sprite_name ensure_sprite_exists verify_sprite_connectivity \ run_sprite setup_shell_environment \ get_openrouter_api_key_manual try_oauth_flow \ get_openrouter_api_key_oauth open_browser; do - type "$fn" &>/dev/null && echo "OK:$fn" || echo "MISSING:$fn" + type "${fn}" &>/dev/null && echo "OK:${fn}" || echo "MISSING:${fn}" done ' 2>/dev/null) - local missing=$(echo "$output" | grep "^MISSING:" || true) - if [[ -z "$missing" ]]; then + local missing=$(echo "${output}" | grep "^MISSING:" || true) + if [[ -z "${missing}" ]]; then echo -e " ${GREEN}✓${NC} All functions defined" ((PASSED++)) else - echo -e " ${RED}✗${NC} Missing functions: $missing" + echo -e " ${RED}✗${NC} Missing functions: ${missing}" ((FAILED++)) fi # Test 2: log functions write to stderr, not stdout local stdout stderr - stdout=$(timeout 5 bash -c 'source "'"$REPO_ROOT"'/sprite/lib/common.sh" && log_info "test"' /dev/null) - stderr=$(timeout 5 bash -c 'source "'"$REPO_ROOT"'/sprite/lib/common.sh" && log_info "test"' &1 >/dev/null) - if [[ -z "$stdout" && -n "$stderr" ]]; then + stdout=$(timeout 5 bash -c 'source "'"${REPO_ROOT}"'/sprite/lib/common.sh" && log_info "test"' /dev/null) + stderr=$(timeout 5 bash -c 'source "'"${REPO_ROOT}"'/sprite/lib/common.sh" && log_info "test"' &1 >/dev/null) + if [[ -z "${stdout}" && -n "${stderr}" ]]; then echo -e " ${GREEN}✓${NC} Log functions write to stderr" ((PASSED++)) else @@ -226,19 +226,19 @@ test_common_source() { # Test 3: get_sprite_name uses SPRITE_NAME env var local name - name=$(timeout 5 bash -c 'SPRITE_NAME=from-env; source "'"$REPO_ROOT"'/sprite/lib/common.sh" && get_sprite_name' 2>/dev/null) - if [[ "$name" == "from-env" ]]; then + name=$(timeout 5 bash -c 'SPRITE_NAME=from-env; source "'"${REPO_ROOT}"'/sprite/lib/common.sh" && get_sprite_name' 2>/dev/null) + if [[ "${name}" == "from-env" ]]; then echo -e " ${GREEN}✓${NC} get_sprite_name reads SPRITE_NAME env var" ((PASSED++)) else - echo -e " ${RED}✗${NC} get_sprite_name should return 'from-env', got '$name'" + echo -e " ${RED}✗${NC} get_sprite_name should return 'from-env', got '${name}'" ((FAILED++)) fi # Test 4: get_sprite_name fails gracefully without TTY or env var local rc=0 - timeout 5 bash -c 'SPRITE_NAME=""; source "'"$REPO_ROOT"'/sprite/lib/common.sh" && get_sprite_name' /dev/null 2>&1 || rc=$? - if [[ "$rc" -ne 0 ]]; then + timeout 5 bash -c 'SPRITE_NAME=""; source "'"${REPO_ROOT}"'/sprite/lib/common.sh" && get_sprite_name' /dev/null 2>&1 || rc=$? + if [[ "${rc}" -ne 0 ]]; then echo -e " ${GREEN}✓${NC} get_sprite_name fails without TTY or env var" ((PASSED++)) else @@ -247,7 +247,7 @@ test_common_source() { fi # Test 5: Syntax check - if bash -n "$REPO_ROOT/sprite/lib/common.sh" 2>/dev/null; then + if bash -n "${REPO_ROOT}/sprite/lib/common.sh" 2>/dev/null; then echo -e " ${GREEN}✓${NC} Syntax valid" ((PASSED++)) else @@ -256,13 +256,13 @@ test_common_source() { fi # Test 6: Remote source (if --remote) - if [[ "$REMOTE" == true ]]; then + if [[ "${REMOTE}" == true ]]; then local remote_fns remote_fns=$(bash -c ' source <(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/sprite/lib/common.sh) type log_info &>/dev/null && echo "OK" || echo "FAIL" ' 2>/dev/null) - if [[ "$remote_fns" == "OK" ]]; then + if [[ "${remote_fns}" == "OK" ]]; then echo -e " ${GREEN}✓${NC} Remote source from GitHub works" ((PASSED++)) else @@ -279,8 +279,8 @@ test_shared_common() { # Test 1: validate_model_id accepts valid model IDs local result - result=$(bash -c 'source "'"$REPO_ROOT"'/shared/common.sh" && validate_model_id "anthropic/claude-3.5-sonnet" && echo "valid"' 2>/dev/null) - if [[ "$result" == "valid" ]]; then + result=$(bash -c 'source "'"${REPO_ROOT}"'/shared/common.sh" && validate_model_id "anthropic/claude-3.5-sonnet" && echo "valid"' 2>/dev/null) + if [[ "${result}" == "valid" ]]; then echo -e " ${GREEN}✓${NC} validate_model_id accepts valid model IDs" ((PASSED++)) else @@ -290,8 +290,8 @@ test_shared_common() { # Test 2: validate_model_id rejects invalid characters local rc=0 - bash -c 'source "'"$REPO_ROOT"'/shared/common.sh" && validate_model_id "bad;model"' /dev/null 2>&1 || rc=$? - if [[ "$rc" -ne 0 ]]; then + bash -c 'source "'"${REPO_ROOT}"'/shared/common.sh" && validate_model_id "bad;model"' /dev/null 2>&1 || rc=$? + if [[ "${rc}" -ne 0 ]]; then echo -e " ${GREEN}✓${NC} validate_model_id rejects invalid characters" ((PASSED++)) else @@ -300,8 +300,8 @@ test_shared_common() { fi # Test 3: validate_model_id accepts empty string - result=$(bash -c 'source "'"$REPO_ROOT"'/shared/common.sh" && validate_model_id "" && echo "valid"' 2>/dev/null) - if [[ "$result" == "valid" ]]; then + result=$(bash -c 'source "'"${REPO_ROOT}"'/shared/common.sh" && validate_model_id "" && echo "valid"' 2>/dev/null) + if [[ "${result}" == "valid" ]]; then echo -e " ${GREEN}✓${NC} validate_model_id accepts empty string" ((PASSED++)) else @@ -310,8 +310,8 @@ test_shared_common() { fi # Test 4: json_escape handles special characters - result=$(bash -c 'source "'"$REPO_ROOT"'/shared/common.sh" && json_escape "test\"quote"' 2>/dev/null) - if [[ "$result" == *'\\"'* ]] || [[ "$result" == *'\"'* ]]; then + result=$(bash -c 'source "'"${REPO_ROOT}"'/shared/common.sh" && json_escape "test\"quote"' 2>/dev/null) + if [[ "${result}" == *'\\"'* ]] || [[ "${result}" == *'\"'* ]]; then echo -e " ${GREEN}✓${NC} json_escape handles special characters" ((PASSED++)) else @@ -320,22 +320,22 @@ test_shared_common() { fi # Test 5: generate_ssh_key_if_missing creates key if missing - local test_key="$TEST_DIR/test_id_ed25519" - bash -c 'source "'"$REPO_ROOT"'/shared/common.sh" && generate_ssh_key_if_missing "'"$test_key"'"' >/dev/null 2>&1 - if [[ -f "$test_key" && -f "${test_key}.pub" ]]; then + local test_key="${TEST_DIR}/test_id_ed25519" + bash -c 'source "'"${REPO_ROOT}"'/shared/common.sh" && generate_ssh_key_if_missing "'"${test_key}"'"' >/dev/null 2>&1 + if [[ -f "${test_key}" && -f "${test_key}.pub" ]]; then echo -e " ${GREEN}✓${NC} generate_ssh_key_if_missing creates key" ((PASSED++)) else - echo -e " ${RED}✗${NC} generate_ssh_key_if_missing should create key at $test_key" + echo -e " ${RED}✗${NC} generate_ssh_key_if_missing should create key at ${test_key}" ((FAILED++)) fi # Test 6: generate_ssh_key_if_missing skips if key exists - local mtime_before=$(stat -c %Y "$test_key" 2>/dev/null || stat -f %m "$test_key" 2>/dev/null) + local mtime_before=$(stat -c %Y "${test_key}" 2>/dev/null || stat -f %m "${test_key}" 2>/dev/null) sleep 1 - bash -c 'source "'"$REPO_ROOT"'/shared/common.sh" && generate_ssh_key_if_missing "'"$test_key"'"' >/dev/null 2>&1 - local mtime_after=$(stat -c %Y "$test_key" 2>/dev/null || stat -f %m "$test_key" 2>/dev/null) - if [[ "$mtime_before" == "$mtime_after" ]]; then + bash -c 'source "'"${REPO_ROOT}"'/shared/common.sh" && generate_ssh_key_if_missing "'"${test_key}"'"' >/dev/null 2>&1 + local mtime_after=$(stat -c %Y "${test_key}" 2>/dev/null || stat -f %m "${test_key}" 2>/dev/null) + if [[ "${mtime_before}" == "${mtime_after}" ]]; then echo -e " ${GREEN}✓${NC} generate_ssh_key_if_missing skips existing key" ((PASSED++)) else @@ -344,17 +344,17 @@ test_shared_common() { fi # Test 7: get_ssh_fingerprint returns fingerprint - result=$(bash -c 'source "'"$REPO_ROOT"'/shared/common.sh" && get_ssh_fingerprint "'"${test_key}.pub"'"' 2>/dev/null) - if [[ -n "$result" && "$result" =~ ^[a-f0-9:]+$ ]]; then + result=$(bash -c 'source "'"${REPO_ROOT}"'/shared/common.sh" && get_ssh_fingerprint "'"${test_key}.pub"'"' 2>/dev/null) + if [[ -n "${result}" && "${result}" =~ ^[a-f0-9:]+$ ]]; then echo -e " ${GREEN}✓${NC} get_ssh_fingerprint returns valid fingerprint" ((PASSED++)) else - echo -e " ${RED}✗${NC} get_ssh_fingerprint should return hex fingerprint, got '$result'" + echo -e " ${RED}✗${NC} get_ssh_fingerprint should return hex fingerprint, got '${result}'" ((FAILED++)) fi # Test 8: Syntax check for shared/common.sh - if bash -n "$REPO_ROOT/shared/common.sh" 2>/dev/null; then + if bash -n "${REPO_ROOT}/shared/common.sh" 2>/dev/null; then echo -e " ${GREEN}✓${NC} shared/common.sh syntax valid" ((PASSED++)) else @@ -364,34 +364,34 @@ test_shared_common() { # Test 9: All logging functions exist in shared/common.sh output=$(bash -c ' - source "'"$REPO_ROOT"'/shared/common.sh" + source "'"${REPO_ROOT}"'/shared/common.sh" for fn in log_info log_warn log_error; do - type "$fn" &>/dev/null && echo "OK:$fn" || echo "MISSING:$fn" + type "${fn}" &>/dev/null && echo "OK:${fn}" || echo "MISSING:${fn}" done ' 2>/dev/null) - missing=$(echo "$output" | grep "^MISSING:" || true) - if [[ -z "$missing" ]]; then + missing=$(echo "${output}" | grep "^MISSING:" || true) + if [[ -z "${missing}" ]]; then echo -e " ${GREEN}✓${NC} All logging functions exist in shared/common.sh" ((PASSED++)) else - echo -e " ${RED}✗${NC} Missing logging functions: $missing" + echo -e " ${RED}✗${NC} Missing logging functions: ${missing}" ((FAILED++)) fi # Test 10: extract_ssh_key_ids parses JSON correctly local mock_json='{"ssh_keys":[{"id":123},{"id":456}]}' - result=$(bash -c 'source "'"$REPO_ROOT"'/shared/common.sh" && echo '"'$mock_json'"' | extract_ssh_key_ids "$(cat)" "ssh_keys"' 2>/dev/null) - if [[ "$result" == "[123, 456]" ]] || [[ "$result" == "[123,456]" ]]; then + result=$(bash -c 'source "'"${REPO_ROOT}"'/shared/common.sh" && echo '"'${mock_json}'"' | extract_ssh_key_ids "$(cat)" "ssh_keys"' 2>/dev/null) + if [[ "${result}" == "[123, 456]" ]] || [[ "${result}" == "[123,456]" ]]; then echo -e " ${GREEN}✓${NC} extract_ssh_key_ids parses JSON correctly" ((PASSED++)) else - echo -e " ${RED}✗${NC} extract_ssh_key_ids should return [123, 456], got '$result'" + echo -e " ${RED}✗${NC} extract_ssh_key_ids should return [123, 456], got '${result}'" ((FAILED++)) fi # Test 11: nc_listen detects busybox nc and adds -p flag result=$(bash -c ' - source "'"$REPO_ROOT"'/shared/common.sh" + source "'"${REPO_ROOT}"'/shared/common.sh" # Mock nc command that returns busybox help nc() { if [[ "$1" == "--help" ]]; then @@ -403,17 +403,17 @@ test_shared_common() { export -f nc nc_listen 8080 ' 2>/dev/null) - if [[ "$result" == *"-l -p 8080"* ]]; then + if [[ "${result}" == *"-l -p 8080"* ]]; then echo -e " ${GREEN}✓${NC} nc_listen adds -p flag for busybox nc" ((PASSED++)) else - echo -e " ${RED}✗${NC} nc_listen should add -p flag for busybox, got '$result'" + echo -e " ${RED}✗${NC} nc_listen should add -p flag for busybox, got '${result}'" ((FAILED++)) fi # Test 12: nc_listen uses standard nc without -p flag result=$(bash -c ' - source "'"$REPO_ROOT"'/shared/common.sh" + source "'"${REPO_ROOT}"'/shared/common.sh" # Mock nc command that returns non-busybox help nc() { if [[ "$1" == "--help" ]]; then @@ -425,41 +425,41 @@ test_shared_common() { export -f nc nc_listen 8080 ' 2>/dev/null) - if [[ "$result" == *"-l 8080"* ]] && [[ "$result" != *"-p"* ]]; then + if [[ "${result}" == *"-l 8080"* ]] && [[ "${result}" != *"-p"* ]]; then echo -e " ${GREEN}✓${NC} nc_listen uses standard nc without -p flag" ((PASSED++)) else - echo -e " ${RED}✗${NC} nc_listen should omit -p flag for standard nc, got '$result'" + echo -e " ${RED}✗${NC} nc_listen should omit -p flag for standard nc, got '${result}'" ((FAILED++)) fi # Test 13: open_browser detects termux-open-url result=$(bash -c ' - source "'"$REPO_ROOT"'/shared/common.sh" + source "'"${REPO_ROOT}"'/shared/common.sh" termux-open-url() { echo "termux: $*"; } export -f termux-open-url open_browser "https://example.com" ' 2>/dev/null) - if [[ "$result" == "termux: https://example.com" ]]; then + if [[ "${result}" == "termux: https://example.com" ]]; then echo -e " ${GREEN}✓${NC} open_browser detects termux-open-url" ((PASSED++)) else - echo -e " ${RED}✗${NC} open_browser should use termux-open-url, got '$result'" + echo -e " ${RED}✗${NC} open_browser should use termux-open-url, got '${result}'" ((FAILED++)) fi # Test 14: open_browser detects macOS open result=$(bash -c ' - source "'"$REPO_ROOT"'/shared/common.sh" + source "'"${REPO_ROOT}"'/shared/common.sh" open() { echo "macOS: $*"; } export -f open open_browser "https://example.com" ' 2>/dev/null) - if [[ "$result" == "macOS: https://example.com" ]]; then + if [[ "${result}" == "macOS: https://example.com" ]]; then echo -e " ${GREEN}✓${NC} open_browser detects macOS open" ((PASSED++)) else - echo -e " ${RED}✗${NC} open_browser should use macOS open, got '$result'" + echo -e " ${RED}✗${NC} open_browser should use macOS open, got '${result}'" ((FAILED++)) fi @@ -468,7 +468,7 @@ test_shared_common() { stderr_output=$(bash -c ' # Use minimal PATH to force fallback behavior PATH="/usr/bin:/bin" - source "'"$REPO_ROOT"'/shared/common.sh" + source "'"${REPO_ROOT}"'/shared/common.sh" # Mock all browser detection to fail command() { if [[ "$2" == "termux-open-url" || "$2" == "open" || "$2" == "xdg-open" ]]; then @@ -479,17 +479,17 @@ test_shared_common() { export -f command open_browser "https://example.com" ' 2>&1 >/dev/null) - if [[ "$stderr_output" == *"Please open: https://example.com"* ]]; then + if [[ "${stderr_output}" == *"Please open: https://example.com"* ]]; then echo -e " ${GREEN}✓${NC} open_browser shows fallback message when browsers unavailable" ((PASSED++)) else - echo -e " ${RED}✗${NC} open_browser should show fallback message, got '$stderr_output'" + echo -e " ${RED}✗${NC} open_browser should show fallback message, got '${stderr_output}'" ((FAILED++)) fi # Test 16: get_cloud_init_userdata returns valid YAML - result=$(bash -c 'source "'"$REPO_ROOT"'/shared/common.sh" && get_cloud_init_userdata' 2>/dev/null) - if [[ "$result" == *"#cloud-config"* ]] && [[ "$result" == *"package_update"* ]]; then + result=$(bash -c 'source "'"${REPO_ROOT}"'/shared/common.sh" && get_cloud_init_userdata' 2>/dev/null) + if [[ "${result}" == *"#cloud-config"* ]] && [[ "${result}" == *"package_update"* ]]; then echo -e " ${GREEN}✓${NC} get_cloud_init_userdata returns valid YAML" ((PASSED++)) else @@ -498,7 +498,7 @@ test_shared_common() { fi # Test 17: get_cloud_init_userdata includes required packages - if [[ "$result" == *"curl"* ]] && [[ "$result" == *"git"* ]] && [[ "$result" == *"zsh"* ]]; then + if [[ "${result}" == *"curl"* ]] && [[ "${result}" == *"git"* ]] && [[ "${result}" == *"zsh"* ]]; then echo -e " ${GREEN}✓${NC} get_cloud_init_userdata includes required packages" ((PASSED++)) else @@ -507,7 +507,7 @@ test_shared_common() { fi # Test 18: get_cloud_init_userdata includes Bun and Claude installation - if [[ "$result" == *"bun.sh/install"* ]] && [[ "$result" == *"claude.ai/install"* ]]; then + if [[ "${result}" == *"bun.sh/install"* ]] && [[ "${result}" == *"claude.ai/install"* ]]; then echo -e " ${GREEN}✓${NC} get_cloud_init_userdata includes Bun and Claude installation" ((PASSED++)) else @@ -516,8 +516,8 @@ test_shared_common() { fi # Test 19: create_oauth_response_html returns valid HTTP response - result=$(bash -c 'source "'"$REPO_ROOT"'/shared/common.sh" && create_oauth_response_html' 2>/dev/null) - if [[ "$result" == *"HTTP/1.1 200 OK"* ]] && [[ "$result" == *"Authentication Successful"* ]]; then + result=$(bash -c 'source "'"${REPO_ROOT}"'/shared/common.sh" && create_oauth_response_html' 2>/dev/null) + if [[ "${result}" == *"HTTP/1.1 200 OK"* ]] && [[ "${result}" == *"Authentication Successful"* ]]; then echo -e " ${GREEN}✓${NC} create_oauth_response_html returns valid HTTP response" ((PASSED++)) else @@ -526,11 +526,11 @@ test_shared_common() { fi # Test 20: wait_for_oauth_code returns success when file exists - local code_test_file="$TEST_DIR/oauth_code_test" - echo "test_code" > "$code_test_file" + local code_test_file="${TEST_DIR}/oauth_code_test" + echo "test_code" > "${code_test_file}" rc=0 - bash -c 'source "'"$REPO_ROOT"'/shared/common.sh" && wait_for_oauth_code "'"$code_test_file"'" 1' >/dev/null 2>&1 || rc=$? - if [[ "$rc" -eq 0 ]]; then + bash -c 'source "'"${REPO_ROOT}"'/shared/common.sh" && wait_for_oauth_code "'"${code_test_file}"'" 1' >/dev/null 2>&1 || rc=$? + if [[ "${rc}" -eq 0 ]]; then echo -e " ${GREEN}✓${NC} wait_for_oauth_code returns success when file exists" ((PASSED++)) else @@ -539,10 +539,10 @@ test_shared_common() { fi # Test 21: wait_for_oauth_code returns failure on timeout - local missing_file="$TEST_DIR/missing_oauth_code" + local missing_file="${TEST_DIR}/missing_oauth_code" rc=0 - bash -c 'source "'"$REPO_ROOT"'/shared/common.sh" && wait_for_oauth_code "'"$missing_file"'" 1' >/dev/null 2>&1 || rc=$? - if [[ "$rc" -ne 0 ]]; then + bash -c 'source "'"${REPO_ROOT}"'/shared/common.sh" && wait_for_oauth_code "'"${missing_file}"'" 1' >/dev/null 2>&1 || rc=$? + if [[ "${rc}" -ne 0 ]]; then echo -e " ${GREEN}✓${NC} wait_for_oauth_code returns failure on timeout" ((PASSED++)) else @@ -551,10 +551,10 @@ test_shared_common() { fi # Test 22: cleanup_oauth_session removes directory - local cleanup_test_dir="$TEST_DIR/oauth_cleanup_test" - mkdir -p "$cleanup_test_dir" - bash -c 'source "'"$REPO_ROOT"'/shared/common.sh" && cleanup_oauth_session "" "'"$cleanup_test_dir"'"' >/dev/null 2>&1 - if [[ ! -d "$cleanup_test_dir" ]]; then + local cleanup_test_dir="${TEST_DIR}/oauth_cleanup_test" + mkdir -p "${cleanup_test_dir}" + bash -c 'source "'"${REPO_ROOT}"'/shared/common.sh" && cleanup_oauth_session "" "'"${cleanup_test_dir}"'"' >/dev/null 2>&1 + if [[ ! -d "${cleanup_test_dir}" ]]; then echo -e " ${GREEN}✓${NC} cleanup_oauth_session removes directory" ((PASSED++)) else @@ -564,42 +564,42 @@ test_shared_common() { # Test 23: generic_ssh_wait succeeds when command passes result=$(bash -c ' - source "'"$REPO_ROOT"'/shared/common.sh" + source "'"${REPO_ROOT}"'/shared/common.sh" # Mock ssh that always succeeds ssh() { return 0; } export -f ssh generic_ssh_wait "root" "1.2.3.4" "-o Test" "true" "test" 2 1 2>&1 echo $? ' 2>/dev/null | tail -1) - if [[ "$result" == "0" ]]; then + if [[ "${result}" == "0" ]]; then echo -e " ${GREEN}✓${NC} generic_ssh_wait succeeds when command passes" ((PASSED++)) else - echo -e " ${RED}✗${NC} generic_ssh_wait should return 0 on success, got '$result'" + echo -e " ${RED}✗${NC} generic_ssh_wait should return 0 on success, got '${result}'" ((FAILED++)) fi # Test 24: generic_ssh_wait fails after max attempts result=$(bash -c ' - source "'"$REPO_ROOT"'/shared/common.sh" + source "'"${REPO_ROOT}"'/shared/common.sh" # Mock ssh that always fails ssh() { return 1; } export -f ssh generic_ssh_wait "root" "1.2.3.4" "-o Test" "false" "test" 2 1 2>&1 echo $? ' 2>/dev/null | tail -1) - if [[ "$result" == "1" ]]; then + if [[ "${result}" == "1" ]]; then echo -e " ${GREEN}✓${NC} generic_ssh_wait fails after max attempts" ((PASSED++)) else - echo -e " ${RED}✗${NC} generic_ssh_wait should return 1 after max attempts, got '$result'" + echo -e " ${RED}✗${NC} generic_ssh_wait should return 1 after max attempts, got '${result}'" ((FAILED++)) fi # Test 25: safe_read fails when no TTY available rc=0 - bash -c 'source "'"$REPO_ROOT"'/shared/common.sh" && safe_read "test: "' /dev/null 2>&1 || rc=$? - if [[ "$rc" -ne 0 ]]; then + bash -c 'source "'"${REPO_ROOT}"'/shared/common.sh" && safe_read "test: "' /dev/null 2>&1 || rc=$? + if [[ "${rc}" -ne 0 ]]; then echo -e " ${GREEN}✓${NC} safe_read fails when no TTY available" ((PASSED++)) else @@ -608,8 +608,8 @@ test_shared_common() { fi # Test 26: validate_model_id accepts openrouter/auto - result=$(bash -c 'source "'"$REPO_ROOT"'/shared/common.sh" && validate_model_id "openrouter/auto" && echo "valid"' 2>/dev/null) - if [[ "$result" == "valid" ]]; then + result=$(bash -c 'source "'"${REPO_ROOT}"'/shared/common.sh" && validate_model_id "openrouter/auto" && echo "valid"' 2>/dev/null) + if [[ "${result}" == "valid" ]]; then echo -e " ${GREEN}✓${NC} validate_model_id accepts openrouter/auto" ((PASSED++)) else @@ -618,8 +618,8 @@ test_shared_common() { fi # Test 27: validate_model_id accepts model IDs with colons - result=$(bash -c 'source "'"$REPO_ROOT"'/shared/common.sh" && validate_model_id "provider/model:version" && echo "valid"' 2>/dev/null) - if [[ "$result" == "valid" ]]; then + result=$(bash -c 'source "'"${REPO_ROOT}"'/shared/common.sh" && validate_model_id "provider/model:version" && echo "valid"' 2>/dev/null) + if [[ "${result}" == "valid" ]]; then echo -e " ${GREEN}✓${NC} validate_model_id accepts model IDs with colons" ((PASSED++)) else @@ -634,21 +634,21 @@ test_shared_common() { for char in "${dangerous_chars[@]}"; do rc=0 # Use printf %q to properly escape the character - local test_str=$(printf 'bad%smodel' "$char") - bash -c 'source "'"$REPO_ROOT"'/shared/common.sh" && validate_model_id '"$(printf '%q' "$test_str")" /dev/null 2>&1 || rc=$? - [[ "$rc" -ne 0 ]] && ((rejected_count++)) + local test_str=$(printf 'bad%smodel' "${char}") + bash -c 'source "'"${REPO_ROOT}"'/shared/common.sh" && validate_model_id '"$(printf '%q' "${test_str}")" /dev/null 2>&1 || rc=$? + [[ "${rc}" -ne 0 ]] && ((rejected_count++)) done - if [[ "$rejected_count" -eq "${#dangerous_chars[@]}" ]]; then + if [[ "${rejected_count}" -eq "${#dangerous_chars[@]}" ]]; then echo -e " ${GREEN}✓${NC} validate_model_id rejects shell metacharacters" ((PASSED++)) else - echo -e " ${RED}✗${NC} validate_model_id should reject all shell metacharacters ($rejected_count/${#dangerous_chars[@]})" + echo -e " ${RED}✗${NC} validate_model_id should reject all shell metacharacters (${rejected_count}/${#dangerous_chars[@]})" ((FAILED++)) fi # Test 29: validate_server_name accepts valid names - result=$(bash -c 'source "'"$REPO_ROOT"'/shared/common.sh" && validate_server_name "dev-server-01" && echo "valid"' 2>/dev/null) - if [[ "$result" == "valid" ]]; then + result=$(bash -c 'source "'"${REPO_ROOT}"'/shared/common.sh" && validate_server_name "dev-server-01" && echo "valid"' 2>/dev/null) + if [[ "${result}" == "valid" ]]; then echo -e " ${GREEN}✓${NC} validate_server_name accepts valid names" ((PASSED++)) else @@ -658,8 +658,8 @@ test_shared_common() { # Test 30: validate_server_name rejects names too short rc=0 - bash -c 'source "'"$REPO_ROOT"'/shared/common.sh" && validate_server_name "ab"' /dev/null 2>&1 || rc=$? - if [[ "$rc" -ne 0 ]]; then + bash -c 'source "'"${REPO_ROOT}"'/shared/common.sh" && validate_server_name "ab"' /dev/null 2>&1 || rc=$? + if [[ "${rc}" -ne 0 ]]; then echo -e " ${GREEN}✓${NC} validate_server_name rejects names too short" ((PASSED++)) else @@ -670,8 +670,8 @@ test_shared_common() { # Test 31: validate_server_name rejects names too long rc=0 local long_name=$(printf 'a%.0s' {1..64}) - bash -c 'source "'"$REPO_ROOT"'/shared/common.sh" && validate_server_name "'"$long_name"'"' /dev/null 2>&1 || rc=$? - if [[ "$rc" -ne 0 ]]; then + bash -c 'source "'"${REPO_ROOT}"'/shared/common.sh" && validate_server_name "'"${long_name}"'"' /dev/null 2>&1 || rc=$? + if [[ "${rc}" -ne 0 ]]; then echo -e " ${GREEN}✓${NC} validate_server_name rejects names too long" ((PASSED++)) else @@ -681,8 +681,8 @@ test_shared_common() { # Test 32: validate_server_name rejects leading dash rc=0 - bash -c 'source "'"$REPO_ROOT"'/shared/common.sh" && validate_server_name "-server"' /dev/null 2>&1 || rc=$? - if [[ "$rc" -ne 0 ]]; then + bash -c 'source "'"${REPO_ROOT}"'/shared/common.sh" && validate_server_name "-server"' /dev/null 2>&1 || rc=$? + if [[ "${rc}" -ne 0 ]]; then echo -e " ${GREEN}✓${NC} validate_server_name rejects leading dash" ((PASSED++)) else @@ -692,8 +692,8 @@ test_shared_common() { # Test 33: validate_server_name rejects trailing dash rc=0 - bash -c 'source "'"$REPO_ROOT"'/shared/common.sh" && validate_server_name "server-"' /dev/null 2>&1 || rc=$? - if [[ "$rc" -ne 0 ]]; then + bash -c 'source "'"${REPO_ROOT}"'/shared/common.sh" && validate_server_name "server-"' /dev/null 2>&1 || rc=$? + if [[ "${rc}" -ne 0 ]]; then echo -e " ${GREEN}✓${NC} validate_server_name rejects trailing dash" ((PASSED++)) else @@ -703,8 +703,8 @@ test_shared_common() { # Test 34: validate_server_name rejects invalid characters rc=0 - bash -c 'source "'"$REPO_ROOT"'/shared/common.sh" && validate_server_name "server_01"' /dev/null 2>&1 || rc=$? - if [[ "$rc" -ne 0 ]]; then + bash -c 'source "'"${REPO_ROOT}"'/shared/common.sh" && validate_server_name "server_01"' /dev/null 2>&1 || rc=$? + if [[ "${rc}" -ne 0 ]]; then echo -e " ${GREEN}✓${NC} validate_server_name rejects invalid characters" ((PASSED++)) else @@ -714,8 +714,8 @@ test_shared_common() { # Test 35: validate_server_name rejects empty string rc=0 - bash -c 'source "'"$REPO_ROOT"'/shared/common.sh" && validate_server_name ""' /dev/null 2>&1 || rc=$? - if [[ "$rc" -ne 0 ]]; then + bash -c 'source "'"${REPO_ROOT}"'/shared/common.sh" && validate_server_name ""' /dev/null 2>&1 || rc=$? + if [[ "${rc}" -ne 0 ]]; then echo -e " ${GREEN}✓${NC} validate_server_name rejects empty string" ((PASSED++)) else @@ -726,8 +726,8 @@ test_shared_common() { # Test 36: check_openrouter_connectivity succeeds with real network # Only run if curl is available and we have network access if command -v curl &> /dev/null; then - result=$(bash -c 'source "'"$REPO_ROOT"'/shared/common.sh" && check_openrouter_connectivity && echo "reachable"' 2>/dev/null) - if [[ "$result" == "reachable" ]] || [[ -z "$result" ]]; then + result=$(bash -c 'source "'"${REPO_ROOT}"'/shared/common.sh" && check_openrouter_connectivity && echo "reachable"' 2>/dev/null) + if [[ "${result}" == "reachable" ]] || [[ -z "${result}" ]]; then echo -e " ${GREEN}✓${NC} check_openrouter_connectivity handles connectivity check" ((PASSED++)) else @@ -745,11 +745,11 @@ test_source_detection() { echo -e "${YELLOW}━━━ Testing source detection ━━━${NC}" for script in claude openclaw nanoclaw; do - local script_path="$REPO_ROOT/sprite/${script}.sh" - [[ -f "$script_path" ]] || continue + local script_path="${REPO_ROOT}/sprite/${script}.sh" + [[ -f "${script_path}" ]] || continue # Verify the source block checks for local file existence - if grep -q 'if \[\[ -f "$SCRIPT_DIR/lib/common.sh" \]\]' "$script_path"; then + if grep -q 'if \[\[ -f "${SCRIPT_DIR}/lib/common.sh" \]\]' "${script_path}"; then echo -e " ${GREEN}✓${NC} ${script}.sh uses file-existence check for sourcing" ((PASSED++)) else @@ -758,7 +758,7 @@ test_source_detection() { fi # Verify syntax - if bash -n "$script_path" 2>/dev/null; then + if bash -n "${script_path}" 2>/dev/null; then echo -e " ${GREEN}✓${NC} ${script}.sh syntax valid" ((PASSED++)) else @@ -782,45 +782,45 @@ run_shellcheck() { # Find all shell scripts local all_scripts=( - "$REPO_ROOT"/sprite/*.sh - "$REPO_ROOT"/sprite/lib/common.sh - "$REPO_ROOT"/shared/common.sh - "$REPO_ROOT"/digitalocean/*.sh - "$REPO_ROOT"/digitalocean/lib/common.sh - "$REPO_ROOT"/hetzner/*.sh - "$REPO_ROOT"/hetzner/lib/common.sh - "$REPO_ROOT"/linode/*.sh - "$REPO_ROOT"/linode/lib/common.sh - "$REPO_ROOT"/vultr/*.sh - "$REPO_ROOT"/vultr/lib/common.sh - "$REPO_ROOT"/test/run.sh + "${REPO_ROOT}"/sprite/*.sh + "${REPO_ROOT}"/sprite/lib/common.sh + "${REPO_ROOT}"/shared/common.sh + "${REPO_ROOT}"/digitalocean/*.sh + "${REPO_ROOT}"/digitalocean/lib/common.sh + "${REPO_ROOT}"/hetzner/*.sh + "${REPO_ROOT}"/hetzner/lib/common.sh + "${REPO_ROOT}"/linode/*.sh + "${REPO_ROOT}"/linode/lib/common.sh + "${REPO_ROOT}"/vultr/*.sh + "${REPO_ROOT}"/vultr/lib/common.sh + "${REPO_ROOT}"/test/run.sh ) local issue_count=0 local checked_count=0 for script in "${all_scripts[@]}"; do - [[ -f "$script" ]] || continue + [[ -f "${script}" ]] || continue ((checked_count++)) # Run shellcheck with warning severity, exclude some noisy checks # SC1090: Can't follow non-constant source # SC2312: Consider invoking this command separately to avoid masking its return value local output - output=$(shellcheck --severity=warning --exclude=SC1090,SC2312 "$script" 2>&1) + output=$(shellcheck --severity=warning --exclude=SC1090,SC2312 "${script}" 2>&1) - if [[ -n "$output" ]]; then + if [[ -n "${output}" ]]; then ((issue_count++)) - echo -e " ${YELLOW}⚠${NC} $(basename "$script"): found issues" - echo "$output" | sed 's/^/ /' + echo -e " ${YELLOW}⚠${NC} $(basename "${script}"): found issues" + echo "${output}" | sed 's/^/ /' fi done - if [[ "$issue_count" -eq 0 ]]; then - echo -e " ${GREEN}✓${NC} No issues found in $checked_count scripts" + if [[ "${issue_count}" -eq 0 ]]; then + echo -e " ${GREEN}✓${NC} No issues found in ${checked_count} scripts" ((PASSED++)) else - echo -e " ${YELLOW}⚠${NC} Found issues in $issue_count/$checked_count scripts (advisory only)" + echo -e " ${YELLOW}⚠${NC} Found issues in ${issue_count}/${checked_count} scripts (advisory only)" # Don't fail the build, just warn fi } @@ -830,10 +830,10 @@ echo "===============================" echo " Spawn Script Test Suite" echo "===============================" echo "" -echo "Repo: $REPO_ROOT" -echo "Temp dir: $TEST_DIR" +echo "Repo: ${REPO_ROOT}" +echo "Temp dir: ${TEST_DIR}" echo "Filter: ${FILTER:-all}" -echo "Remote: $REMOTE" +echo "Remote: ${REMOTE}" setup_mocks setup_extra_mocks @@ -845,10 +845,10 @@ test_source_detection # Run per-script tests for script in claude openclaw nanoclaw; do - if [[ -n "$FILTER" && "$FILTER" != "$script" && "$FILTER" != "--remote" ]]; then + if [[ -n "${FILTER}" && "${FILTER}" != "${script}" && "${FILTER}" != "--remote" ]]; then continue fi - [[ -f "$REPO_ROOT/sprite/${script}.sh" ]] && run_script_test "$script" + [[ -f "${REPO_ROOT}/sprite/${script}.sh" ]] && run_script_test "${script}" done # --- Summary --- @@ -858,4 +858,4 @@ TOTAL=$((PASSED + FAILED)) echo -e " Results: ${GREEN}${PASSED} passed${NC}, ${RED}${FAILED} failed${NC}, ${TOTAL} total" echo "===============================" -[[ "$FAILED" -eq 0 ]] && exit 0 || exit 1 +[[ "${FAILED}" -eq 0 ]] && exit 0 || exit 1 diff --git a/vultr/aider.sh b/vultr/aider.sh index 5b933f3a..e43f9cac 100755 --- a/vultr/aider.sh +++ b/vultr/aider.sh @@ -3,8 +3,8 @@ set -eo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)" # shellcheck source=vultr/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/vultr/lib/common.sh)" fi @@ -16,12 +16,12 @@ ensure_vultr_token ensure_ssh_key SERVER_NAME=$(get_server_name) -create_server "$SERVER_NAME" -verify_server_connectivity "$VULTR_SERVER_IP" -wait_for_cloud_init "$VULTR_SERVER_IP" +create_server "${SERVER_NAME}" +verify_server_connectivity "${VULTR_SERVER_IP}" +wait_for_cloud_init "${VULTR_SERVER_IP}" log_warn "Installing Aider..." -run_server "$VULTR_SERVER_IP" "pip install aider-chat 2>/dev/null || pip3 install aider-chat" +run_server "${VULTR_SERVER_IP}" "pip install aider-chat 2>/dev/null || pip3 install aider-chat" log_info "Aider installed" echo "" @@ -34,15 +34,15 @@ fi MODEL_ID=$(get_model_id_interactive "openrouter/auto" "Aider") || exit 1 log_warn "Setting up environment variables..." -inject_env_vars_ssh "$VULTR_SERVER_IP" upload_file run_server \ - "OPENROUTER_API_KEY=$OPENROUTER_API_KEY" +inject_env_vars_ssh "${VULTR_SERVER_IP}" upload_file run_server \ + "OPENROUTER_API_KEY=${OPENROUTER_API_KEY}" echo "" log_info "Vultr instance setup completed successfully!" -log_info "Server: $SERVER_NAME (ID: $VULTR_SERVER_ID, IP: $VULTR_SERVER_IP)" +log_info "Server: ${SERVER_NAME} (ID: ${VULTR_SERVER_ID}, IP: ${VULTR_SERVER_IP})" echo "" log_warn "Starting Aider..." sleep 1 clear -interactive_session "$VULTR_SERVER_IP" "source ~/.zshrc && aider --model openrouter/${MODEL_ID}" +interactive_session "${VULTR_SERVER_IP}" "source ~/.zshrc && aider --model openrouter/${MODEL_ID}" diff --git a/vultr/amazonq.sh b/vultr/amazonq.sh index cdbe7aaa..96e94ca6 100755 --- a/vultr/amazonq.sh +++ b/vultr/amazonq.sh @@ -1,10 +1,10 @@ #!/bin/bash -set -e +set -eo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)" # shellcheck source=vultr/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/vultr/lib/common.sh)" fi @@ -16,12 +16,12 @@ ensure_vultr_token ensure_ssh_key SERVER_NAME=$(get_server_name) -create_server "$SERVER_NAME" -verify_server_connectivity "$VULTR_SERVER_IP" -wait_for_cloud_init "$VULTR_SERVER_IP" +create_server "${SERVER_NAME}" +verify_server_connectivity "${VULTR_SERVER_IP}" +wait_for_cloud_init "${VULTR_SERVER_IP}" log_warn "Installing Amazon Q CLI..." -run_server "$VULTR_SERVER_IP" "curl -fsSL https://desktop-release.q.us-east-1.amazonaws.com/latest/amazon-q-cli-install.sh | bash" +run_server "${VULTR_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 "$VULTR_SERVER_IP" "$ENV_TEMP" "/tmp/env_config" -run_server "$VULTR_SERVER_IP" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config" -rm "$ENV_TEMP" +upload_file "${VULTR_SERVER_IP}" "${ENV_TEMP}" "/tmp/env_config" +run_server "${VULTR_SERVER_IP}" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config" +rm "${ENV_TEMP}" echo "" log_info "Vultr instance setup completed successfully!" -log_info "Server: $SERVER_NAME (ID: $VULTR_SERVER_ID, IP: $VULTR_SERVER_IP)" +log_info "Server: ${SERVER_NAME} (ID: ${VULTR_SERVER_ID}, IP: ${VULTR_SERVER_IP})" echo "" log_warn "Starting Amazon Q..." sleep 1 clear -interactive_session "$VULTR_SERVER_IP" "source ~/.zshrc && q chat" +interactive_session "${VULTR_SERVER_IP}" "source ~/.zshrc && q chat" diff --git a/vultr/claude.sh b/vultr/claude.sh index 9c74467a..36dda76c 100755 --- a/vultr/claude.sh +++ b/vultr/claude.sh @@ -3,8 +3,8 @@ set -eo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)" # shellcheck source=vultr/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/vultr/lib/common.sh)" fi @@ -16,14 +16,14 @@ ensure_vultr_token ensure_ssh_key SERVER_NAME=$(get_server_name) -create_server "$SERVER_NAME" -verify_server_connectivity "$VULTR_SERVER_IP" -wait_for_cloud_init "$VULTR_SERVER_IP" +create_server "${SERVER_NAME}" +verify_server_connectivity "${VULTR_SERVER_IP}" +wait_for_cloud_init "${VULTR_SERVER_IP}" log_warn "Verifying Claude Code installation..." -if ! run_server "$VULTR_SERVER_IP" "command -v claude" >/dev/null 2>&1; then +if ! run_server "${VULTR_SERVER_IP}" "command -v claude" >/dev/null 2>&1; then log_warn "Claude Code not found, installing manually..." - run_server "$VULTR_SERVER_IP" "curl -fsSL https://claude.ai/install.sh | bash" + run_server "${VULTR_SERVER_IP}" "curl -fsSL https://claude.ai/install.sh | bash" fi log_info "Claude Code is installed" @@ -35,24 +35,24 @@ else fi log_warn "Setting up environment variables..." -inject_env_vars_ssh "$VULTR_SERVER_IP" upload_file run_server \ - "OPENROUTER_API_KEY=$OPENROUTER_API_KEY" \ +inject_env_vars_ssh "${VULTR_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 $VULTR_SERVER_IP" \ - "run_server $VULTR_SERVER_IP" +setup_claude_code_config "${OPENROUTER_API_KEY}" \ + "upload_file ${VULTR_SERVER_IP}" \ + "run_server ${VULTR_SERVER_IP}" echo "" log_info "Vultr instance setup completed successfully!" -log_info "Server: $SERVER_NAME (ID: $VULTR_SERVER_ID, IP: $VULTR_SERVER_IP)" +log_info "Server: ${SERVER_NAME} (ID: ${VULTR_SERVER_ID}, IP: ${VULTR_SERVER_IP})" echo "" log_warn "Starting Claude Code..." sleep 1 clear -interactive_session "$VULTR_SERVER_IP" "source ~/.zshrc && claude" +interactive_session "${VULTR_SERVER_IP}" "source ~/.zshrc && claude" diff --git a/vultr/cline.sh b/vultr/cline.sh index 65346f23..309d8e31 100755 --- a/vultr/cline.sh +++ b/vultr/cline.sh @@ -1,10 +1,10 @@ #!/bin/bash -set -e +set -eo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)" # shellcheck source=vultr/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/vultr/lib/common.sh)" fi @@ -16,12 +16,12 @@ ensure_vultr_token ensure_ssh_key SERVER_NAME=$(get_server_name) -create_server "$SERVER_NAME" -verify_server_connectivity "$VULTR_SERVER_IP" -wait_for_cloud_init "$VULTR_SERVER_IP" +create_server "${SERVER_NAME}" +verify_server_connectivity "${VULTR_SERVER_IP}" +wait_for_cloud_init "${VULTR_SERVER_IP}" log_warn "Installing Cline..." -run_server "$VULTR_SERVER_IP" "npm install -g cline" +run_server "${VULTR_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 "$VULTR_SERVER_IP" "$ENV_TEMP" "/tmp/env_config" -run_server "$VULTR_SERVER_IP" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config" -rm "$ENV_TEMP" +upload_file "${VULTR_SERVER_IP}" "${ENV_TEMP}" "/tmp/env_config" +run_server "${VULTR_SERVER_IP}" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config" +rm "${ENV_TEMP}" echo "" log_info "Vultr instance setup completed successfully!" -log_info "Server: $SERVER_NAME (ID: $VULTR_SERVER_ID, IP: $VULTR_SERVER_IP)" +log_info "Server: ${SERVER_NAME} (ID: ${VULTR_SERVER_ID}, IP: ${VULTR_SERVER_IP})" echo "" log_warn "Starting Cline..." sleep 1 clear -interactive_session "$VULTR_SERVER_IP" "source ~/.zshrc && cline" +interactive_session "${VULTR_SERVER_IP}" "source ~/.zshrc && cline" diff --git a/vultr/codex.sh b/vultr/codex.sh index ac6228a1..cc3ab66b 100755 --- a/vultr/codex.sh +++ b/vultr/codex.sh @@ -3,8 +3,8 @@ set -eo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)" # shellcheck source=vultr/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/vultr/lib/common.sh)" fi @@ -16,12 +16,12 @@ ensure_vultr_token ensure_ssh_key SERVER_NAME=$(get_server_name) -create_server "$SERVER_NAME" -verify_server_connectivity "$VULTR_SERVER_IP" -wait_for_cloud_init "$VULTR_SERVER_IP" +create_server "${SERVER_NAME}" +verify_server_connectivity "${VULTR_SERVER_IP}" +wait_for_cloud_init "${VULTR_SERVER_IP}" log_warn "Installing Codex CLI..." -run_server "$VULTR_SERVER_IP" "npm install -g @openai/codex" +run_server "${VULTR_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 "$VULTR_SERVER_IP" upload_file run_server \ - "OPENROUTER_API_KEY=$OPENROUTER_API_KEY" \ - "OPENAI_API_KEY=$OPENROUTER_API_KEY" \ +inject_env_vars_ssh "${VULTR_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 "Vultr instance setup completed successfully!" -log_info "Server: $SERVER_NAME (ID: $VULTR_SERVER_ID, IP: $VULTR_SERVER_IP)" +log_info "Server: ${SERVER_NAME} (ID: ${VULTR_SERVER_ID}, IP: ${VULTR_SERVER_IP})" echo "" log_warn "Starting Codex..." sleep 1 clear -interactive_session "$VULTR_SERVER_IP" "source ~/.zshrc && codex" +interactive_session "${VULTR_SERVER_IP}" "source ~/.zshrc && codex" diff --git a/vultr/gemini.sh b/vultr/gemini.sh index 99d17637..96132874 100755 --- a/vultr/gemini.sh +++ b/vultr/gemini.sh @@ -1,10 +1,10 @@ #!/bin/bash -set -e +set -eo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)" # shellcheck source=vultr/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/vultr/lib/common.sh)" fi @@ -16,12 +16,12 @@ ensure_vultr_token ensure_ssh_key SERVER_NAME=$(get_server_name) -create_server "$SERVER_NAME" -verify_server_connectivity "$VULTR_SERVER_IP" -wait_for_cloud_init "$VULTR_SERVER_IP" +create_server "${SERVER_NAME}" +verify_server_connectivity "${VULTR_SERVER_IP}" +wait_for_cloud_init "${VULTR_SERVER_IP}" log_warn "Installing Gemini CLI..." -run_server "$VULTR_SERVER_IP" "npm install -g @google/gemini-cli" +run_server "${VULTR_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 "$VULTR_SERVER_IP" "$ENV_TEMP" "/tmp/env_config" -run_server "$VULTR_SERVER_IP" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config" -rm "$ENV_TEMP" +upload_file "${VULTR_SERVER_IP}" "${ENV_TEMP}" "/tmp/env_config" +run_server "${VULTR_SERVER_IP}" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config" +rm "${ENV_TEMP}" echo "" log_info "Vultr instance setup completed successfully!" -log_info "Server: $SERVER_NAME (ID: $VULTR_SERVER_ID, IP: $VULTR_SERVER_IP)" +log_info "Server: ${SERVER_NAME} (ID: ${VULTR_SERVER_ID}, IP: ${VULTR_SERVER_IP})" echo "" log_warn "Starting Gemini..." sleep 1 clear -interactive_session "$VULTR_SERVER_IP" "source ~/.zshrc && gemini" +interactive_session "${VULTR_SERVER_IP}" "source ~/.zshrc && gemini" diff --git a/vultr/goose.sh b/vultr/goose.sh index 4d7e2efb..24ced658 100755 --- a/vultr/goose.sh +++ b/vultr/goose.sh @@ -3,8 +3,8 @@ set -eo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)" # shellcheck source=vultr/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/vultr/lib/common.sh)" fi @@ -16,12 +16,12 @@ ensure_vultr_token ensure_ssh_key SERVER_NAME=$(get_server_name) -create_server "$SERVER_NAME" -verify_server_connectivity "$VULTR_SERVER_IP" -wait_for_cloud_init "$VULTR_SERVER_IP" +create_server "${SERVER_NAME}" +verify_server_connectivity "${VULTR_SERVER_IP}" +wait_for_cloud_init "${VULTR_SERVER_IP}" log_warn "Installing Goose..." -run_server "$VULTR_SERVER_IP" "CONFIGURE=false curl -fsSL https://github.com/block/goose/releases/latest/download/download_cli.sh | bash" +run_server "${VULTR_SERVER_IP}" "CONFIGURE=false curl -fsSL https://github.com/block/goose/releases/latest/download/download_cli.sh | bash" log_info "Goose installed" echo "" @@ -32,16 +32,16 @@ else fi log_warn "Setting up environment variables..." -inject_env_vars_ssh "$VULTR_SERVER_IP" upload_file run_server \ +inject_env_vars_ssh "${VULTR_SERVER_IP}" upload_file run_server \ "GOOSE_PROVIDER=openrouter" \ - "OPENROUTER_API_KEY=$OPENROUTER_API_KEY" + "OPENROUTER_API_KEY=${OPENROUTER_API_KEY}" echo "" log_info "Vultr instance setup completed successfully!" -log_info "Server: $SERVER_NAME (ID: $VULTR_SERVER_ID, IP: $VULTR_SERVER_IP)" +log_info "Server: ${SERVER_NAME} (ID: ${VULTR_SERVER_ID}, IP: ${VULTR_SERVER_IP})" echo "" log_warn "Starting Goose..." sleep 1 clear -interactive_session "$VULTR_SERVER_IP" "source ~/.zshrc && goose" +interactive_session "${VULTR_SERVER_IP}" "source ~/.zshrc && goose" diff --git a/vultr/interpreter.sh b/vultr/interpreter.sh index d3f9f62a..1c9a6049 100755 --- a/vultr/interpreter.sh +++ b/vultr/interpreter.sh @@ -3,8 +3,8 @@ set -eo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)" # shellcheck source=vultr/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/vultr/lib/common.sh)" fi @@ -16,12 +16,12 @@ ensure_vultr_token ensure_ssh_key SERVER_NAME=$(get_server_name) -create_server "$SERVER_NAME" -verify_server_connectivity "$VULTR_SERVER_IP" -wait_for_cloud_init "$VULTR_SERVER_IP" +create_server "${SERVER_NAME}" +verify_server_connectivity "${VULTR_SERVER_IP}" +wait_for_cloud_init "${VULTR_SERVER_IP}" log_warn "Installing Open Interpreter..." -run_server "$VULTR_SERVER_IP" "pip install open-interpreter 2>/dev/null || pip3 install open-interpreter" +run_server "${VULTR_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 "$VULTR_SERVER_IP" upload_file run_server \ - "OPENROUTER_API_KEY=$OPENROUTER_API_KEY" \ - "OPENAI_API_KEY=$OPENROUTER_API_KEY" \ +inject_env_vars_ssh "${VULTR_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 "Vultr instance setup completed successfully!" -log_info "Server: $SERVER_NAME (ID: $VULTR_SERVER_ID, IP: $VULTR_SERVER_IP)" +log_info "Server: ${SERVER_NAME} (ID: ${VULTR_SERVER_ID}, IP: ${VULTR_SERVER_IP})" echo "" log_warn "Starting Open Interpreter..." sleep 1 clear -interactive_session "$VULTR_SERVER_IP" "source ~/.zshrc && interpreter" +interactive_session "${VULTR_SERVER_IP}" "source ~/.zshrc && interpreter" diff --git a/vultr/nanoclaw.sh b/vultr/nanoclaw.sh index 43184fcd..9e9bed8d 100755 --- a/vultr/nanoclaw.sh +++ b/vultr/nanoclaw.sh @@ -3,8 +3,8 @@ set -eo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)" # shellcheck source=vultr/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/vultr/lib/common.sh)" fi @@ -16,14 +16,14 @@ ensure_vultr_token ensure_ssh_key SERVER_NAME=$(get_server_name) -create_server "$SERVER_NAME" -verify_server_connectivity "$VULTR_SERVER_IP" -wait_for_cloud_init "$VULTR_SERVER_IP" +create_server "${SERVER_NAME}" +verify_server_connectivity "${VULTR_SERVER_IP}" +wait_for_cloud_init "${VULTR_SERVER_IP}" log_warn "Installing tsx..." -run_server "$VULTR_SERVER_IP" "source ~/.bashrc && bun install -g tsx" +run_server "${VULTR_SERVER_IP}" "source ~/.bashrc && bun install -g tsx" log_warn "Cloning and building nanoclaw..." -run_server "$VULTR_SERVER_IP" "git clone https://github.com/gavrielc/nanoclaw.git ~/nanoclaw && cd ~/nanoclaw && npm install && npm run build" +run_server "${VULTR_SERVER_IP}" "git clone https://github.com/gavrielc/nanoclaw.git ~/nanoclaw && cd ~/nanoclaw && npm install && npm run build" log_info "NanoClaw installed" echo "" @@ -34,26 +34,26 @@ else fi log_warn "Setting up environment variables..." -inject_env_vars_ssh "$VULTR_SERVER_IP" upload_file run_server \ - "OPENROUTER_API_KEY=$OPENROUTER_API_KEY" \ - "ANTHROPIC_API_KEY=$OPENROUTER_API_KEY" \ +inject_env_vars_ssh "${VULTR_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 "$VULTR_SERVER_IP" "$DOTENV_TEMP" "/root/nanoclaw/.env" -rm "$DOTENV_TEMP" +upload_file "${VULTR_SERVER_IP}" "${DOTENV_TEMP}" "/root/nanoclaw/.env" +rm "${DOTENV_TEMP}" echo "" log_info "Vultr instance setup completed successfully!" -log_info "Server: $SERVER_NAME (ID: $VULTR_SERVER_ID, IP: $VULTR_SERVER_IP)" +log_info "Server: ${SERVER_NAME} (ID: ${VULTR_SERVER_ID}, IP: ${VULTR_SERVER_IP})" echo "" log_warn "Starting nanoclaw..." log_warn "You will need to scan a WhatsApp QR code to authenticate." echo "" -interactive_session "$VULTR_SERVER_IP" "cd ~/nanoclaw && source ~/.zshrc && npm run dev" +interactive_session "${VULTR_SERVER_IP}" "cd ~/nanoclaw && source ~/.zshrc && npm run dev" diff --git a/vultr/openclaw.sh b/vultr/openclaw.sh index 0231023e..d49fd59c 100755 --- a/vultr/openclaw.sh +++ b/vultr/openclaw.sh @@ -3,8 +3,8 @@ set -eo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)" # shellcheck source=vultr/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/vultr/lib/common.sh)" fi @@ -16,12 +16,12 @@ ensure_vultr_token ensure_ssh_key SERVER_NAME=$(get_server_name) -create_server "$SERVER_NAME" -verify_server_connectivity "$VULTR_SERVER_IP" -wait_for_cloud_init "$VULTR_SERVER_IP" +create_server "${SERVER_NAME}" +verify_server_connectivity "${VULTR_SERVER_IP}" +wait_for_cloud_init "${VULTR_SERVER_IP}" log_warn "Installing openclaw..." -run_server "$VULTR_SERVER_IP" "source ~/.bashrc && bun install -g openclaw" +run_server "${VULTR_SERVER_IP}" "source ~/.bashrc && bun install -g openclaw" log_info "OpenClaw installed" echo "" @@ -34,21 +34,21 @@ fi MODEL_ID=$(get_model_id_interactive "openrouter/auto" "Openclaw") || exit 1 log_warn "Setting up environment variables..." -inject_env_vars_ssh "$VULTR_SERVER_IP" upload_file run_server \ - "OPENROUTER_API_KEY=$OPENROUTER_API_KEY" \ - "ANTHROPIC_API_KEY=$OPENROUTER_API_KEY" \ +inject_env_vars_ssh "${VULTR_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 $VULTR_SERVER_IP" \ - "run_server $VULTR_SERVER_IP" +setup_openclaw_config "${OPENROUTER_API_KEY}" "${MODEL_ID}" \ + "upload_file ${VULTR_SERVER_IP}" \ + "run_server ${VULTR_SERVER_IP}" echo "" log_info "Vultr instance setup completed successfully!" -log_info "Server: $SERVER_NAME (ID: $VULTR_SERVER_ID, IP: $VULTR_SERVER_IP)" +log_info "Server: ${SERVER_NAME} (ID: ${VULTR_SERVER_ID}, IP: ${VULTR_SERVER_IP})" echo "" log_warn "Starting openclaw..." -run_server "$VULTR_SERVER_IP" "source ~/.zshrc && nohup openclaw gateway > /tmp/openclaw-gateway.log 2>&1 &" +run_server "${VULTR_SERVER_IP}" "source ~/.zshrc && nohup openclaw gateway > /tmp/openclaw-gateway.log 2>&1 &" sleep 2 -interactive_session "$VULTR_SERVER_IP" "source ~/.zshrc && openclaw tui" +interactive_session "${VULTR_SERVER_IP}" "source ~/.zshrc && openclaw tui"