Commit graph

23 commits

Author SHA1 Message Date
A
e4a3b60c90
ux: improve GCP CLI installation and setup guidance (#1149) (#1156)
Enhanced error messages in gcp/lib/common.sh to provide comprehensive,
platform-specific guidance for users getting started with GCP:

Changes:
- Added detailed install instructions for macOS (Homebrew), Ubuntu/Debian,
  and Fedora/RHEL platforms
- Included post-installation steps (auth and project configuration)
- Added links to create GCP project and enable Compute Engine API
- Improved error message structure with clear "How to fix" sections
- Maintained color-coded output for better readability

This addresses the issue where users felt the GCP flow "doesn't guide
me toward finding the right resource". The new error messages walk
users through the complete setup process from CLI installation to
project configuration.

Agent: ux-engineer

Co-authored-by: spawn-refactor-bot <refactor@openrouter.ai>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-14 20:39:41 -05:00
A
577206bc1b
fix(ux): add post-session summary to Alibaba Cloud and GCP (#1052)
Both clouds had custom `interactive_session` functions that called
`ssh` directly, bypassing the shared `ssh_interactive_session` which
shows the post-session server-still-running warning. Users ending
sessions on these clouds got no reminder to delete their server,
risking ongoing charges.

Changes:
- alibabacloud: replace custom SSH functions with shared helpers,
  add SPAWN_DASHBOARD_URL pointing to ECS console
- gcp: set SSH_USER to GCP_USERNAME, replace custom SSH functions
  with shared helpers, add SPAWN_DASHBOARD_URL pointing to
  Compute Engine console

Agent: ux-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-14 00:29:43 -05:00
A
8852bcfc36
refactor: decompose GCP ensure_gcloud and create_server into focused helpers (#964)
ensure_gcloud (36 lines -> 5 lines + 3 helpers):
- _gcp_check_cli_installed: verify gcloud CLI presence
- _gcp_check_auth: verify active authenticated account
- _gcp_resolve_project: resolve and export GCP_PROJECT

create_server (65 lines -> 37 lines + 4 helpers):
- _gcp_write_startup_script: write cloud-init to tracked temp file
- _gcp_invoke_create: run gcloud compute instances create
- _gcp_handle_create_error: actionable error guidance
- _gcp_get_instance_ip: fetch and export instance external IP

Agent: complexity-hunter

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-13 10:19:19 -08:00
A
f3d2384392
refactor: decompose GCP and Cherry create_server functions (#965)
GCP create_server was 64 lines (largest function across all cloud libs).
Cherry create_server was 54 lines. Both are now under 30 lines each
by extracting focused helpers:

GCP (64 -> 25 lines):
- _gcp_prepare_instance_files: startup script + SSH key temp files
- _gcp_run_create: gcloud command execution with error diagnostics
- _gcp_get_instance_ip: IP extraction from instance describe

Cherry (54 -> 27 lines):
- _cherry_build_server_body: JSON payload construction
- _cherry_submit_create: API call with error handling

Agent: complexity-hunter

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-02-13 10:15:47 -08:00
A
3c3c697ea5
fix: json_escape SSH key names and fix GCP metadata injection (#958)
SSH key registration in 11 cloud providers used unescaped key_name
directly in JSON request bodies. If the hostname (used to generate
key names) contained JSON-special characters like double-quotes, it
could break out of the JSON string and inject arbitrary JSON fields.

Fix: use json_escape for key_name in all providers, matching the
pattern already used by Scaleway.

Also fix GCP create_server which embedded the startup script inline
in --metadata with comma delimiters. Commas in the script could break
metadata parsing or inject additional metadata keys. Fix: use
--metadata-from-file for the startup script.

Affected providers: Hetzner, DigitalOcean, Vultr, BinaryLane,
Hostinger, Contabo, Cherry, HOSTKEY, Civo, Linode, Genesis Cloud, GCP.

Agent: security-auditor

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-13 09:03:35 -08:00
A
fd80f1992c
fix: improve error messages for GCP, AWS Lightsail, Cherry, and Oracle (#957)
- GCP: capture gcloud stderr on failure, add common issues guidance,
  use _log_diagnostic for ensure_gcloud errors
- AWS Lightsail: add common issues for create_server failure,
  use _log_diagnostic for ensure_aws_cli errors,
  improve instance timeout message with actionable steps
- Cherry Servers: use extract_api_error_message instead of raw response
  dump, add common issues for server creation failure
- Oracle Cloud: capture OCI CLI stderr on instance launch failure,
  add common issues for VCN, subnet, and instance creation errors

Agent: ux-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-13 09:00:10 -08:00
A
0835b35a36
fix: use log_step (cyan) for progress messages instead of log_warn (yellow) (#534)
~1500 progress messages across 481 files were using log_warn (yellow)
for normal status updates like "Installing...", "Setting up...",
"Creating server...", etc. This made users think something was wrong
when everything was proceeding normally.

Changes:
- Replace log_warn with log_step for all progress/status messages
- Keep log_warn only for actual warnings (errors, remediation hints)
- Remove emoji from 3 sprite completion messages

Agent: ux-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
2026-02-11 14:37:43 -08:00
A
b0f924b511
fix: Prevent Python/shell injection via env vars and triple-quote strings (#102)
- Fix triple-quote injection in SSH keys (Scaleway, UpCloud), userdata
  (BinaryLane), init scripts (Civo, Kamatera), and GraphQL queries
  (RunPod) by passing data via stdin/json_escape instead of inline
  string interpolation
- Add input validation for all cloud provider env vars (region, type,
  plan, etc.) using validate_region_name/validate_resource_name to block
  shell metacharacters before they reach Python string interpolation
- Validate Modal image name as Python identifier to prevent code injection
- Validate numeric env vars (RAM, GPU count, disk size) across all providers

Affects: 19 cloud provider lib/common.sh files
Agent: security-auditor

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-09 10:22:39 -08:00
Sprite
359777d855 refactor: Document and fix GCP variable export pattern
Improved the variable export pattern in gcp/lib/common.sh:
- Added SC2034 disable with clear documentation in create_server()
- Made server_ip a local variable before export
- Added SC2154 suppressions with documentation in all 10 GCP agent scripts

This eliminates shellcheck warnings while maintaining the existing
export behavior that makes GCP_SERVER_IP, GCP_INSTANCE_NAME_ACTUAL,
and GCP_ZONE available to calling scripts.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-08 03:40:12 +00:00
Sprite
55ef42c82e refactor: add shellcheck disables for intentional SSH_OPTS word splitting
Add SC2086 disable comments to interactive_session() functions in
GCP, Hetzner, and DigitalOcean providers. SSH_OPTS is intentionally
unquoted to allow word splitting for multiple SSH options.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-08 02:56:08 +00:00
Sprite
cabdbc37ba refactor: add pipefail to error handling flags
Changed 65 agent scripts from `set -e` to `set -eo pipefail` to ensure
errors in piped commands are properly caught. This prevents silent
failures when commands like `curl | bash` fail in the middle.

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-08 02:34:45 +00:00
Sprite
6171fa73a9 refactor: use generic_ssh_wait in GCP wait_for_cloud_init
- Call generic_ssh_wait() to establish SSH first
- Simplifies cloud-init waiting logic
- Reduces code duplication

Score: 27 (Impact: 6, Confidence: 9, Risk: 2)
2026-02-08 02:00:49 +00:00
Sprite
f6a16da0ab refactor: cache GCP username at file level
- Add GCP_USERNAME=$(whoami) at file scope
- Replace 6 duplicate whoami subprocess calls
- Eliminates redundant process invocations

Score: 40 (Impact: 4, Confidence: 10, Risk: 1)
2026-02-08 02:00:31 +00:00
Sprite
60524118de refactor: use generic_ssh_wait in AWS Lightsail wait_for_cloud_init
- Call generic_ssh_wait() with ubuntu user to establish SSH first
- Simplifies cloud-init waiting logic
- Reduces code duplication

Score: 16 (Impact: 4, Confidence: 8, Risk: 2)
2026-02-08 01:59:59 +00:00
Sprite
2b8806cc60 refactor: add braces to variable references in gcp/lib/common.sh
Fixed all 57 SC2250 shellcheck warnings by adding braces to variable
references. This improves code consistency and follows shellcheck
best practices.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-08 01:46:16 +00:00
Sprite
f883ff42e8 refactor: check exit codes directly instead of using $?
Fixed SC2181 warnings by refactoring indirect exit code checks
($? -ne 0) to direct command checks (if ! command). This improves
readability and follows shellcheck best practices.

Changes:
- aws-lightsail/lib/common.sh: Refactored aws lightsail create-instances check
- gcp/lib/common.sh: Refactored gcloud compute instances create check

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-08 01:29:56 +00:00
Sprite
16b9b1eda1 refactor: fix SC2155 shellcheck warnings in GCP and AWS Lightsail libraries
Apply mechanical fix to split local variable declarations from command
substitution assignments. This prevents masking return values and aligns
with shellcheck best practices.

Files fixed:
- gcp/lib/common.sh - 9 warnings fixed
- aws-lightsail/lib/common.sh - 3 warnings fixed

Pattern applied: `local var=$(cmd)` → `local var; var=$(cmd)`

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-08 01:21:12 +00:00
Sprite
0b4fe29026 refactor: fix SC2154 warnings for SSH_OPTS in provider libraries
Added shellcheck directive comments before first SSH_OPTS usage in:
- aws-lightsail/lib/common.sh
- gcp/lib/common.sh
- lambda/lib/common.sh
- vultr/lib/common.sh
- linode/lib/common.sh
- hetzner/lib/common.sh
- digitalocean/lib/common.sh

SSH_OPTS is defined in shared/common.sh but shellcheck can't detect
cross-file variable definitions, so we suppress the warning with
an explanatory comment.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-08 01:20:06 +00:00
Sprite
0ad6680f1f refactor: extract duplicate get_server_name logic to shared function
- Add get_resource_name() to shared/common.sh
  - Generic function for env-var-or-prompt pattern
  - Uses indirect expansion ${!var} for dynamic env vars
  - Preserves exact behavior: env check → prompt → error

- Update 9 cloud providers to use shared function:
  - aws-lightsail: LIGHTSAIL_SERVER_NAME
  - digitalocean: DO_DROPLET_NAME (with validation)
  - gcp: GCP_INSTANCE_NAME
  - hetzner: HETZNER_SERVER_NAME (with validation)
  - linode: LINODE_SERVER_NAME (with validation)
  - sprite: SPRITE_NAME (with validation)
  - vultr: VULTR_SERVER_NAME (with validation)
  - e2b: E2B_SANDBOX_NAME
  - modal: MODAL_SANDBOX_NAME

- Reduces code duplication: ~120 lines → ~25 lines
- Maintains backward compatibility (env vars, prompts, errors unchanged)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-08 01:16:20 +00:00
Sprite
a9818001da refactor: migrate 5 cloud libraries to shared/common.sh pattern
Migrated aws-lightsail, e2b, gcp, lambda, and modal libraries to use
the shared library pattern established in earlier refactoring rounds.

Changes:
- Added shared/common.sh sourcing block (local-first, remote-fallback)
- Added bash safety flags (set -eo pipefail) to all 5 libraries
- Removed duplicate provider-agnostic functions:
  - Logging (log_info, log_warn, log_error)
  - Input handling (safe_read)
  - OAuth flow (try_oauth_flow, get_openrouter_api_key_oauth)
  - SSH helpers (generate_ssh_key_if_missing, etc.)
- Retained cloud-specific functions:
  - API wrappers and CLI integration
  - Server provisioning and lifecycle management
  - Cloud-specific validation and configuration

Impact:
- Net reduction: 460 lines (-545 added +85)
- Eliminates code duplication across 5 providers
- Improves consistency and maintainability
- All libraries now follow the same architectural pattern

Task: #3 (score 56 - highest priority)
Also addresses Task #4 (bash safety flags)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-08 01:08:34 +00:00
L
591066cd53
Use ${VAR:-} for all optional env var checks (#28)
Protects against 'unbound variable' errors even if set -u is
re-enabled or inherited. Every [[ -n "$UPPER_VAR" ]] pattern now
uses [[ -n "${UPPER_VAR:-}" ]] to safely default to empty.

Co-authored-by: Sprite <noreply@sprite.dev>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-07 16:28:12 -08:00
L
6ac59e6bb3
Fix OAuth server for macOS bash 3.x (#24)
Three issues broke the OAuth callback server on macOS:

1. echo -e doesn't work in bash 3.x — \r\n appears as literal text
   in the HTTP response, browser gets malformed headers.
   Fix: pre-write response with printf to a file before the subshell.

2. local variables inside ( ... ) & subshell — undefined behavior in
   bash 3.x since subshells aren't function scope.
   Fix: use plain variables in subshells.

3. ((elapsed++)) when elapsed=0 evaluates to falsy — set -e kills
   the script on the first iteration of the timeout loop.
   Fix: use elapsed=$((elapsed + 1)) instead.

Also simplified nc_listen detection to only check for BusyBox
(the -p flag check could misfire on macOS nc).

Applied to all 10 lib/common.sh files.

Co-authored-by: Sprite <noreply@sprite.dev>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-07 14:21:47 -08:00
L
85938a7b0d
Add GCP Compute Engine as eighth cloud provider with all 10 agents (#19)
GCP instances via gcloud CLI with startup-script for provisioning.
Uses current username for SSH (not root/ubuntu).
- gcp/lib/common.sh: gcloud wrapper, SSH key handling, instance lifecycle
- All 10 agents: claude, openclaw, nanoclaw, aider, goose, codex, interpreter, gemini, amazonq, cline

Matrix now 10 agents x 8 clouds = 80/80 implemented.

Co-authored-by: Sprite <noreply@sprite.dev>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-07 12:06:37 -08:00