chore: rename moved repos (OpenRouterTeam→OpenRouterLabs, sst→anomalyco) (#3445)

* chore: rename moved repos OpenRouterTeam→OpenRouterLabs and sst/opencode→anomalyco

Pure mechanical find/replace across the tree — both repos were renamed on
GitHub and only resolved via 301 redirects (fragile; hijack risk if the old
names are re-registered).

- OpenRouterTeam/spawn → OpenRouterLabs/spawn (141 refs): hardcoded REPO
  consts (manifest.ts, agent-tarball.ts), release-download URLs in every
  sh/{cloud}/{agent}.sh, gh/raw/asset URLs, docs, tests, fixtures.
- sst/opencode → anomalyco/opencode (5 refs): manifest, README, agent-setup.ts
  download cmd, opencode.Dockerfile.

No behavior change. biome clean (205 files). CLI version 1.1.0 → 1.1.1.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test(spawn): deflake cmdRun + hetzner tests (disable telemetry in tests, route hetzner mock by endpoint)

* test(spawn): deflake cmdRun + hetzner tests (disable telemetry in tests, route hetzner mock by endpoint)

* test(spawn): deflake cmdRun + hetzner tests (disable telemetry in tests, route hetzner mock by endpoint)

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: spa-the-spawn-maintainer[bot] <286559366+spa-the-spawn-maintainer[bot]@users.noreply.github.com>
This commit is contained in:
Ahmed Abushagur 2026-06-03 00:29:14 -07:00 committed by GitHub
parent c21a65b777
commit 4b62e8735f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
115 changed files with 263 additions and 197 deletions

View file

@ -68,7 +68,7 @@ To add: same steps as before (manifest.json entry, matrix entries, implement on
## 4. Respond to GitHub issues
Check `gh issue list --repo OpenRouterTeam/spawn --state open` for user requests:
Check `gh issue list --repo OpenRouterLabs/spawn --state open` for user requests:
- If someone requests an agent or cloud, implement it and comment with the PR link
- If something is already implemented, close the issue with a note
- If a bug is reported, fix it

View file

@ -35,7 +35,7 @@ Before editing ANY files:
```
5. **Open a draft PR, then merge when done:**
```bash
gh pr create --draft --repo OpenRouterTeam/spawn
gh pr create --draft --repo OpenRouterLabs/spawn
gh pr ready NUMBER && gh pr merge --squash NUMBER
```
6. **Clean up** the worktree:

View file

@ -19,8 +19,8 @@ macOS ships bash 3.2. All scripts MUST work on it:
- `#!/bin/bash` + `set -eo pipefail` (no `u` flag)
- Use `${VAR:-}` for all optional env var checks (`OPENROUTER_API_KEY`, cloud tokens, etc.)
- Primary script URL: `https://openrouter.ai/labs/spawn/{path}` (CDN proxy, maps to repo `sh/`, e.g., `{cloud}/{agent}.sh`)
- Fallback script URL: `https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/sh/{path}`
- Version check URL: `https://github.com/OpenRouterTeam/spawn/releases/download/cli-latest/version` (GitHub release artifact)
- Fallback script URL: `https://raw.githubusercontent.com/OpenRouterLabs/spawn/main/sh/{path}`
- Version check URL: `https://github.com/OpenRouterLabs/spawn/releases/download/cli-latest/version` (GitHub release artifact)
- All env vars documented in the cloud's `sh/{cloud}/README.md`
## Use Bun + TypeScript for Inline Scripting — NEVER python/python3

View file

@ -16,7 +16,7 @@ set -eo pipefail
_COLLAB_CACHE_FILE="/tmp/spawn-collaborators-cache"
_COLLAB_CACHE_TTL=600 # 10 minutes
_COLLAB_REPO="OpenRouterTeam/spawn"
_COLLAB_REPO="OpenRouterLabs/spawn"
# Refresh the collaborator cache if stale or missing
_refresh_collaborator_cache() {

View file

@ -45,7 +45,7 @@ git branch -r --format='%(refname:short) %(committerdate:relative)' | grep -v 'o
### Step 4: Get branches with open PRs (protected)
```bash
gh pr list --repo OpenRouterTeam/spawn --state open --json headRefName --jq '.[].headRefName'
gh pr list --repo OpenRouterLabs/spawn --state open --json headRefName --jq '.[].headRefName'
```
Any branch with an open PR MUST be skipped. Never delete a branch that has an open PR.

View file

@ -41,7 +41,7 @@ Subsequent thread replies in tracked threads auto-trigger new Claude Code runs.
| `SLACK_BOT_TOKEN` | Bot User OAuth Token (`xoxb-...`) |
| `SLACK_APP_TOKEN` | App-Level Token for Socket Mode (`xapp-...`) |
| `SLACK_CHANNEL_ID` | Channel ID to listen in (e.g. `C0123456789`) |
| `GITHUB_REPO` | Target repo context (default: `OpenRouterTeam/spawn`) |
| `GITHUB_REPO` | Target repo context (default: `OpenRouterLabs/spawn`) |
| `REPO_ROOT` | Working directory for Claude Code (default: cwd) |
GitHub auth uses the `gh` CLI — run `gh auth login` before starting.
@ -59,7 +59,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
export SLACK_BOT_TOKEN="xoxb-YOUR-BOT-TOKEN"
export SLACK_APP_TOKEN="xapp-YOUR-APP-TOKEN"
export SLACK_CHANNEL_ID="C0000000000"
export GITHUB_REPO="OpenRouterTeam/spawn"
export GITHUB_REPO="OpenRouterLabs/spawn"
export REPO_ROOT="$(cd "${SCRIPT_DIR}/../../.." && pwd)"
exec bun run "${SCRIPT_DIR}/main.ts"

View file

@ -40,7 +40,7 @@ type SlackClient = InstanceType<typeof App>["client"];
const SLACK_BOT_TOKEN = process.env.SLACK_BOT_TOKEN ?? "";
const SLACK_APP_TOKEN = process.env.SLACK_APP_TOKEN ?? "";
const GITHUB_REPO = process.env.GITHUB_REPO ?? "OpenRouterTeam/spawn";
const GITHUB_REPO = process.env.GITHUB_REPO ?? "OpenRouterLabs/spawn";
const TRIGGER_SECRET = process.env.TRIGGER_SECRET ?? "";
const GROWTH_TRIGGER_URL = process.env.GROWTH_TRIGGER_URL ?? "";
const GROWTH_REPLY_SECRET = process.env.GROWTH_REPLY_SECRET ?? "";

View file

@ -332,10 +332,10 @@ describe("extractToolHint", () => {
it("extracts command from input", () => {
const block: Record<string, unknown> = {
input: {
command: "gh issue list --repo OpenRouterTeam/spawn",
command: "gh issue list --repo OpenRouterLabs/spawn",
},
};
expect(extractToolHint(block)).toBe("gh issue list --repo OpenRouterTeam/spawn");
expect(extractToolHint(block)).toBe("gh issue list --repo OpenRouterLabs/spawn");
});
it("extracts pattern from input", () => {

View file

@ -183,7 +183,7 @@ async function refreshIconsFor(
const contentType = res.headers.get("content-type")?.split(";")[0] ?? "";
const ext = EXT_MAP[contentType] ?? src.ext;
const outPath = resolve(ROOT, `${assetDir}/${id}.${ext}`);
const rawUrl = `https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/${assetDir}/${id}.${ext}`;
const rawUrl = `https://raw.githubusercontent.com/OpenRouterLabs/spawn/main/${assetDir}/${id}.${ext}`;
if (dryRun) {
console.log(` [dry-run] ${id}: would download ${src.url}${outPath}`);

View file

@ -72,7 +72,7 @@ All cloud provisioning and agent setup logic lives in TypeScript under `packages
When you encounter bugs, stale references, broken functionality, or architectural issues that are **outside the scope of your current task**, file a GitHub issue immediately rather than ignoring them or trying to fix everything at once:
```bash
gh issue create --repo OpenRouterTeam/spawn --title "bug: <brief description>" --body "<details>"
gh issue create --repo OpenRouterLabs/spawn --title "bug: <brief description>" --body "<details>"
```
Examples of when to file:

View file

@ -332,7 +332,7 @@ If an agent fails to install or launch on a cloud:
- **Rerun last session**: `spawn last` or `spawn rerun`
- **Check version**: `spawn version` shows CLI version and cache status
- **Update spawn**: `spawn update` checks for the latest version
- **Report bugs**: Open an issue at https://github.com/OpenRouterTeam/spawn/issues
- **Report bugs**: Open an issue at https://github.com/OpenRouterLabs/spawn/issues
## Matrix
@ -341,7 +341,7 @@ If an agent fails to install or launch on a cloud:
| [**Claude Code**](https://claude.ai) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| [**OpenClaw**](https://github.com/openclaw/openclaw) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| [**Codex CLI**](https://github.com/openai/codex) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| [**OpenCode**](https://github.com/sst/opencode) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| [**OpenCode**](https://github.com/anomalyco/opencode) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| [**Kilo Code**](https://github.com/Kilo-Org/kilocode) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| [**Hermes Agent**](https://github.com/NousResearch/hermes-agent) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| [**Junie**](https://www.jetbrains.com/junie/) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
@ -362,7 +362,7 @@ Scripts work standalone (`bash <(curl ...)`) or through the CLI.
## Development
```bash
git clone https://github.com/OpenRouterTeam/spawn.git
git clone https://github.com/OpenRouterLabs/spawn.git
cd spawn
git config core.hooksPath .githooks
```
@ -400,7 +400,7 @@ Pick any agent + cloud combination from the matrix and try it out:
spawn claude hetzner # or any combination
```
If something breaks, hangs, or behaves unexpectedly, open an issue using the [bug report template](https://github.com/OpenRouterTeam/spawn/issues/new?template=bug_report.yml). Include:
If something breaks, hangs, or behaves unexpectedly, open an issue using the [bug report template](https://github.com/OpenRouterLabs/spawn/issues/new?template=bug_report.yml). Include:
- The exact command you ran
- The cloud provider and agent
@ -411,9 +411,9 @@ If something breaks, hangs, or behaves unexpectedly, open an issue using the [bu
Want to see a specific cloud provider or agent supported? Use the dedicated templates:
- [Request a cloud provider](https://github.com/OpenRouterTeam/spawn/issues/new?template=cloud_request.yml)
- [Request an agent](https://github.com/OpenRouterTeam/spawn/issues/new?template=agent_request.yml)
- [Request a CLI feature](https://github.com/OpenRouterTeam/spawn/issues/new?template=cli_feature_request.yml)
- [Request a cloud provider](https://github.com/OpenRouterLabs/spawn/issues/new?template=cloud_request.yml)
- [Request an agent](https://github.com/OpenRouterLabs/spawn/issues/new?template=agent_request.yml)
- [Request a CLI feature](https://github.com/OpenRouterLabs/spawn/issues/new?template=cli_feature_request.yml)
Requests with real-world use cases get prioritized.

View file

@ -21,7 +21,7 @@
"type": "tool_use",
"id": "toolu_01ABC",
"name": "Bash",
"input": { "command": "gh issue list --repo OpenRouterTeam/spawn --state open --limit 5" }
"input": { "command": "gh issue list --repo OpenRouterLabs/spawn --state open --limit 5" }
}
],
"model": "claude-sonnet-4-20250514",

View file

@ -27,7 +27,7 @@
"bypassPermissionsModeAccepted": true
}
},
"icon": "https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/assets/agents/claude.png",
"icon": "https://raw.githubusercontent.com/OpenRouterLabs/spawn/main/assets/agents/claude.png",
"featured_cloud": [
"digitalocean",
"sprite"
@ -67,7 +67,7 @@
"default": "openrouter/auto"
}
},
"icon": "https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/assets/agents/openclaw.png",
"icon": "https://raw.githubusercontent.com/OpenRouterLabs/spawn/main/assets/agents/openclaw.png",
"featured_cloud": [
"digitalocean",
"sprite"
@ -101,7 +101,7 @@
"OPENROUTER_API_KEY": "${OPENROUTER_API_KEY}"
},
"notes": "Works with OpenRouter via OPENAI_BASE_URL override pointing to openrouter.ai/api/v1",
"icon": "https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/assets/agents/codex.png",
"icon": "https://raw.githubusercontent.com/OpenRouterLabs/spawn/main/assets/agents/codex.png",
"featured_cloud": [
"digitalocean",
"sprite"
@ -126,20 +126,20 @@
"opencode": {
"name": "OpenCode",
"description": "AI coding agent built for the terminal with TUI",
"url": "https://github.com/sst/opencode",
"url": "https://github.com/anomalyco/opencode",
"install": "curl -fsSL https://opencode.ai/install | bash",
"launch": "opencode",
"env": {
"OPENROUTER_API_KEY": "${OPENROUTER_API_KEY}"
},
"notes": "Natively supports OpenRouter via OPENROUTER_API_KEY env var. Go-based TUI using Bubble Tea.",
"icon": "https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/assets/agents/opencode.png",
"icon": "https://raw.githubusercontent.com/OpenRouterLabs/spawn/main/assets/agents/opencode.png",
"featured_cloud": [
"digitalocean",
"sprite"
],
"creator": "SST",
"repo": "sst/opencode",
"repo": "anomalyco/opencode",
"license": "MIT",
"created": "2025-04",
"added": "2025-08",
@ -167,7 +167,7 @@
"OPENROUTER_API_KEY": "${OPENROUTER_API_KEY}"
},
"notes": "Natively supports OpenRouter as a provider via KILO_PROVIDER_TYPE=openrouter. CLI installable via npm as @kilocode/cli, invocable as 'kilocode' or 'kilo'.",
"icon": "https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/assets/agents/kilocode.png",
"icon": "https://raw.githubusercontent.com/OpenRouterLabs/spawn/main/assets/agents/kilocode.png",
"featured_cloud": [
"digitalocean",
"sprite"
@ -202,7 +202,7 @@
"OPENAI_API_KEY": "${OPENROUTER_API_KEY}"
},
"notes": "Natively supports OpenRouter via OPENROUTER_API_KEY. Also works via OPENAI_BASE_URL + OPENAI_API_KEY for OpenAI-compatible mode. Installs Python 3.11 via uv. Ships a local web dashboard (port 9119) for configuration, session monitoring, skill browsing, and gateway management — auto-exposed via SSH tunnel when run through spawn.",
"icon": "https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/assets/agents/hermes.png",
"icon": "https://raw.githubusercontent.com/OpenRouterLabs/spawn/main/assets/agents/hermes.png",
"featured_cloud": [
"digitalocean",
"sprite"
@ -236,7 +236,7 @@
"OPENROUTER_API_KEY": "${OPENROUTER_API_KEY}"
},
"notes": "Natively supports OpenRouter via JUNIE_OPENROUTER_API_KEY. Subagent tasks may require GPT-4.1 Mini, GPT-4.1, or GPT-5 models to be enabled on your OpenRouter account.",
"icon": "https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/assets/agents/junie.png",
"icon": "https://raw.githubusercontent.com/OpenRouterLabs/spawn/main/assets/agents/junie.png",
"featured_cloud": [
"digitalocean",
"sprite"
@ -269,7 +269,7 @@
"OPENROUTER_API_KEY": "${OPENROUTER_API_KEY}"
},
"notes": "Natively supports OpenRouter as a provider via OPENROUTER_API_KEY. The CLI command is 'pi'. Config lives in ~/.pi/agent/. Also known as shittycodingagent.ai.",
"icon": "https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/assets/agents/pi.png",
"icon": "https://raw.githubusercontent.com/OpenRouterLabs/spawn/main/assets/agents/pi.png",
"featured_cloud": [
"digitalocean",
"sprite"
@ -318,7 +318,7 @@
}
},
"notes": "Routes through OpenRouter via a local ConnectRPC-to-REST translation proxy (Caddy + Node.js). The proxy intercepts Cursor's proprietary protobuf protocol, translates to OpenAI-compatible API calls, and streams responses back. Binary installs to ~/.local/bin/agent.",
"icon": "https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/assets/agents/cursor.png",
"icon": "https://raw.githubusercontent.com/OpenRouterLabs/spawn/main/assets/agents/cursor.png",
"featured_cloud": [
"digitalocean",
"sprite"
@ -355,7 +355,7 @@
"OPENAI_BASE_URL": "https://openrouter.ai/api/v1"
},
"notes": "Web GUI that spawns Claude Code and Codex as subprocesses via node-pty. OpenRouter integration works through inherited env vars on the child agent processes. Requires Node.js 22+. Default port 3773.",
"icon": "https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/assets/agents/t3code.png",
"icon": "https://raw.githubusercontent.com/OpenRouterLabs/spawn/main/assets/agents/t3code.png",
"featured_cloud": [
"digitalocean",
"sprite"
@ -384,7 +384,7 @@
"name": "Local Machine",
"price": "Free",
"description": "Your computer — no account or payment needed",
"url": "https://github.com/OpenRouterTeam/spawn",
"url": "https://github.com/OpenRouterLabs/spawn",
"type": "local",
"auth": "none",
"provision_method": "none (local execution)",
@ -396,7 +396,7 @@
"name": "Local Sandbox",
"price": "Free",
"description": "Your computer, in a throwaway Docker container — no account or payment needed",
"url": "https://github.com/OpenRouterTeam/spawn",
"url": "https://github.com/OpenRouterLabs/spawn",
"type": "local",
"auth": "none",
"provision_method": "docker run (local container)",
@ -419,7 +419,7 @@
"location": "nbg1",
"image": "ubuntu-24.04"
},
"icon": "https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/assets/clouds/hetzner.png"
"icon": "https://raw.githubusercontent.com/OpenRouterLabs/spawn/main/assets/clouds/hetzner.png"
},
"aws": {
"name": "AWS Lightsail",
@ -437,7 +437,7 @@
"blueprint": "ubuntu_24_04"
},
"notes": "Uses 'ubuntu' user instead of 'root'. Requires AWS CLI installed and configured.",
"icon": "https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/assets/clouds/aws.png"
"icon": "https://raw.githubusercontent.com/OpenRouterLabs/spawn/main/assets/clouds/aws.png"
},
"digitalocean": {
"name": "DigitalOcean",
@ -454,7 +454,7 @@
"region": "nyc3",
"image": "ubuntu-24-04-x64"
},
"icon": "https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/assets/clouds/digitalocean.png"
"icon": "https://raw.githubusercontent.com/OpenRouterLabs/spawn/main/assets/clouds/digitalocean.png"
},
"gcp": {
"name": "GCP Compute Engine",
@ -472,7 +472,7 @@
"image_family": "ubuntu-2404-lts-amd64"
},
"notes": "Uses current username for SSH. Requires gcloud CLI installed and configured.",
"icon": "https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/assets/clouds/gcp.png"
"icon": "https://raw.githubusercontent.com/OpenRouterLabs/spawn/main/assets/clouds/gcp.png"
},
"daytona": {
"name": "Daytona",
@ -489,7 +489,7 @@
"size": "small"
},
"notes": "Uses the Daytona SDK for sandbox lifecycle, file transfer, and signed preview URLs. SSH access tokens are minted on demand and never persisted.",
"icon": "https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/assets/clouds/daytona.png"
"icon": "https://raw.githubusercontent.com/OpenRouterLabs/spawn/main/assets/clouds/daytona.png"
},
"sprite": {
"name": "Sprite",
@ -501,7 +501,7 @@
"provision_method": "sprite create",
"exec_method": "sprite exec",
"interactive_method": "sprite exec -tty",
"icon": "https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/assets/clouds/sprite.png"
"icon": "https://raw.githubusercontent.com/OpenRouterLabs/spawn/main/assets/clouds/sprite.png"
}
},
"matrix": {

View file

@ -57,7 +57,7 @@ The TypeScript CLI (`src/*.ts`) provides:
### Quick Install
```bash
curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/sh/cli/install.sh | bash
curl -fsSL https://raw.githubusercontent.com/OpenRouterLabs/spawn/main/sh/cli/install.sh | bash
```
The installer will:

View file

@ -1,6 +1,6 @@
{
"name": "@openrouter/spawn",
"version": "1.1.0",
"version": "1.1.1",
"type": "module",
"bin": {
"spawn": "cli.js"

View file

@ -30,7 +30,7 @@ const RELEASE_PAYLOAD = {
{
name: "spawn-agent-openclaw-x86_64-20260305.tar.gz",
browser_download_url:
"https://github.com/OpenRouterTeam/spawn/releases/download/agent-openclaw-latest/spawn-agent-openclaw-x86_64-20260305.tar.gz",
"https://github.com/OpenRouterLabs/spawn/releases/download/agent-openclaw-latest/spawn-agent-openclaw-x86_64-20260305.tar.gz",
},
],
};
@ -178,7 +178,7 @@ describe("tryTarballInstall", () => {
{
name: "spawn-agent-claude-x86_64-20260305.tar.gz",
browser_download_url:
"https://github.com/OpenRouterTeam/spawn/releases/download/agent-claude-latest/spawn-agent-claude-x86_64-20260305.tar.gz",
"https://github.com/OpenRouterLabs/spawn/releases/download/agent-claude-latest/spawn-agent-claude-x86_64-20260305.tar.gz",
},
],
};
@ -199,7 +199,7 @@ describe("tryTarballInstall", () => {
{
name: "spawn-agent-claude-arm64-20260305.tar.gz",
browser_download_url:
"https://github.com/OpenRouterTeam/spawn/releases/download/agent-claude-latest/spawn-agent-claude-arm64-20260305.tar.gz",
"https://github.com/OpenRouterLabs/spawn/releases/download/agent-claude-latest/spawn-agent-claude-arm64-20260305.tar.gz",
},
],
};
@ -220,12 +220,12 @@ describe("tryTarballInstall", () => {
{
name: "spawn-agent-claude-x86_64-20260305.tar.gz",
browser_download_url:
"https://github.com/OpenRouterTeam/spawn/releases/download/agent-claude-latest/spawn-agent-claude-x86_64-20260305.tar.gz",
"https://github.com/OpenRouterLabs/spawn/releases/download/agent-claude-latest/spawn-agent-claude-x86_64-20260305.tar.gz",
},
{
name: "spawn-agent-claude-arm64-20260305.tar.gz",
browser_download_url:
"https://github.com/OpenRouterTeam/spawn/releases/download/agent-claude-latest/spawn-agent-claude-arm64-20260305.tar.gz",
"https://github.com/OpenRouterLabs/spawn/releases/download/agent-claude-latest/spawn-agent-claude-arm64-20260305.tar.gz",
},
],
};

View file

@ -49,6 +49,23 @@ let fetchCalls: Array<{
url: string;
}> = [];
/**
* Filter fetchCalls down to just the spawn-script download URLs.
*
* cmdRun fires background telemetry (PostHog `us.i.posthog.com/batch/`) and
* feature-flag (`/decide/`) requests that flush asynchronously. In a full-suite
* run these can land mid-test and pollute fetchCalls, so we must assert on the
* script-host URLs we actually care about rather than "everything that isn't the
* manifest". See: the cmdrun-happy-path flake fix.
*/
function scriptDownloadFetches() {
// Script URLs always end in `.sh` (primary: openrouter.ai/labs/spawn/<cloud>/<agent>.sh,
// fallback: raw.githubusercontent.com/.../sh/<cloud>/<agent>.sh). The manifest
// (`manifest.json`) and telemetry/feature-flag calls never do, so this cleanly
// isolates the download requests under test.
return fetchCalls.filter((c) => c.url.endsWith(".sh"));
}
function mockFetchForDownload(opts: {
primaryOk?: boolean;
fallbackOk?: boolean;
@ -171,7 +188,7 @@ describe("cmdRun happy-path pipeline", () => {
await cmdRun("claude", "sprite");
// Should have fetched the manifest + the primary script URL
const scriptFetches = fetchCalls.filter((c) => !c.url.includes("manifest.json"));
const scriptFetches = scriptDownloadFetches();
expect(scriptFetches.length).toBe(1);
expect(scriptFetches[0].url).toContain("openrouter.ai");
});
@ -215,7 +232,7 @@ describe("cmdRun happy-path pipeline", () => {
await cmdRun("claude", "sprite");
// Should have fetched manifest + primary (failed) + fallback (success)
const scriptFetches = fetchCalls.filter((c) => !c.url.includes("manifest.json"));
const scriptFetches = scriptDownloadFetches();
expect(scriptFetches.length).toBe(2);
expect(scriptFetches[0].url).toContain("openrouter.ai");
expect(scriptFetches[1].url).toContain("raw.githubusercontent.com");

View file

@ -241,7 +241,7 @@ describe("Commands Display Output", () => {
it("should show repository URL", () => {
cmdHelp();
const output = consoleMocks.log.mock.calls.map((c: unknown[]) => c.join(" ")).join("\n");
expect(output).toContain("OpenRouterTeam/spawn");
expect(output).toContain("OpenRouterLabs/spawn");
});
});

View file

@ -1,4 +1,5 @@
import { afterEach, beforeEach, describe, expect, it, mock, spyOn } from "bun:test";
import { isString } from "@openrouter/spawn-shared";
import { mockBunSpawn, mockClackPrompts } from "./test-helpers";
mockClackPrompts();
@ -585,11 +586,21 @@ describe("hetzner/createServer", () => {
},
},
};
let callCount = 0;
global.fetch = mock(() => {
callCount++;
if (callCount <= 1) {
// Token validation
// Route responses by HTTP method + endpoint rather than a fragile global
// call-counter. The previous call-count-keyed mock drifted in full-suite
// runs (the resource-limit 403 landed on the wrong call slot, so cleanup
// never fired and the raw 403 propagated). Routing by request makes the
// mock order-independent and robust to any extra/interleaved fetches.
let createAttempts = 0;
let listIpCalls = 0;
let deleteIpCalls = 0;
global.fetch = mock((input: string | URL | Request, init?: RequestInit) => {
const url = isString(input) ? input : input instanceof URL ? input.href : input.url;
const method = (init?.method ?? (input instanceof Request ? input.method : "GET")).toUpperCase();
const path = url.replace("https://api.hetzner.cloud/v1", "");
// Token validation (GET /servers?per_page=1) and any other server reads
if (method === "GET" && path.startsWith("/servers")) {
return Promise.resolve(
new Response(
JSON.stringify({
@ -598,8 +609,8 @@ describe("hetzner/createServer", () => {
),
);
}
if (callCount <= 2) {
// SSH keys
// SSH keys lookup
if (method === "GET" && path.startsWith("/ssh_keys")) {
return Promise.resolve(
new Response(
JSON.stringify({
@ -608,24 +619,29 @@ describe("hetzner/createServer", () => {
),
);
}
if (callCount <= 3) {
// First create attempt — resource_limit_exceeded (HTTP 403)
return Promise.resolve(
new Response(
JSON.stringify({
error: {
code: "resource_limit_exceeded",
message: "primary_ip_limit",
// Create server: first attempt fails with resource_limit, retry succeeds
if (method === "POST" && path === "/servers") {
createAttempts++;
if (createAttempts === 1) {
return Promise.resolve(
new Response(
JSON.stringify({
error: {
code: "resource_limit_exceeded",
message: "primary_ip_limit",
},
}),
{
status: 403,
},
}),
{
status: 403,
},
),
);
),
);
}
return Promise.resolve(new Response(JSON.stringify(serverResp)));
}
if (callCount <= 4) {
// List primary IPs for cleanup
// List primary IPs for cleanup — one orphaned (assignee 0), one attached
if (method === "GET" && path.startsWith("/primary_ips")) {
listIpCalls++;
return Promise.resolve(
new Response(
JSON.stringify({
@ -645,31 +661,40 @@ describe("hetzner/createServer", () => {
),
);
}
if (callCount <= 5) {
// Delete orphaned IP 100
// Delete orphaned primary IP
if (method === "DELETE" && path.startsWith("/primary_ips/")) {
deleteIpCalls++;
return Promise.resolve(
new Response("", {
status: 204,
}),
);
}
// Retry create — success
return Promise.resolve(new Response(JSON.stringify(serverResp)));
return Promise.resolve(
new Response(JSON.stringify({}), {
status: 404,
}),
);
});
const { ensureHcloudToken, createServer } = await import("../hetzner/hetzner");
await ensureHcloudToken();
const conn = await createServer("test-retry", "cx23", "fsn1");
expect(conn.ip).toBe("10.0.0.5");
// Should have called: token(1), ssh_keys(2), create-fail(3), list-ips(4), delete-ip(5), create-ok(6)
expect(callCount).toBeGreaterThanOrEqual(6);
// The retry flow must have: failed once, cleaned up an orphaned IP, retried.
expect(createAttempts).toBe(2);
expect(listIpCalls).toBeGreaterThanOrEqual(1);
expect(deleteIpCalls).toBe(1);
});
it("throws with guidance when resource limit hit and no orphaned IPs to clean", async () => {
process.env.HCLOUD_TOKEN = "test-token";
let callCount = 0;
global.fetch = mock(() => {
callCount++;
if (callCount <= 1) {
// Route by method + endpoint (order-independent — see the retry test above).
global.fetch = mock((input: string | URL | Request, init?: RequestInit) => {
const url = isString(input) ? input : input instanceof URL ? input.href : input.url;
const method = (init?.method ?? (input instanceof Request ? input.method : "GET")).toUpperCase();
const path = url.replace("https://api.hetzner.cloud/v1", "");
if (method === "GET" && path.startsWith("/servers")) {
return Promise.resolve(
new Response(
JSON.stringify({
@ -678,7 +703,7 @@ describe("hetzner/createServer", () => {
),
);
}
if (callCount <= 2) {
if (method === "GET" && path.startsWith("/ssh_keys")) {
return Promise.resolve(
new Response(
JSON.stringify({
@ -687,8 +712,8 @@ describe("hetzner/createServer", () => {
),
);
}
if (callCount <= 3) {
// Create fails with resource_limit_exceeded
// Create always fails with resource_limit_exceeded
if (method === "POST" && path === "/servers") {
return Promise.resolve(
new Response(
JSON.stringify({
@ -703,19 +728,26 @@ describe("hetzner/createServer", () => {
),
);
}
// List primary IPs — all attached (none orphaned)
// List primary IPs — all attached (none orphaned to clean up)
if (method === "GET" && path.startsWith("/primary_ips")) {
return Promise.resolve(
new Response(
JSON.stringify({
primary_ips: [
{
id: 100,
ip: "1.2.3.4",
assignee_id: 42,
},
],
}),
),
);
}
return Promise.resolve(
new Response(
JSON.stringify({
primary_ips: [
{
id: 100,
ip: "1.2.3.4",
assignee_id: 42,
},
],
}),
),
new Response(JSON.stringify({}), {
status: 404,
}),
);
});
const { ensureHcloudToken, createServer } = await import("../hetzner/hetzner");

View file

@ -37,6 +37,23 @@ import { tryCatch } from "@openrouter/spawn-shared";
//
// We clean up before and after every test run to keep the working tree tidy.
// ── Disable telemetry / analytics network calls in tests ────────────────────
//
// `bun test` does NOT set NODE_ENV or BUN_ENV, so without this the telemetry
// module (shared/telemetry.ts) sees `_enabled = true` and fires real
// fire-and-forget PostHog `fetch` calls (https://us.i.posthog.com/batch/) plus
// feature-flag `/decide/` requests during tests. Because those land on the
// SAME `global.fetch` that tests mock, they:
// - pollute fetch-call tracking arrays (e.g. cmdrun-happy-path counted 10
// "downloads" instead of 1 when batched PostHog flushes interleaved), and
// - drift sequential `callCount`-keyed mocks (e.g. hetzner-cov's
// resource-limit retry test), and can make real network calls.
// Setting these env vars before any module loads hard-disables telemetry for
// the whole suite, removing the shared root cause of those flakes.
process.env.NODE_ENV = "test";
process.env.BUN_ENV = "test";
process.env.SPAWN_TELEMETRY = "0";
const REAL_HOME = process.env.HOME ?? "";
function cleanupStrayTestFiles(): void {

View file

@ -126,7 +126,7 @@ describe("maybeShowStarPrompt", () => {
expect(logMessageSpy).toHaveBeenCalledTimes(1);
const msg = logMessageSpy.mock.calls[0]?.[0];
expect(isString(msg) && msg.includes("github.com/OpenRouterTeam/spawn")).toBe(true);
expect(isString(msg) && msg.includes("github.com/OpenRouterLabs/spawn")).toBe(true);
});
it("saves starPromptShownAt to preferences after showing", () => {

View file

@ -180,7 +180,7 @@ export function buildReadmeTemplate(): string {
return [
"# __NAME__",
"",
"Exported from a [spawn](https://github.com/OpenRouterTeam/spawn) session on `__CLOUD__`.",
"Exported from a [spawn](https://github.com/OpenRouterLabs/spawn) session on `__CLOUD__`.",
"",
"## Quickstart",
"",

View file

@ -65,14 +65,14 @@ export const EXIT_CODE_GUIDANCE: Record<number, ExitCodeEntry> = {
lines: [
" - A downloaded binary may lack execute permissions",
" - The script may require root/sudo access",
` - Report it if this persists: ${pc.cyan("https://github.com/OpenRouterTeam/spawn/issues")}`,
` - Report it if this persists: ${pc.cyan("https://github.com/OpenRouterLabs/spawn/issues")}`,
],
includeDashboard: false,
},
2: {
header: "Shell syntax or argument error. This is likely a bug in the script.",
lines: [
` Report it at: ${pc.cyan("https://github.com/OpenRouterTeam/spawn/issues")}`,
` Report it at: ${pc.cyan("https://github.com/OpenRouterLabs/spawn/issues")}`,
],
includeDashboard: false,
},

View file

@ -497,7 +497,7 @@ function showVersion(): void {
);
const age = getCacheAge();
console.log(pc.dim(` manifest cache: ${formatCacheAge(age)}`));
console.log(pc.dim(" https://github.com/OpenRouterTeam/spawn"));
console.log(pc.dim(" https://github.com/OpenRouterLabs/spawn"));
console.log(pc.dim(` Run ${pc.cyan("spawn feedback")} to tell us what to improve.`));
}

View file

@ -111,7 +111,7 @@ export interface Manifest {
// ── Constants ──────────────────────────────────────────────────────────────────
const REPO = "OpenRouterTeam/spawn";
const REPO = "OpenRouterLabs/spawn";
const RAW_BASE = `https://raw.githubusercontent.com/${REPO}/main` as const;
/** Primary CDN for shell scripts — maps openrouter.ai/labs/spawn/* → repo sh/* */
const SPAWN_CDN = "https://openrouter.ai/labs/spawn" as const;

View file

@ -142,7 +142,7 @@ export function validateScriptContent(script: string): void {
"Security check failed: the downloaded script contains a dangerous pattern.\n\n" +
`Pattern detected: ${description}\n\n` +
"This is unexpected and may indicate the file was tampered with or corrupted.\n" +
"Please report this at: https://github.com/OpenRouterTeam/spawn/issues",
"Please report this at: https://github.com/OpenRouterLabs/spawn/issues",
);
}
}
@ -159,7 +159,7 @@ export function validateScriptContent(script: string): void {
" 1. Check your internet connection and try again\n" +
" 2. Run 'spawn matrix' to verify the combination is marked as implemented\n" +
" 3. Wait a few moments (the script may be deploying) and retry\n" +
" 4. If the issue persists, report it: https://github.com/OpenRouterTeam/spawn/issues",
" 4. If the issue persists, report it: https://github.com/OpenRouterLabs/spawn/issues",
);
}
}

View file

@ -756,7 +756,7 @@ export async function startHermesDashboard(runner: CloudRunner): Promise<void> {
// ─── OpenCode Install Command ────────────────────────────────────────────────
function openCodeInstallCmd(): string {
return 'OC_ARCH=$(uname -m); case "$OC_ARCH" in aarch64) OC_ARCH=arm64;; x86_64) OC_ARCH=x64;; esac; OC_OS=$(uname -s | tr A-Z a-z); mkdir -p /tmp/opencode-install "$HOME/.opencode/bin" && curl --proto \'=https\' -fsSL -o /tmp/opencode-install/oc.tar.gz "https://github.com/sst/opencode/releases/latest/download/opencode-${OC_OS}-${OC_ARCH}.tar.gz" && if tar -tzf /tmp/opencode-install/oc.tar.gz | grep -qE \'(^/|\\.\\.)\'; then echo "Tarball contains unsafe paths" >&2; exit 1; fi && tar xzf /tmp/opencode-install/oc.tar.gz -C /tmp/opencode-install && mv /tmp/opencode-install/opencode "$HOME/.opencode/bin/" && rm -rf /tmp/opencode-install && for _rc in "$HOME/.bashrc" "$HOME/.profile" "$HOME/.bash_profile"; do grep -q ".opencode/bin" "$_rc" 2>/dev/null || echo \'export PATH="$HOME/.opencode/bin:$PATH"\' >> "$_rc"; done; { [ ! -f "$HOME/.zshrc" ] || grep -q ".opencode/bin" "$HOME/.zshrc" 2>/dev/null || echo \'export PATH="$HOME/.opencode/bin:$PATH"\' >> "$HOME/.zshrc"; }; export PATH="$HOME/.opencode/bin:$PATH"';
return 'OC_ARCH=$(uname -m); case "$OC_ARCH" in aarch64) OC_ARCH=arm64;; x86_64) OC_ARCH=x64;; esac; OC_OS=$(uname -s | tr A-Z a-z); mkdir -p /tmp/opencode-install "$HOME/.opencode/bin" && curl --proto \'=https\' -fsSL -o /tmp/opencode-install/oc.tar.gz "https://github.com/anomalyco/opencode/releases/latest/download/opencode-${OC_OS}-${OC_ARCH}.tar.gz" && if tar -tzf /tmp/opencode-install/oc.tar.gz | grep -qE \'(^/|\\.\\.)\'; then echo "Tarball contains unsafe paths" >&2; exit 1; fi && tar xzf /tmp/opencode-install/oc.tar.gz -C /tmp/opencode-install && mv /tmp/opencode-install/opencode "$HOME/.opencode/bin/" && rm -rf /tmp/opencode-install && for _rc in "$HOME/.bashrc" "$HOME/.profile" "$HOME/.bash_profile"; do grep -q ".opencode/bin" "$_rc" 2>/dev/null || echo \'export PATH="$HOME/.opencode/bin:$PATH"\' >> "$_rc"; done; { [ ! -f "$HOME/.zshrc" ] || grep -q ".opencode/bin" "$HOME/.zshrc" 2>/dev/null || echo \'export PATH="$HOME/.opencode/bin:$PATH"\' >> "$HOME/.zshrc"; }; export PATH="$HOME/.opencode/bin:$PATH"';
}
// ─── npm prefix helper ────────────────────────────────────────────────────────

View file

@ -9,7 +9,7 @@ import * as v from "valibot";
import { asyncTryCatch } from "./result.js";
import { logDebug, logInfo, logStep, logWarn } from "./ui.js";
const REPO = "OpenRouterTeam/spawn";
const REPO = "OpenRouterLabs/spawn";
/** Schema for a single GitHub Release asset. */
const AssetSchema = v.object({

View file

@ -42,7 +42,7 @@ export function maybeShowStarPrompt(): void {
}
// 3. Print the star message
p.log.message("⭐ Enjoying Spawn? Star us on GitHub!\n https://github.com/OpenRouterTeam/spawn");
p.log.message("⭐ Enjoying Spawn? Star us on GitHub!\n https://github.com/OpenRouterLabs/spawn");
// 4. Save the updated timestamp
const merged = {

View file

@ -21,6 +21,6 @@ fi
# Remote — download and run compiled TypeScript bundle
AWS_JS=$(mktemp)
trap 'rm -f "$AWS_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/aws-latest/aws.js" -o "$AWS_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/aws-latest/aws.js" -o "$AWS_JS" \
|| { printf '\033[0;31mFailed to download aws.js\033[0m\n' >&2; exit 1; }
exec bun run "$AWS_JS" claude "$@"

View file

@ -21,6 +21,6 @@ fi
# Remote — download and run compiled TypeScript bundle
AWS_JS=$(mktemp)
trap 'rm -f "$AWS_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/aws-latest/aws.js" -o "$AWS_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/aws-latest/aws.js" -o "$AWS_JS" \
|| { printf '\033[0;31mFailed to download aws.js\033[0m\n' >&2; exit 1; }
exec bun run "$AWS_JS" codex "$@"

View file

@ -21,6 +21,6 @@ fi
# Remote — download and run compiled TypeScript bundle
AWS_JS=$(mktemp)
trap 'rm -f "$AWS_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/aws-latest/aws.js" -o "$AWS_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/aws-latest/aws.js" -o "$AWS_JS" \
|| { printf '\033[0;31mFailed to download aws.js\033[0m\n' >&2; exit 1; }
exec bun run "$AWS_JS" cursor "$@"

View file

@ -21,6 +21,6 @@ fi
# Remote — download and run compiled TypeScript bundle
AWS_JS=$(mktemp)
trap 'rm -f "$AWS_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/aws-latest/aws.js" -o "$AWS_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/aws-latest/aws.js" -o "$AWS_JS" \
|| { printf '\033[0;31mFailed to download aws.js\033[0m\n' >&2; exit 1; }
exec bun run "$AWS_JS" hermes "$@"

View file

@ -21,6 +21,6 @@ fi
# Remote — download and run compiled TypeScript bundle
AWS_JS=$(mktemp)
trap 'rm -f "$AWS_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/aws-latest/aws.js" -o "$AWS_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/aws-latest/aws.js" -o "$AWS_JS" \
|| { printf '\033[0;31mFailed to download aws.js\033[0m\n' >&2; exit 1; }
exec bun run "$AWS_JS" junie "$@"

View file

@ -21,6 +21,6 @@ fi
# Remote — download and run compiled TypeScript bundle
AWS_JS=$(mktemp)
trap 'rm -f "$AWS_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/aws-latest/aws.js" -o "$AWS_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/aws-latest/aws.js" -o "$AWS_JS" \
|| { printf '\033[0;31mFailed to download aws.js\033[0m\n' >&2; exit 1; }
exec bun run "$AWS_JS" kilocode "$@"

View file

@ -21,6 +21,6 @@ fi
# Remote — download and run compiled TypeScript bundle
AWS_JS=$(mktemp)
trap 'rm -f "$AWS_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/aws-latest/aws.js" -o "$AWS_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/aws-latest/aws.js" -o "$AWS_JS" \
|| { printf '\033[0;31mFailed to download aws.js\033[0m\n' >&2; exit 1; }
exec bun run "$AWS_JS" openclaw "$@"

View file

@ -21,6 +21,6 @@ fi
# Remote — download and run compiled TypeScript bundle
AWS_JS=$(mktemp)
trap 'rm -f "$AWS_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/aws-latest/aws.js" -o "$AWS_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/aws-latest/aws.js" -o "$AWS_JS" \
|| { printf '\033[0;31mFailed to download aws.js\033[0m\n' >&2; exit 1; }
exec bun run "$AWS_JS" opencode "$@"

View file

@ -21,6 +21,6 @@ fi
# Remote — download and run compiled TypeScript bundle
AWS_JS=$(mktemp)
trap 'rm -f "$AWS_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/aws-latest/aws.js" -o "$AWS_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/aws-latest/aws.js" -o "$AWS_JS" \
|| { printf '\033[0;31mFailed to download aws.js\033[0m\n' >&2; exit 1; }
exec bun run "$AWS_JS" pi "$@"

View file

@ -21,6 +21,6 @@ fi
# Remote — download and run compiled TypeScript bundle
AWS_JS=$(mktemp)
trap 'rm -f "$AWS_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/aws-latest/aws.js" -o "$AWS_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/aws-latest/aws.js" -o "$AWS_JS" \
|| { printf '\033[0;31mFailed to download aws.js\033[0m\n' >&2; exit 1; }
exec bun run "$AWS_JS" t3code "$@"

View file

@ -12,7 +12,7 @@
$ErrorActionPreference = "Stop"
$SPAWN_REPO = "OpenRouterTeam/spawn"
$SPAWN_REPO = "OpenRouterLabs/spawn"
$SPAWN_RAW_BASE = "https://raw.githubusercontent.com/$SPAWN_REPO/main"
$MIN_BUN_VERSION = [version]"1.2.0"

View file

@ -11,7 +11,7 @@
set -eo pipefail
SPAWN_REPO="OpenRouterTeam/spawn"
SPAWN_REPO="OpenRouterLabs/spawn"
SPAWN_CDN="https://openrouter.ai/labs/spawn"
SPAWN_RAW_BASE="https://raw.githubusercontent.com/${SPAWN_REPO}/main"
MIN_BUN_VERSION="1.2.0"

View file

@ -21,7 +21,7 @@ fi
# Remote — download bundled daytona.js from GitHub release
DAYTONA_JS=$(mktemp)
trap 'rm -f "$DAYTONA_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/daytona-latest/daytona.js" -o "$DAYTONA_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/daytona-latest/daytona.js" -o "$DAYTONA_JS" \
|| { printf '\033[0;31mFailed to download daytona.js\033[0m\n' >&2; exit 1; }
exec bun run "$DAYTONA_JS" claude "$@"

View file

@ -21,7 +21,7 @@ fi
# Remote — download bundled daytona.js from GitHub release
DAYTONA_JS=$(mktemp)
trap 'rm -f "$DAYTONA_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/daytona-latest/daytona.js" -o "$DAYTONA_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/daytona-latest/daytona.js" -o "$DAYTONA_JS" \
|| { printf '\033[0;31mFailed to download daytona.js\033[0m\n' >&2; exit 1; }
exec bun run "$DAYTONA_JS" codex "$@"

View file

@ -21,7 +21,7 @@ fi
# Remote — download bundled daytona.js from GitHub release
DAYTONA_JS=$(mktemp)
trap 'rm -f "$DAYTONA_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/daytona-latest/daytona.js" -o "$DAYTONA_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/daytona-latest/daytona.js" -o "$DAYTONA_JS" \
|| { printf '\033[0;31mFailed to download daytona.js\033[0m\n' >&2; exit 1; }
exec bun run "$DAYTONA_JS" cursor "$@"

View file

@ -21,7 +21,7 @@ fi
# Remote — download bundled daytona.js from GitHub release
DAYTONA_JS=$(mktemp)
trap 'rm -f "$DAYTONA_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/daytona-latest/daytona.js" -o "$DAYTONA_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/daytona-latest/daytona.js" -o "$DAYTONA_JS" \
|| { printf '\033[0;31mFailed to download daytona.js\033[0m\n' >&2; exit 1; }
exec bun run "$DAYTONA_JS" hermes "$@"

View file

@ -21,7 +21,7 @@ fi
# Remote — download bundled daytona.js from GitHub release
DAYTONA_JS=$(mktemp)
trap 'rm -f "$DAYTONA_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/daytona-latest/daytona.js" -o "$DAYTONA_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/daytona-latest/daytona.js" -o "$DAYTONA_JS" \
|| { printf '\033[0;31mFailed to download daytona.js\033[0m\n' >&2; exit 1; }
exec bun run "$DAYTONA_JS" junie "$@"

View file

@ -21,7 +21,7 @@ fi
# Remote — download bundled daytona.js from GitHub release
DAYTONA_JS=$(mktemp)
trap 'rm -f "$DAYTONA_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/daytona-latest/daytona.js" -o "$DAYTONA_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/daytona-latest/daytona.js" -o "$DAYTONA_JS" \
|| { printf '\033[0;31mFailed to download daytona.js\033[0m\n' >&2; exit 1; }
exec bun run "$DAYTONA_JS" kilocode "$@"

View file

@ -21,7 +21,7 @@ fi
# Remote — download bundled daytona.js from GitHub release
DAYTONA_JS=$(mktemp)
trap 'rm -f "$DAYTONA_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/daytona-latest/daytona.js" -o "$DAYTONA_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/daytona-latest/daytona.js" -o "$DAYTONA_JS" \
|| { printf '\033[0;31mFailed to download daytona.js\033[0m\n' >&2; exit 1; }
exec bun run "$DAYTONA_JS" openclaw "$@"

View file

@ -21,7 +21,7 @@ fi
# Remote — download bundled daytona.js from GitHub release
DAYTONA_JS=$(mktemp)
trap 'rm -f "$DAYTONA_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/daytona-latest/daytona.js" -o "$DAYTONA_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/daytona-latest/daytona.js" -o "$DAYTONA_JS" \
|| { printf '\033[0;31mFailed to download daytona.js\033[0m\n' >&2; exit 1; }
exec bun run "$DAYTONA_JS" opencode "$@"

View file

@ -21,7 +21,7 @@ fi
# Remote — download bundled daytona.js from GitHub release
DAYTONA_JS=$(mktemp)
trap 'rm -f "$DAYTONA_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/daytona-latest/daytona.js" -o "$DAYTONA_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/daytona-latest/daytona.js" -o "$DAYTONA_JS" \
|| { printf '\033[0;31mFailed to download daytona.js\033[0m\n' >&2; exit 1; }
exec bun run "$DAYTONA_JS" pi "$@"

View file

@ -21,7 +21,7 @@ fi
# Remote — download bundled daytona.js from GitHub release
DAYTONA_JS=$(mktemp)
trap 'rm -f "$DAYTONA_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/daytona-latest/daytona.js" -o "$DAYTONA_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/daytona-latest/daytona.js" -o "$DAYTONA_JS" \
|| { printf '\033[0;31mFailed to download daytona.js\033[0m\n' >&2; exit 1; }
exec bun run "$DAYTONA_JS" t3code "$@"

View file

@ -77,7 +77,7 @@ fi
# Remote — download bundled digitalocean.js from GitHub release
DO_JS=$(mktemp)
trap 'rm -f "$DO_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/digitalocean-latest/digitalocean.js" -o "$DO_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/digitalocean-latest/digitalocean.js" -o "$DO_JS" \
|| { printf '\033[0;31mFailed to download digitalocean.js\033[0m\n' >&2; exit 1; }
_run_with_restart bun run "$DO_JS" "$_AGENT_NAME" "$@"

View file

@ -77,7 +77,7 @@ fi
# Remote — download bundled digitalocean.js from GitHub release
DO_JS=$(mktemp)
trap 'rm -f "$DO_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/digitalocean-latest/digitalocean.js" -o "$DO_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/digitalocean-latest/digitalocean.js" -o "$DO_JS" \
|| { printf '\033[0;31mFailed to download digitalocean.js\033[0m\n' >&2; exit 1; }
_run_with_restart bun run "$DO_JS" "$_AGENT_NAME" "$@"

View file

@ -77,7 +77,7 @@ fi
# Remote — download bundled digitalocean.js from GitHub release
DO_JS=$(mktemp)
trap 'rm -f "$DO_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/digitalocean-latest/digitalocean.js" -o "$DO_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/digitalocean-latest/digitalocean.js" -o "$DO_JS" \
|| { printf '\033[0;31mFailed to download digitalocean.js\033[0m\n' >&2; exit 1; }
_run_with_restart bun run "$DO_JS" "$_AGENT_NAME" "$@"

View file

@ -77,7 +77,7 @@ fi
# Remote — download bundled digitalocean.js from GitHub release
DO_JS=$(mktemp)
trap 'rm -f "$DO_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/digitalocean-latest/digitalocean.js" -o "$DO_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/digitalocean-latest/digitalocean.js" -o "$DO_JS" \
|| { printf '\033[0;31mFailed to download digitalocean.js\033[0m\n' >&2; exit 1; }
_run_with_restart bun run "$DO_JS" "$_AGENT_NAME" "$@"

View file

@ -77,7 +77,7 @@ fi
# Remote — download bundled digitalocean.js from GitHub release
DO_JS=$(mktemp)
trap 'rm -f "$DO_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/digitalocean-latest/digitalocean.js" -o "$DO_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/digitalocean-latest/digitalocean.js" -o "$DO_JS" \
|| { printf '\033[0;31mFailed to download digitalocean.js\033[0m\n' >&2; exit 1; }
_run_with_restart bun run "$DO_JS" "$_AGENT_NAME" "$@"

View file

@ -77,7 +77,7 @@ fi
# Remote — download bundled digitalocean.js from GitHub release
DO_JS=$(mktemp)
trap 'rm -f "$DO_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/digitalocean-latest/digitalocean.js" -o "$DO_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/digitalocean-latest/digitalocean.js" -o "$DO_JS" \
|| { printf '\033[0;31mFailed to download digitalocean.js\033[0m\n' >&2; exit 1; }
_run_with_restart bun run "$DO_JS" "$_AGENT_NAME" "$@"

View file

@ -77,7 +77,7 @@ fi
# Remote — download bundled digitalocean.js from GitHub release
DO_JS=$(mktemp)
trap 'rm -f "$DO_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/digitalocean-latest/digitalocean.js" -o "$DO_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/digitalocean-latest/digitalocean.js" -o "$DO_JS" \
|| { printf '\033[0;31mFailed to download digitalocean.js\033[0m\n' >&2; exit 1; }
_run_with_restart bun run "$DO_JS" "$_AGENT_NAME" "$@"

View file

@ -77,7 +77,7 @@ fi
# Remote — download bundled digitalocean.js from GitHub release
DO_JS=$(mktemp)
trap 'rm -f "$DO_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/digitalocean-latest/digitalocean.js" -o "$DO_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/digitalocean-latest/digitalocean.js" -o "$DO_JS" \
|| { printf '\033[0;31mFailed to download digitalocean.js\033[0m\n' >&2; exit 1; }
_run_with_restart bun run "$DO_JS" "$_AGENT_NAME" "$@"

View file

@ -77,7 +77,7 @@ fi
# Remote — download bundled digitalocean.js from GitHub release
DO_JS=$(mktemp)
trap 'rm -f "$DO_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/digitalocean-latest/digitalocean.js" -o "$DO_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/digitalocean-latest/digitalocean.js" -o "$DO_JS" \
|| { printf '\033[0;31mFailed to download digitalocean.js\033[0m\n' >&2; exit 1; }
_run_with_restart bun run "$DO_JS" "$_AGENT_NAME" "$@"

View file

@ -21,6 +21,6 @@ fi
# Remote — download and run compiled TypeScript bundle
DO_JS=$(mktemp)
trap 'rm -f "$DO_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/digitalocean-latest/digitalocean.js" -o "$DO_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/digitalocean-latest/digitalocean.js" -o "$DO_JS" \
|| { printf '\033[0;31mFailed to download digitalocean.js\033[0m\n' >&2; exit 1; }
exec bun run "$DO_JS" t3code "$@"

View file

@ -14,7 +14,7 @@ RUN OC_ARCH=$(uname -m) && \
OC_OS=$(uname -s | tr A-Z a-z) && \
mkdir -p /tmp/opencode-install /root/.opencode/bin && \
curl --proto '=https' -fsSL -o /tmp/opencode-install/oc.tar.gz \
"https://github.com/sst/opencode/releases/latest/download/opencode-${OC_OS}-${OC_ARCH}.tar.gz" && \
"https://github.com/anomalyco/opencode/releases/latest/download/opencode-${OC_OS}-${OC_ARCH}.tar.gz" && \
tar xzf /tmp/opencode-install/oc.tar.gz -C /tmp/opencode-install && \
mv /tmp/opencode-install/opencode /root/.opencode/bin/ && \
rm -rf /tmp/opencode-install

View file

@ -72,7 +72,7 @@ ${example}
local issue_url
if issue_url=$(gh issue create \
--repo OpenRouterTeam/spawn \
--repo OpenRouterLabs/spawn \
--title "${title}" \
--label "ux" \
--body "${body}" 2>/dev/null); then
@ -80,7 +80,7 @@ ${example}
else
# Label may not exist — retry without it
if issue_url=$(gh issue create \
--repo OpenRouterTeam/spawn \
--repo OpenRouterLabs/spawn \
--title "${title}" \
--body "${body}" 2>/dev/null); then
log_ok "UX issue filed: ${issue_url}"

View file

@ -21,7 +21,7 @@ fi
# Remote — download bundled gcp.js from GitHub release
GCP_JS=$(mktemp)
trap 'rm -f "$GCP_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/gcp-latest/gcp.js" -o "$GCP_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/gcp-latest/gcp.js" -o "$GCP_JS" \
|| { printf '\033[0;31mFailed to download gcp.js\033[0m\n' >&2; exit 1; }
exec bun run "$GCP_JS" claude "$@"

View file

@ -21,7 +21,7 @@ fi
# Remote — download bundled gcp.js from GitHub release
GCP_JS=$(mktemp)
trap 'rm -f "$GCP_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/gcp-latest/gcp.js" -o "$GCP_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/gcp-latest/gcp.js" -o "$GCP_JS" \
|| { printf '\033[0;31mFailed to download gcp.js\033[0m\n' >&2; exit 1; }
exec bun run "$GCP_JS" codex "$@"

View file

@ -21,7 +21,7 @@ fi
# Remote — download bundled gcp.js from GitHub release
GCP_JS=$(mktemp)
trap 'rm -f "$GCP_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/gcp-latest/gcp.js" -o "$GCP_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/gcp-latest/gcp.js" -o "$GCP_JS" \
|| { printf '\033[0;31mFailed to download gcp.js\033[0m\n' >&2; exit 1; }
exec bun run "$GCP_JS" cursor "$@"

View file

@ -21,7 +21,7 @@ fi
# Remote — download bundled gcp.js from GitHub release
GCP_JS=$(mktemp)
trap 'rm -f "$GCP_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/gcp-latest/gcp.js" -o "$GCP_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/gcp-latest/gcp.js" -o "$GCP_JS" \
|| { printf '\033[0;31mFailed to download gcp.js\033[0m\n' >&2; exit 1; }
exec bun run "$GCP_JS" hermes "$@"

View file

@ -21,7 +21,7 @@ fi
# Remote — download bundled gcp.js from GitHub release
GCP_JS=$(mktemp)
trap 'rm -f "$GCP_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/gcp-latest/gcp.js" -o "$GCP_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/gcp-latest/gcp.js" -o "$GCP_JS" \
|| { printf '\033[0;31mFailed to download gcp.js\033[0m\n' >&2; exit 1; }
exec bun run "$GCP_JS" junie "$@"

View file

@ -21,7 +21,7 @@ fi
# Remote — download bundled gcp.js from GitHub release
GCP_JS=$(mktemp)
trap 'rm -f "$GCP_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/gcp-latest/gcp.js" -o "$GCP_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/gcp-latest/gcp.js" -o "$GCP_JS" \
|| { printf '\033[0;31mFailed to download gcp.js\033[0m\n' >&2; exit 1; }
exec bun run "$GCP_JS" kilocode "$@"

View file

@ -21,7 +21,7 @@ fi
# Remote — download bundled gcp.js from GitHub release
GCP_JS=$(mktemp)
trap 'rm -f "$GCP_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/gcp-latest/gcp.js" -o "$GCP_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/gcp-latest/gcp.js" -o "$GCP_JS" \
|| { printf '\033[0;31mFailed to download gcp.js\033[0m\n' >&2; exit 1; }
exec bun run "$GCP_JS" openclaw "$@"

View file

@ -21,7 +21,7 @@ fi
# Remote — download bundled gcp.js from GitHub release
GCP_JS=$(mktemp)
trap 'rm -f "$GCP_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/gcp-latest/gcp.js" -o "$GCP_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/gcp-latest/gcp.js" -o "$GCP_JS" \
|| { printf '\033[0;31mFailed to download gcp.js\033[0m\n' >&2; exit 1; }
exec bun run "$GCP_JS" opencode "$@"

View file

@ -21,7 +21,7 @@ fi
# Remote — download bundled gcp.js from GitHub release
GCP_JS=$(mktemp)
trap 'rm -f "$GCP_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/gcp-latest/gcp.js" -o "$GCP_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/gcp-latest/gcp.js" -o "$GCP_JS" \
|| { printf '\033[0;31mFailed to download gcp.js\033[0m\n' >&2; exit 1; }
exec bun run "$GCP_JS" pi "$@"

View file

@ -21,6 +21,6 @@ fi
# Remote — download and run compiled TypeScript bundle
GCP_JS=$(mktemp)
trap 'rm -f "$GCP_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/gcp-latest/gcp.js" -o "$GCP_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/gcp-latest/gcp.js" -o "$GCP_JS" \
|| { printf '\033[0;31mFailed to download gcp.js\033[0m\n' >&2; exit 1; }
exec bun run "$GCP_JS" t3code "$@"

View file

@ -17,6 +17,6 @@ fi
HETZNER_JS=$(mktemp)
trap 'rm -f "$HETZNER_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/hetzner-latest/hetzner.js" -o "$HETZNER_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/hetzner-latest/hetzner.js" -o "$HETZNER_JS" \
|| { printf '\033[0;31mFailed to download hetzner.js\033[0m\n' >&2; exit 1; }
exec bun run "$HETZNER_JS" claude "$@"

View file

@ -17,6 +17,6 @@ fi
HETZNER_JS=$(mktemp)
trap 'rm -f "$HETZNER_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/hetzner-latest/hetzner.js" -o "$HETZNER_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/hetzner-latest/hetzner.js" -o "$HETZNER_JS" \
|| { printf '\033[0;31mFailed to download hetzner.js\033[0m\n' >&2; exit 1; }
exec bun run "$HETZNER_JS" codex "$@"

View file

@ -21,6 +21,6 @@ fi
# Remote — download and run compiled TypeScript bundle
HETZNER_JS=$(mktemp)
trap 'rm -f "$HETZNER_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/hetzner-latest/hetzner.js" -o "$HETZNER_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/hetzner-latest/hetzner.js" -o "$HETZNER_JS" \
|| { printf '\033[0;31mFailed to download hetzner.js\033[0m\n' >&2; exit 1; }
exec bun run "$HETZNER_JS" cursor "$@"

View file

@ -21,6 +21,6 @@ fi
# Remote — download and run compiled TypeScript bundle
HETZNER_JS=$(mktemp)
trap 'rm -f "$HETZNER_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/hetzner-latest/hetzner.js" -o "$HETZNER_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/hetzner-latest/hetzner.js" -o "$HETZNER_JS" \
|| { printf '\033[0;31mFailed to download hetzner.js\033[0m\n' >&2; exit 1; }
exec bun run "$HETZNER_JS" hermes "$@"

View file

@ -21,6 +21,6 @@ fi
# Remote — download and run compiled TypeScript bundle
HETZNER_JS=$(mktemp)
trap 'rm -f "$HETZNER_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/hetzner-latest/hetzner.js" -o "$HETZNER_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/hetzner-latest/hetzner.js" -o "$HETZNER_JS" \
|| { printf '\033[0;31mFailed to download hetzner.js\033[0m\n' >&2; exit 1; }
exec bun run "$HETZNER_JS" junie "$@"

View file

@ -17,6 +17,6 @@ fi
HETZNER_JS=$(mktemp)
trap 'rm -f "$HETZNER_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/hetzner-latest/hetzner.js" -o "$HETZNER_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/hetzner-latest/hetzner.js" -o "$HETZNER_JS" \
|| { printf '\033[0;31mFailed to download hetzner.js\033[0m\n' >&2; exit 1; }
exec bun run "$HETZNER_JS" kilocode "$@"

View file

@ -17,6 +17,6 @@ fi
HETZNER_JS=$(mktemp)
trap 'rm -f "$HETZNER_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/hetzner-latest/hetzner.js" -o "$HETZNER_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/hetzner-latest/hetzner.js" -o "$HETZNER_JS" \
|| { printf '\033[0;31mFailed to download hetzner.js\033[0m\n' >&2; exit 1; }
exec bun run "$HETZNER_JS" openclaw "$@"

View file

@ -17,6 +17,6 @@ fi
HETZNER_JS=$(mktemp)
trap 'rm -f "$HETZNER_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/hetzner-latest/hetzner.js" -o "$HETZNER_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/hetzner-latest/hetzner.js" -o "$HETZNER_JS" \
|| { printf '\033[0;31mFailed to download hetzner.js\033[0m\n' >&2; exit 1; }
exec bun run "$HETZNER_JS" opencode "$@"

View file

@ -17,6 +17,6 @@ fi
HETZNER_JS=$(mktemp)
trap 'rm -f "$HETZNER_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/hetzner-latest/hetzner.js" -o "$HETZNER_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/hetzner-latest/hetzner.js" -o "$HETZNER_JS" \
|| { printf '\033[0;31mFailed to download hetzner.js\033[0m\n' >&2; exit 1; }
exec bun run "$HETZNER_JS" pi "$@"

View file

@ -21,6 +21,6 @@ fi
# Remote — download and run compiled TypeScript bundle
HETZNER_JS=$(mktemp)
trap 'rm -f "$HETZNER_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/hetzner-latest/hetzner.js" -o "$HETZNER_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/hetzner-latest/hetzner.js" -o "$HETZNER_JS" \
|| { printf '\033[0;31mFailed to download hetzner.js\033[0m\n' >&2; exit 1; }
exec bun run "$HETZNER_JS" t3code "$@"

View file

@ -6,7 +6,7 @@ Run agents directly on your local machine without any cloud provisioning.
## Quick Start
If you have the [spawn CLI](https://github.com/OpenRouterTeam/spawn) installed:
If you have the [spawn CLI](https://github.com/OpenRouterLabs/spawn) installed:
```bash
spawn claude local

View file

@ -21,7 +21,7 @@ fi
# Remote — download bundled local.js from GitHub release
LOCAL_JS=$(mktemp)
trap 'rm -f "$LOCAL_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/local-latest/local.js" -o "$LOCAL_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/local-latest/local.js" -o "$LOCAL_JS" \
|| { printf '\033[0;31mFailed to download local.js\033[0m\n' >&2; exit 1; }
exec bun run "$LOCAL_JS" claude "$@"

View file

@ -21,7 +21,7 @@ fi
# Remote — download bundled local.js from GitHub release
LOCAL_JS=$(mktemp)
trap 'rm -f "$LOCAL_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/local-latest/local.js" -o "$LOCAL_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/local-latest/local.js" -o "$LOCAL_JS" \
|| { printf '\033[0;31mFailed to download local.js\033[0m\n' >&2; exit 1; }
exec bun run "$LOCAL_JS" codex "$@"

View file

@ -21,7 +21,7 @@ fi
# Remote — download bundled local.js from GitHub release
LOCAL_JS=$(mktemp)
trap 'rm -f "$LOCAL_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/local-latest/local.js" -o "$LOCAL_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/local-latest/local.js" -o "$LOCAL_JS" \
|| { printf '\033[0;31mFailed to download local.js\033[0m\n' >&2; exit 1; }
exec bun run "$LOCAL_JS" cursor "$@"

View file

@ -21,7 +21,7 @@ fi
# Remote — download bundled local.js from GitHub release
LOCAL_JS=$(mktemp)
trap 'rm -f "$LOCAL_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/local-latest/local.js" -o "$LOCAL_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/local-latest/local.js" -o "$LOCAL_JS" \
|| { printf '\033[0;31mFailed to download local.js\033[0m\n' >&2; exit 1; }
exec bun run "$LOCAL_JS" hermes "$@"

View file

@ -21,7 +21,7 @@ fi
# Remote — download bundled local.js from GitHub release
LOCAL_JS=$(mktemp)
trap 'rm -f "$LOCAL_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/local-latest/local.js" -o "$LOCAL_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/local-latest/local.js" -o "$LOCAL_JS" \
|| { printf '\033[0;31mFailed to download local.js\033[0m\n' >&2; exit 1; }
exec bun run "$LOCAL_JS" junie "$@"

View file

@ -21,7 +21,7 @@ fi
# Remote — download bundled local.js from GitHub release
LOCAL_JS=$(mktemp)
trap 'rm -f "$LOCAL_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/local-latest/local.js" -o "$LOCAL_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/local-latest/local.js" -o "$LOCAL_JS" \
|| { printf '\033[0;31mFailed to download local.js\033[0m\n' >&2; exit 1; }
exec bun run "$LOCAL_JS" kilocode "$@"

View file

@ -21,7 +21,7 @@ fi
# Remote — download bundled local.js from GitHub release
LOCAL_JS=$(mktemp)
trap 'rm -f "$LOCAL_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/local-latest/local.js" -o "$LOCAL_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/local-latest/local.js" -o "$LOCAL_JS" \
|| { printf '\033[0;31mFailed to download local.js\033[0m\n' >&2; exit 1; }
exec bun run "$LOCAL_JS" openclaw "$@"

View file

@ -21,7 +21,7 @@ fi
# Remote — download bundled local.js from GitHub release
LOCAL_JS=$(mktemp)
trap 'rm -f "$LOCAL_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/local-latest/local.js" -o "$LOCAL_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/local-latest/local.js" -o "$LOCAL_JS" \
|| { printf '\033[0;31mFailed to download local.js\033[0m\n' >&2; exit 1; }
exec bun run "$LOCAL_JS" opencode "$@"

View file

@ -21,7 +21,7 @@ fi
# Remote — download bundled local.js from GitHub release
LOCAL_JS=$(mktemp)
trap 'rm -f "$LOCAL_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/local-latest/local.js" -o "$LOCAL_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/local-latest/local.js" -o "$LOCAL_JS" \
|| { printf '\033[0;31mFailed to download local.js\033[0m\n' >&2; exit 1; }
exec bun run "$LOCAL_JS" pi "$@"

View file

@ -21,7 +21,7 @@ fi
# Remote — download bundled local.js from GitHub release
LOCAL_JS=$(mktemp)
trap 'rm -f "$LOCAL_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/local-latest/local.js" -o "$LOCAL_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/local-latest/local.js" -o "$LOCAL_JS" \
|| { printf '\033[0;31mFailed to download local.js\033[0m\n' >&2; exit 1; }
exec bun run "$LOCAL_JS" t3code "$@"

View file

@ -8,7 +8,7 @@ This was previously the `--beta sandbox` flag on the `local` cloud. It is now a
## Quick Start
If you have the [spawn CLI](https://github.com/OpenRouterTeam/spawn) installed:
If you have the [spawn CLI](https://github.com/OpenRouterLabs/spawn) installed:
```bash
spawn claude sandbox

View file

@ -23,7 +23,7 @@ fi
# Remote — download bundled sandbox.js from GitHub release
SANDBOX_JS=$(mktemp)
trap 'rm -f "$SANDBOX_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/sandbox-latest/sandbox.js" -o "$SANDBOX_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/sandbox-latest/sandbox.js" -o "$SANDBOX_JS" \
|| { printf '\033[0;31mFailed to download sandbox.js\033[0m\n' >&2; exit 1; }
exec bun run "$SANDBOX_JS" claude "$@"

View file

@ -23,7 +23,7 @@ fi
# Remote — download bundled sandbox.js from GitHub release
SANDBOX_JS=$(mktemp)
trap 'rm -f "$SANDBOX_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/sandbox-latest/sandbox.js" -o "$SANDBOX_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/sandbox-latest/sandbox.js" -o "$SANDBOX_JS" \
|| { printf '\033[0;31mFailed to download sandbox.js\033[0m\n' >&2; exit 1; }
exec bun run "$SANDBOX_JS" codex "$@"

View file

@ -23,7 +23,7 @@ fi
# Remote — download bundled sandbox.js from GitHub release
SANDBOX_JS=$(mktemp)
trap 'rm -f "$SANDBOX_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/sandbox-latest/sandbox.js" -o "$SANDBOX_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/sandbox-latest/sandbox.js" -o "$SANDBOX_JS" \
|| { printf '\033[0;31mFailed to download sandbox.js\033[0m\n' >&2; exit 1; }
exec bun run "$SANDBOX_JS" cursor "$@"

View file

@ -23,7 +23,7 @@ fi
# Remote — download bundled sandbox.js from GitHub release
SANDBOX_JS=$(mktemp)
trap 'rm -f "$SANDBOX_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/sandbox-latest/sandbox.js" -o "$SANDBOX_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/sandbox-latest/sandbox.js" -o "$SANDBOX_JS" \
|| { printf '\033[0;31mFailed to download sandbox.js\033[0m\n' >&2; exit 1; }
exec bun run "$SANDBOX_JS" hermes "$@"

View file

@ -23,7 +23,7 @@ fi
# Remote — download bundled sandbox.js from GitHub release
SANDBOX_JS=$(mktemp)
trap 'rm -f "$SANDBOX_JS"' EXIT
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/sandbox-latest/sandbox.js" -o "$SANDBOX_JS" \
curl -fsSL --proto '=https' "https://github.com/OpenRouterLabs/spawn/releases/download/sandbox-latest/sandbox.js" -o "$SANDBOX_JS" \
|| { printf '\033[0;31mFailed to download sandbox.js\033[0m\n' >&2; exit 1; }
exec bun run "$SANDBOX_JS" junie "$@"

Some files were not shown because too many files have changed in this diff Show more