Commit graph

17 commits

Author SHA1 Message Date
A
4e33cc39cd
fix: address medium security findings from #753 (#755)
- Replace `echo -e` with `printf` in cli/install.sh for macOS bash 3.x compat
- Remove `-u` (nounset) from test/run.sh — use `${VAR:-}` pattern instead
- Replace `source <(curl ...)` with `eval "$(curl ...)"` in test/run.sh for curl|bash compat
- Add .gitignore patterns for sensitive files (.env, *.pem, *.key, credentials)

Refs #753

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-12 15:48:52 -08:00
L
d961947983
fix: download pre-built CLI from GitHub release when local build fails (#728)
Root cause: bun install creates empty directories in proot (Termux)
because proot can't intercept bun's symlink/hardlink/copy_file_range
syscalls. This breaks both local build and source-mode fallback.

Fix: when `bun run build` fails, download the pre-built cli.js from
the `cli-latest` GitHub release. The bundled binary is self-contained
(80KB, all deps inlined) and only needs the bun runtime.

- Add CI workflow (.github/workflows/cli-release.yml) that builds and
  uploads cli.js to a rolling `cli-latest` release on every push to main
- Replace broken source-mode fallback with GitHub release download
- Bump CLI version to 0.2.63

Co-authored-by: Sprite <noreply@sprite.dev>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-12 13:48:45 -08:00
L
ecfd8e2f4e
fix: source-mode wrapper must cd into ~/.spawn for package resolution (#710)
bun 1.3.8 on Termux proot doesn't resolve node_modules by walking up
from the source file directory. Changing cwd to ~/.spawn/ (where
node_modules lives) before exec ensures packages are found.

Co-authored-by: Sprite <noreply@sprite.dev>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-12 12:17:06 -08:00
L
db72074e0a
fix: fall back to source-mode install when bundled build fails (#707)
bun 1.3.8 in Termux proot cannot resolve packages with --packages bundle
even with bun.lock present and after --force reinstall. When the bundled
build fails, install source + node_modules to ~/.spawn/ and create a
wrapper script that runs via `bun` directly.

Co-authored-by: Sprite <noreply@sprite.dev>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-12 12:13:19 -08:00
L
ac1f8239c8
fix: install.sh fails on Termux proot due to missing bun.lock (#704)
The non-git download path did not fetch bun.lock, causing bun install
to resolve dependencies from scratch. On older bun versions (e.g. 1.3.8
in Termux proot), this produced a node_modules layout that broke
`bun build --packages bundle`.

- Download bun.lock in the non-git (curl) path
- Add build retry with `bun install --force` fallback
- Enforce minimum bun version (1.2.0) with auto-upgrade
- Bump CLI version to 0.2.60

Co-authored-by: Sprite <noreply@sprite.dev>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-12 11:49:20 -08:00
A
30f19b7df6
refactor: Drop spawn.sh bash fallback, auto-install bun instead (#163)
The 663-line bash CLI (spawn.sh) has drifted from the TypeScript CLI,
missing --prompt, security validation, download fallback, and other
features. Rather than maintaining two implementations, the installer
now auto-installs bun (~5 seconds) when it's not present, ensuring
every user gets the full-featured TypeScript CLI.

- Remove cli/spawn.sh (663 lines)
- Simplify install.sh: remove npm method, add bun auto-install
- Extract build_and_install() helper to deduplicate build logic
- Update cli/README.md and CLAUDE.md to reflect bun-only strategy

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 22:30:48 -08:00
Sprite
0295df0bf0 fix: Install to ~/.local/bin (in PATH) instead of ~/.bun/bin
~/.bun/bin is often NOT in PATH, causing 'command not found' after
install. Now picks the first dir already in PATH from:
  1. ~/.local/bin (most universal)
  2. $(bun pm bin -g)
  3. ~/.bun/bin
  4. ~/bin

Also consolidated PATH detection and instructions into shared helpers,
with clear shell-specific instructions when the dir isn't in PATH.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-09 00:45:18 +00:00
Sprite
d92bf66f51 fix: Install spawn binary directly instead of using bun link
bun link only registers packages for project-level linking — it does
not create global CLI binaries. bun install -g has the same issue.

New approach:
- bun: build cli.js, copy directly to $(bun pm bin -g)/spawn (55KB)
- npm: build with esbuild, copy to $(npm bin -g)/spawn
- Both methods put the binary exactly where the runtime expects it

Also replaced brittle hardcoded file downloads with git sparse-checkout
(with GitHub API fallback), so new source files never break the installer.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-09 00:37:55 +00:00
Sprite
c7981d626e fix: Replace hardcoded file list with dynamic clone in installer
The install script had a hardcoded list of source files to download,
which broke whenever a new file was added (e.g., security.ts). Also,
openrouter.ai/lab/spawn served a stale cached version without the fix.

Now uses git sparse-checkout (fast, gets only cli/) with a GitHub API
fallback for environments without git. Adding new source files will
never break the installer again.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-09 00:12:22 +00:00
Sprite
863cfbe711 fix: Add missing security.ts to CLI installer downloads
commands.ts imports ./security.js but install.sh never downloaded
security.ts, causing build to fail with "Could not resolve" error.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-09 00:07:58 +00:00
Sprite
7410c8ee4f fix: Build cli.js before linking in install script
package.json bin points to cli.js, but it was never built during
installation. Both bun link and npm install -g failed silently because
the file didn't exist.

- Bun path: run `bun run build` before `bun link`
- npm path: use npx esbuild to bundle cli.js with node shebang

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-08 23:50:19 +00:00
LAB
298065f4ad
UX: Improve error messages, help text, and progress indicators (#55)
Enhance the spawn CLI user experience with actionable error messages,
comprehensive help documentation, and visual progress feedback.

Changes:
- Help text: Add AUTHENTICATION, TROUBLESHOOTING, and MORE INFO sections
- Error messages: Show examples of valid options when validation fails
- Progress indicators: Add spinners for script downloads
- Install flow: Provide clear alternatives when npm install requires sudo
- README: Add environment variable documentation and alternative install URL
- Security errors: Suggest workarounds for false positives

All error messages now follow the pattern:
1. What went wrong
2. Why it matters
3. What to do next

Documentation: .docs/UX_IMPROVEMENTS_20260208.md

Co-authored-by: Sprite <noreply@sprite.dev>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-08 12:00:59 -08:00
Sprite
36b3d82d2e refactor: add OAuth timeout and remove unused color variables
- Add --max-time 30 to OAuth key exchange curl to prevent indefinite hangs
- Remove unused DIM variable from cli/install.sh
- Remove unused BLUE variable from cli/spawn.sh

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-08 03:01:55 +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
39ee858943 security: fix SC2064 trap quoting to prevent early variable expansion
Changed trap commands from double quotes to single quotes so variables
expand at trap execution time instead of definition time. This prevents
security issues where variables could be tampered with between trap
definition and execution.

Fixed 3 instances:
- cli/install.sh (2 instances): trap 'rm -rf "$tmpdir"' EXIT
- test/run.sh (1 instance): trap 'cleanup' EXIT

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-08 01:29:56 +00:00
L
4087deb14e
Drop nounset (set -u) flag — incompatible with env var checks (#27)
The autonomous refactoring added `set -euo pipefail` but the scripts
check optional env vars with `[[ -n "$VAR" ]]` which is a fatal error
under nounset when the var isn't set (e.g. SPRITE_NAME, OPENROUTER_API_KEY).

Fix: downgrade to `set -eo pipefail` across all 42 affected files.

Co-authored-by: Sprite <noreply@sprite.dev>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-07 16:22:04 -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