Commit graph

27 commits

Author SHA1 Message Date
A
5ebe3e5a13
fix: add actionable guidance to destroy_server failures and service timeouts (#959)
When server destruction fails, users are left with a bare error message and
no indication that they may still be billed for a running server. This adds
dashboard URLs and clear warnings to destroy_server errors across 9 clouds
(Hetzner, UpCloud, Contabo, Netcup, RamNode, Hostinger, HOSTKEY, OVH,
Latitude). Also improves error messages for Koyeb (app creation, service
deployment, deployment timeout, instance ID), GitHub Codespaces (creation
failure, readiness timeout), and E2B (sandbox creation failure).

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-13 09:38:58 -08:00
A
b2dd67a0af
refactor: extract helpers to reduce complexity in fly and netcup providers (#912)
fly/lib/common.sh:
- Extract _get_fly_cmd() to eliminate duplicated fly/flyctl CLI resolution
  across run_server, interactive_session, _try_flyctl_auth, ensure_fly_cli
- Extract _fly_parse_error() to deduplicate JSON error parsing (was inline
  in _validate_fly_token, _fly_create_app, _fly_create_machine)
- Extract _fly_build_machine_body() from _fly_create_machine (50→32 lines)
- Use shared _extract_json_field in _fly_create_machine and
  _fly_wait_for_machine_start instead of inline python3 calls

netcup/lib/common.sh:
- Extract _netcup_is_success() for repeated status=='success' checks
  (was inline python3 in create_server, destroy_server, _netcup_wait_for_ip)
- Extract _netcup_build_login_body() from netcup_get_session (51→30 lines)
- Use _extract_json_field throughout instead of inline python3 one-liners
- Net reduction: 351→335 lines (-16)

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 05:07:53 -08:00
L
6633873ccc
refactor: replace Python with jq in Hetzner lib, fix /lab → /labs URLs (#827)
Hetzner lib: replace all Python JSON parsing with jq. Uses the
/datacenters API as the authoritative source for server type
availability (server_types.available), cross-referenced with
/server_types for specs and pricing. jq is auto-installed if missing.

URLs: update openrouter.ai/lab/spawn → openrouter.ai/labs/spawn
across all READMEs and CLI source.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-12 23:14:11 -08:00
A
68c53c4d3f
feat: implement netcup/kilocode integration (#751)
* feat: implement netcup/kilocode integration

Add Kilo Code support on Netcup VPS provider. This fills a missing matrix entry by combining Netcup cloud primitives with Kilo Code agent setup.

Changes:
- netcup/kilocode.sh: New script using Netcup API provisioning + Kilo Code CLI
- netcup/README.md: Added Kilo Code to available agents list
- manifest.json: Updated netcup/kilocode from "missing" to "implemented"

Agent: gap-filler-1

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* fix: address review findings in netcup/kilocode.sh

- Add missing upload_file/run_server args to inject_env_vars_ssh (HIGH -
  prevented credential leak where API key was passed as upload_func)
- Add wait_for_cloud_init call after verify_server_connectivity (MEDIUM)
- Add shellcheck source directive and SC2154 disable
- Add server info to completion message

Agent: pr-maintainer
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Sprite <noreply@sprites.dev>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
2026-02-12 15:49:19 -08:00
A
cf53ea1fb2
fix: use log_step (cyan) for in-progress messages instead of log_info (green) (#757)
Consistently use log_step for progress/status messages ("Waiting for...",
"Fetching...", "Creating...") and reserve log_info for success/completion
messages. This gives users a clear visual distinction between operations
that are still running (cyan) vs operations that have completed (green).

Also adds periodic progress updates to silent polling loops in ramnode,
cherry, and netcup IP wait functions so users see activity during long waits.

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-12 15:48:38 -08:00
A
fad2560a23
feat: Add netcup/plandex implementation (#558)
Implements Plandex on Netcup VPS using netcup/lib/common.sh primitives.
Updates manifest.json to mark netcup/plandex as implemented.
Updates netcup/README.md with Plandex usage instructions.

Agent: gap-filler-netcup

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-11 16:43:23 -08:00
A
be5f9f1087
refactor: extract get_validated_server_name to eliminate 18 duplicate get_server_name functions (#535)
18 cloud lib/common.sh files had identical 7-line get_server_name()
functions (get_resource_name + validate_server_name + echo). Added a
shared get_validated_server_name helper to shared/common.sh and replaced
all duplicates with one-line delegations. Net -110 lines.

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-11 14:42:09 -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
c7d41a93b2
feat: Add opencode support for Netcup cloud (#529)
Agent: netcup-gap-filler

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-11 14:16:13 -08:00
A
c16f09a010
fix: use log_step for progress messages in recent scripts (#524)
Replace log_warn (yellow) with log_step (cyan) for progress messages
like "Installing...", "Setting up environment variables...", and
"Starting..." in recently-added scripts. Yellow warnings should be
reserved for actual warnings, not normal progress output.

Also fix bare `clear` calls to use `clear 2>/dev/null || true` for
robustness on minimal terminals, and improve the misleading
"Appending environment variables to ~/.zshrc..." message in local
scripts to the standard "Setting up environment variables..." phrasing.

Files: local/gptme.sh, local/aider.sh, ramnode/openclaw.sh,
ramnode/gptme.sh, netcup/gptme.sh

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-11 14:04:14 -08:00
A
85b7e1bcb0
feat: Add netcup/gptme script (#522)
Implements gptme agent on Netcup VPS using netcup lib primitives.

Agent: gap-filler-netcup

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-11 13:48:30 -08:00
A
3f41f5e82b
feat: Add Cline support for Netcup (#473)
Agent: gap-filler-1

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-11 08:36:38 -08:00
A
79e3b887c9
refactor: extract ensure_multi_credentials to reduce duplication across 5 providers (#468)
Add a generic ensure_multi_credentials() helper to shared/common.sh that
handles the env-var/config-file/prompt/test/save flow for providers needing
multiple credentials. This eliminates ~270 lines of duplicated logic across
contabo, netcup, ramnode, ionos, and upcloud, replacing it with single
function calls.

Each provider's ensure_*_credentials() function is now 3-8 lines instead
of 30-65 lines.

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-11 07:48:32 -08:00
A
54e32cec4f
feat: Add amazonq support for Netcup (#460)
Agent: gap-filler-netcup

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-11 07:00:23 -08:00
A
4b76b3422c
refactor: reduce complexity in execScript and netcup pick functions (#449)
Extract error handling from execScript() into dedicated helpers
(reportDownloadError, reportScriptFailure, getScriptFailureGuidance),
reducing the function from 52 to 15 lines and making error guidance
directly testable.

Replace duplicated _pick_vps_product() and _pick_datacenter() in
netcup/lib/common.sh with calls to shared interactive_pick(),
eliminating ~60 lines of copy-pasted selection logic.

Net reduction: 42 lines (-98/+56).

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-11 05:56:48 -08:00
A
d25cdd0da6
fix: use log_step for progress messages in netcup scripts (#441)
All netcup agent scripts were using log_warn (yellow) for routine
progress messages like "Installing...", "Setting up...", "Starting...".
These should use log_step (cyan) which was added specifically for
progress/status messages, reserving log_warn for actual warnings.

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-11 04:45:44 -08:00
A
14fc3ebbe6
feat: Add codex agent for Netcup (#437)
Agent: gap-filler-netcup-2

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-11 04:27:12 -08:00
A
e9e39f2032
feat: add netcup/gemini.sh implementation (#436)
Implements Gemini CLI on Netcup cloud infrastructure using the standard
pattern: provision VPS, install Gemini via npm, inject OpenRouter API
credentials, and launch interactive session.

Agent: gap-filler-netcup-5

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-11 04:27:08 -08:00
A
7ca3edc7ee
feat: Add Continue agent for Netcup (#439)
Agent: gap-filler-netcup-4

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-11 04:26:48 -08:00
A
e7a459a456
feat: Add nanoclaw agent for Netcup (#438)
Agent: gap-filler-netcup-1

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-11 04:26:43 -08:00
A
8ba9a14139
feat: Add Open Interpreter agent for Netcup (#435)
Agent: gap-filler-netcup-3

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-11 04:26:23 -08:00
A
88a5e9e844
refactor: extract shared config load/save helpers to reduce credential management complexity (#434)
Add _load_json_config_fields and _save_json_config to shared/common.sh,
replacing duplicated multi-python3-call patterns in IONOS (2 calls -> 1),
Netcup (3 calls -> 1 + inline python save -> helper), and RamNode
(3 calls -> 1 + inline python save -> helper).

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-11 04:25:22 -08:00
A
fdc5d5e58b
refactor: extract shared SSH helpers to eliminate ~410 lines of duplication (#429)
Add ssh_run_server, ssh_upload_file, ssh_interactive_session, and
ssh_verify_connectivity to shared/common.sh. These four functions
were copy-pasted identically across 21 cloud provider lib files,
differing only in SSH username (root vs ubuntu).

Providers now set SSH_USER and delegate to the shared helpers via
one-line wrappers, reducing each provider's lib by ~20 lines.

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-11 03:45:18 -08:00
A
de19996360
refactor: extract helpers from create_server() in 4 cloud providers (#423)
Extract wait-for-IP polling loops and JSON body builders from the
largest create_server() functions (ramnode 105->59, netcup 95->50,
cherry 80->57, binarylane 92->70 lines), following the pattern
already established in ionos/lib/common.sh.

Extracted helpers:
- ramnode: _ramnode_build_server_body(), _ramnode_wait_for_ip()
- netcup: _netcup_build_create_body(), _netcup_wait_for_ip()
- cherry: _cherry_wait_for_ip()
- binarylane: _binarylane_wait_for_active()

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-11 02:59:31 -08:00
A
246b72a22b
fix: Prevent Python/JSON injection in RamNode and Netcup providers (#420)
Use sys.argv and sys.stdin instead of shell variable interpolation
in Python strings to prevent code injection via credentials, SSH keys,
server names, and other user-controlled inputs.

RamNode fixes:
- _get_ramnode_token: credentials via sys.argv instead of string interpolation
- Config file read: use sys.argv[1] for file path (matches other providers)
- Config file save: use sys.argv for all values
- ramnode_check_ssh_key: key_name via sys.argv
- ramnode_register_ssh_key: public key via stdin, name via sys.argv
- create_server: all parameters via sys.argv

Netcup fixes:
- netcup_get_session: use python3+json.dumps instead of unquoted heredoc
- netcup_api: use python3+json.dumps for action parameter
- Config file read: use sys.argv[1] for file path
- Config file save: use python3+sys.argv instead of unquoted heredoc
- create_server: all parameters via sys.argv

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-11 02:36:03 -08:00
A
343042cd90
feat: Add openclaw support for Netcup (#416)
- Uses netcup lib primitives for server creation
- Installs bun and openclaw via bun global install
- OpenRouter injection via env vars
- Tested with bash -n

Agent: gap-filler-1

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-11 02:28:30 -08:00
A
93a043cef8
feat: Add Netcup cloud provider support (#407)
Add Netcup as a new cloud provider - a German budget VPS provider
with REST API support starting at €3.86/mo.

Changes:
- Created netcup/lib/common.sh with session-based REST API primitives
- Added Netcup to manifest.json clouds section
- Added 15 matrix entries (claude/aider/goose implemented, rest missing)
- Implemented netcup/claude.sh, netcup/aider.sh, netcup/goose.sh
- Created netcup/README.md with usage documentation

Netcup uses session-based authentication requiring:
- NETCUP_CUSTOMER_NUMBER
- NETCUP_API_KEY
- NETCUP_API_PASSWORD

API launched Oct 2025, replaces legacy SOAP service (deprecated May 2026).

Agent: cloud-scout-2

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
2026-02-11 01:34:59 -08:00