* feat: migrate shell script URLs to openrouter.ai/labs/spawn CDN
Users on older CLI versions can't auto-update because the repo was restructured
(cli/ → packages/cli/), so old version-check URLs 404. This decouples the CLI
from the repo's internal directory structure:
- Shell script URLs (install, agent scripts, github-auth) now use
openrouter.ai/labs/spawn/* as primary with GitHub raw as fallback
- Version checks now use GitHub release artifact (cli-latest/version)
as primary — a static URL that never changes regardless of repo layout
- CI workflow updated to publish a `version` file alongside cli.js
- Remove GITHUB_RAW_URL_PATTERN validation (no longer needed since
install URL is now a hardcoded CDN string, not interpolated)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* style: fix biome formatting in update-check test
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: CLAUDE.md says biome lint but should say biome check
biome lint only checks lint rules, not formatting. biome check does both.
The hooks and CI already run biome check — the docs were out of sync.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(hooks): PostToolUse hook wasn't running biome on CLI source files
Two bugs in validate-file.ts:
1. Config search only checked 1-2 levels up from the edited file, but
biome.json is at packages/cli/ — 3 levels above src/__tests__/*.ts.
Fix: walk up directories until biome.json is found (or hit root).
2. Ran `biome format` (prints formatted output, always exits 0) instead
of `biome format --check` (exits non-zero if file needs formatting).
Fix: use `biome check` which does lint + format check in one pass.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat!: remove Fly.io cloud provider support
Drop Fly.io as a supported cloud provider. Sprite (which uses Fly.io
infrastructure internally) is retained.
- Delete packages/cli/src/fly/ module, sh/fly/ scripts, fixtures/fly/
- Remove fly cloud entry and 6 fly matrix entries from manifest.json
- Remove fly imports, destroy cases, and connection handlers from commands.ts
- Remove fly-ssh sentinel from security.ts
- Port E2E test suite from Fly.io to AWS Lightsail (fly-e2e.sh → aws-e2e.sh)
- Update README (7 clouds, 42 combinations), CLAUDE.md, and skill prompts
- Clean up fly references in build config, gitignore, icon sources
- Bump CLI version to 0.11.0
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: restore Docker image build under sh/docker/
Move openclaw Dockerfile from sh/fly/docker/ to sh/docker/ and rename
workflow from fly-docker.yml to docker.yml with updated paths.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* style: fix extra blank lines in commands.ts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: spawn-bot <spawn-bot@openrouter.ai>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: L <6723574+louisgv@users.noreply.github.com>
Restructure the repo as a Bun workspace monorepo:
- Move cli/ → packages/cli/
- Create packages/shared/ (@openrouter/spawn-shared) with type-guards and parse utilities
- Add root package.json with workspace configuration
- Update all CLI imports to use @openrouter/spawn-shared
- Deduplicate toRecord/toObjectArray helpers from 4 cloud modules
- Update SPA (slack-bot) to use shared package instead of local toObj()
- Update 48 agent shell scripts for new packages/cli/ path
- Update install.sh, install.ps1, e2e, and test scripts
- Update all GitHub workflows, .gitignore, pre-commit hooks
- Update CLAUDE.md, README.md, and skill prompt references
- Pin all dependency versions (no ^ ranges)
- Bump CLI version 0.9.1 → 0.10.0
All 1908 tests pass. Lint clean. All 8 cloud bundles build.
Co-authored-by: Claude <claude@anthropic.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reorganizes the project so all shell scripts live under a dedicated
/sh directory, enabling the OpenRouter rewrite URL to point at /sh/
instead of the repository root.
Moves:
- cli/install.sh → sh/cli/install.sh
- shared/*.sh → sh/shared/*.sh
- {cloud}/{agent}.sh → sh/{cloud}/{agent}.sh (48 scripts)
- {cloud}/README.md → sh/{cloud}/README.md
- e2e/*.sh → sh/e2e/*.sh
- test/macos-compat.sh → sh/test/macos-compat.sh
- test/fixtures/**/*.sh → sh/test/fixtures/**/*.sh
Updates all references:
- RAW_BASE path construction in commands.ts, update-check.ts
- GitHub auth URL in agent-setup.ts
- Self-referencing URLs in install.sh, github-auth.sh
- CI workflow paths in lint.yml, cli-release.yml
- Test file paths in install-script-validation, manifest-integrity
- Documentation in README.md, cli/README.md, CLAUDE.md
- QA scripts in .claude/skills/
Co-authored-by: lab <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The race condition: two PRs merged 3 seconds apart both triggered the
CLI Release workflow. The second run (v0.7.12) finished last and
overwrote the release with a stale binary, even though the repo HEAD
was at v0.8.0.
- Add concurrency group so concurrent releases cancel the older one
- Add workflow_dispatch trigger for manual re-runs
Co-authored-by: lab <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move all fly TypeScript files from fly/lib/*.ts and fly/main.ts into
cli/src/fly/. This gives them access to cli/node_modules (@clack/prompts),
biome linting, and the existing bun:test infrastructure — no symlinks or
NODE_PATH hacks needed.
The org picker now uses @clack/prompts select() directly (static import,
bundled at build time).
New: cli/build-clouds.sh — auto-discovers cli/src/*/main.ts and bundles
each into {cloud}.js. Scalable to future cloud TS migrations:
bash cli/build-clouds.sh # build all
bash cli/build-clouds.sh fly # build one
Shims now check for cli/src/fly/main.ts (local) or download fly.js from
GitHub releases (remote curl|bash).
Co-authored-by: lab <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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>