Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude/rules/discovery.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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
Expand Down
2 changes: 1 addition & 1 deletion .claude/rules/git-workflow.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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:
Expand Down
4 changes: 2 additions & 2 deletions .claude/rules/shell-scripts.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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
Expand Down
2 changes: 1 addition & 1 deletion .claude/scripts/collaborator-gate.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -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() {
Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/pcl/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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.
Expand Down
4 changes: 2 additions & 2 deletions .claude/skills/setup-spa/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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.
Expand All@@ -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"
Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/setup-spa/main.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -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 ?? "";
Expand Down
4 changes: 2 additions & 2 deletions .claude/skills/setup-spa/spa.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -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", () => {
Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/update-metadata/update.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -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}`);
Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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:
Expand Down
14 changes: 7 additions & 7 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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

Expand All@@ -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/) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
Expand All@@ -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
```
Expand DownExpand Up@@ -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
Expand All@@ -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.

Expand Down
2 changes: 1 addition & 1 deletion fixtures/claude-code/stream-events.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -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",
Expand Down
40 changes: 20 additions & 20 deletions manifest.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand All@@ -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",
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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)",
Expand All@@ -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)",
Expand All@@ -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",
Expand All@@ -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",
Expand All@@ -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",
Expand All@@ -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",
Expand All@@ -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",
Expand All@@ -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": {
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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:
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/package.json
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
{
"name": "@openrouter/spawn",
"version": "1.1.0",
"version": "1.1.1",
"type": "module",
"bin": {
"spawn": "cli.js"
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude/rules/discovery.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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
Expand Down
2 changes: 1 addition & 1 deletion .claude/rules/git-workflow.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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:
Expand Down
4 changes: 2 additions & 2 deletions .claude/rules/shell-scripts.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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
Expand Down
2 changes: 1 addition & 1 deletion .claude/scripts/collaborator-gate.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -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() {
Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/pcl/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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.
Expand Down
4 changes: 2 additions & 2 deletions .claude/skills/setup-spa/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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.
Expand All@@ -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"
Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/setup-spa/main.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -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 ?? "";
Expand Down
4 changes: 2 additions & 2 deletions .claude/skills/setup-spa/spa.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -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", () => {
Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/update-metadata/update.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -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}`);
Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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:
Expand Down
14 changes: 7 additions & 7 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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

Expand All@@ -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/) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
Expand All@@ -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
```
Expand DownExpand Up@@ -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
Expand All@@ -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.

Expand Down
2 changes: 1 addition & 1 deletion fixtures/claude-code/stream-events.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -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",
Expand Down
40 changes: 20 additions & 20 deletions manifest.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand All@@ -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",
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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)",
Expand All@@ -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)",
Expand All@@ -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",
Expand All@@ -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",
Expand All@@ -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",
Expand All@@ -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",
Expand All@@ -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",
Expand All@@ -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": {
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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:
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/package.json
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
{
"name": "@openrouter/spawn",
"version": "1.1.0",
"version": "1.1.1",
"type": "module",
"bin": {
"spawn": "cli.js"
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude/rules/discovery.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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
Expand Down
2 changes: 1 addition & 1 deletion .claude/rules/git-workflow.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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:
Expand Down
4 changes: 2 additions & 2 deletions .claude/rules/shell-scripts.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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
Expand Down
2 changes: 1 addition & 1 deletion .claude/scripts/collaborator-gate.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -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() {
Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/pcl/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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.
Expand Down
4 changes: 2 additions & 2 deletions .claude/skills/setup-spa/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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.
Expand All@@ -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"
Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/setup-spa/main.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -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 ?? "";
Expand Down
4 changes: 2 additions & 2 deletions .claude/skills/setup-spa/spa.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -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", () => {
Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/update-metadata/update.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -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}`);
Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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:
Expand Down
14 changes: 7 additions & 7 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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

Expand All@@ -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/) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
Expand All@@ -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
```
Expand DownExpand Up@@ -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
Expand All@@ -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.

Expand Down
2 changes: 1 addition & 1 deletion fixtures/claude-code/stream-events.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -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",
Expand Down
40 changes: 20 additions & 20 deletions manifest.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand All@@ -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",
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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)",
Expand All@@ -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)",
Expand All@@ -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",
Expand All@@ -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",
Expand All@@ -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",
Expand All@@ -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",
Expand All@@ -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",
Expand All@@ -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": {
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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:
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/package.json
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
{
"name": "@openrouter/spawn",
"version": "1.1.0",
"version": "1.1.1",
"type": "module",
"bin": {
"spawn": "cli.js"
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude/rules/discovery.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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
Expand Down
2 changes: 1 addition & 1 deletion .claude/rules/git-workflow.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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:
Expand Down
4 changes: 2 additions & 2 deletions .claude/rules/shell-scripts.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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
Expand Down
2 changes: 1 addition & 1 deletion .claude/scripts/collaborator-gate.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -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() {
Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/pcl/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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.
Expand Down
4 changes: 2 additions & 2 deletions .claude/skills/setup-spa/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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.
Expand All@@ -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"
Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/setup-spa/main.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -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 ?? "";
Expand Down
4 changes: 2 additions & 2 deletions .claude/skills/setup-spa/spa.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -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", () => {
Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/update-metadata/update.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -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}`);
Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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:
Expand Down
14 changes: 7 additions & 7 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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

Expand All@@ -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/) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
Expand All@@ -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
```
Expand DownExpand Up@@ -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
Expand All@@ -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.

Expand Down
2 changes: 1 addition & 1 deletion fixtures/claude-code/stream-events.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -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",
Expand Down
40 changes: 20 additions & 20 deletions manifest.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand All@@ -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",
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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)",
Expand All@@ -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)",
Expand All@@ -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",
Expand All@@ -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",
Expand All@@ -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",
Expand All@@ -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",
Expand All@@ -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",
Expand All@@ -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": {
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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:
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/package.json
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
{
"name": "@openrouter/spawn",
"version": "1.1.0",
"version": "1.1.1",
"type": "module",
"bin": {
"spawn": "cli.js"
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude/rules/discovery.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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
Expand Down
2 changes: 1 addition & 1 deletion .claude/rules/git-workflow.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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:
Expand Down
4 changes: 2 additions & 2 deletions .claude/rules/shell-scripts.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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
Expand Down
2 changes: 1 addition & 1 deletion .claude/scripts/collaborator-gate.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -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() {
Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/pcl/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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.
Expand Down
4 changes: 2 additions & 2 deletions .claude/skills/setup-spa/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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.
Expand All@@ -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"
Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/setup-spa/main.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -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 ?? "";
Expand Down
4 changes: 2 additions & 2 deletions .claude/skills/setup-spa/spa.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -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", () => {
Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/update-metadata/update.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -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}`);
Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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:
Expand Down
14 changes: 7 additions & 7 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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

Expand All@@ -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/) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
Expand All@@ -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
```
Expand DownExpand Up@@ -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
Expand All@@ -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.

Expand Down
2 changes: 1 addition & 1 deletion fixtures/claude-code/stream-events.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -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",
Expand Down
40 changes: 20 additions & 20 deletions manifest.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand All@@ -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",
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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)",
Expand All@@ -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)",
Expand All@@ -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",
Expand All@@ -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",
Expand All@@ -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",
Expand All@@ -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",
Expand All@@ -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",
Expand All@@ -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": {
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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:
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/package.json
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
{
"name": "@openrouter/spawn",
"version": "1.1.0",
"version": "1.1.1",
"type": "module",
"bin": {
"spawn": "cli.js"
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude/rules/discovery.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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
Expand Down
2 changes: 1 addition & 1 deletion .claude/rules/git-workflow.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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:
Expand Down
4 changes: 2 additions & 2 deletions .claude/rules/shell-scripts.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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
Expand Down
2 changes: 1 addition & 1 deletion .claude/scripts/collaborator-gate.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -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() {
Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/pcl/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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.
Expand Down
4 changes: 2 additions & 2 deletions .claude/skills/setup-spa/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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.
Expand All@@ -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"
Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/setup-spa/main.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -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 ?? "";
Expand Down
4 changes: 2 additions & 2 deletions .claude/skills/setup-spa/spa.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -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", () => {
Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/update-metadata/update.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -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}`);
Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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:
Expand Down
14 changes: 7 additions & 7 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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

Expand All@@ -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/) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
Expand All@@ -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
```
Expand DownExpand Up@@ -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
Expand All@@ -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.

Expand Down
2 changes: 1 addition & 1 deletion fixtures/claude-code/stream-events.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -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",
Expand Down
40 changes: 20 additions & 20 deletions manifest.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand All@@ -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",
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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)",
Expand All@@ -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)",
Expand All@@ -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",
Expand All@@ -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",
Expand All@@ -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",
Expand All@@ -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",
Expand All@@ -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",
Expand All@@ -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": {
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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:
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/package.json
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
{
"name": "@openrouter/spawn",
"version": "1.1.0",
"version": "1.1.1",
"type": "module",
"bin": {
"spawn": "cli.js"
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude/rules/discovery.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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
Expand Down
2 changes: 1 addition & 1 deletion .claude/rules/git-workflow.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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:
Expand Down
4 changes: 2 additions & 2 deletions .claude/rules/shell-scripts.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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
Expand Down
2 changes: 1 addition & 1 deletion .claude/scripts/collaborator-gate.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -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() {
Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/pcl/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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.
Expand Down
4 changes: 2 additions & 2 deletions .claude/skills/setup-spa/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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.
Expand All@@ -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"
Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/setup-spa/main.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -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 ?? "";
Expand Down
4 changes: 2 additions & 2 deletions .claude/skills/setup-spa/spa.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -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", () => {
Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/update-metadata/update.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -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}`);
Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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:
Expand Down
14 changes: 7 additions & 7 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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

Expand All@@ -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/) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
Expand All@@ -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
```
Expand DownExpand Up@@ -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
Expand All@@ -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.

Expand Down
2 changes: 1 addition & 1 deletion fixtures/claude-code/stream-events.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -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",
Expand Down
40 changes: 20 additions & 20 deletions manifest.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand All@@ -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",
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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)",
Expand All@@ -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)",
Expand All@@ -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",
Expand All@@ -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",
Expand All@@ -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",
Expand All@@ -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",
Expand All@@ -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",
Expand All@@ -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": {
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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:
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/package.json
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
{
"name": "@openrouter/spawn",
"version": "1.1.0",
"version": "1.1.1",
"type": "module",
"bin": {
"spawn": "cli.js"
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude/rules/discovery.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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
Expand Down
2 changes: 1 addition & 1 deletion .claude/rules/git-workflow.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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:
Expand Down
4 changes: 2 additions & 2 deletions .claude/rules/shell-scripts.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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
Expand Down
2 changes: 1 addition & 1 deletion .claude/scripts/collaborator-gate.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -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() {
Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/pcl/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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.
Expand Down
4 changes: 2 additions & 2 deletions .claude/skills/setup-spa/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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.
Expand All@@ -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"
Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/setup-spa/main.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -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 ?? "";
Expand Down
4 changes: 2 additions & 2 deletions .claude/skills/setup-spa/spa.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -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", () => {
Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/update-metadata/update.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -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}`);
Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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:
Expand Down
14 changes: 7 additions & 7 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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

Expand All@@ -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/) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
Expand All@@ -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
```
Expand DownExpand Up@@ -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
Expand All@@ -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.

Expand Down
2 changes: 1 addition & 1 deletion fixtures/claude-code/stream-events.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -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",
Expand Down
40 changes: 20 additions & 20 deletions manifest.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand All@@ -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",
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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"
Expand DownExpand Up@@ -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)",
Expand All@@ -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)",
Expand All@@ -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",
Expand All@@ -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",
Expand All@@ -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",
Expand All@@ -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",
Expand All@@ -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",
Expand All@@ -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": {
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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:
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/package.json
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
{
"name": "@openrouter/spawn",
"version": "1.1.0",
"version": "1.1.1",
"type": "module",
"bin": {
"spawn": "cli.js"
Expand Down
Loading
Loading