mirror of
https://github.com/OpenRouterTeam/spawn.git
synced 2026-04-28 03:49:31 +00:00
feat(agent): add T3 Code agent (web GUI for Claude/Codex) (#3322)
All CI green. Rebased from #3321, added Daytona support, resolved conflicts. Security reviewed: no injection vectors — all env var values come from hardcoded config, shell scripts follow existing patterns.
This commit is contained in:
parent
51e36d2154
commit
57174a0f15
20 changed files with 301 additions and 2 deletions
|
|
@ -34,5 +34,9 @@
|
||||||
"pi": {
|
"pi": {
|
||||||
"url": "custom:shittycodingagent.ai/logo.svg (official Pi logo, converted to PNG with dark background)",
|
"url": "custom:shittycodingagent.ai/logo.svg (official Pi logo, converted to PNG with dark background)",
|
||||||
"ext": "png"
|
"ext": "png"
|
||||||
|
},
|
||||||
|
"t3code": {
|
||||||
|
"url": "https://avatars.githubusercontent.com/u/59054278?s=200&v=4",
|
||||||
|
"ext": "png"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
BIN
assets/agents/t3code.png
Normal file
BIN
assets/agents/t3code.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
|
|
@ -340,6 +340,43 @@
|
||||||
"agentic",
|
"agentic",
|
||||||
"cursor"
|
"cursor"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"t3code": {
|
||||||
|
"name": "T3 Code",
|
||||||
|
"description": "Minimal web GUI for coding agents by Ping.gg — wraps Claude Code and Codex with a browser-based interface",
|
||||||
|
"url": "https://github.com/pingdotgg/t3code",
|
||||||
|
"install": "npm install -g t3",
|
||||||
|
"launch": "t3",
|
||||||
|
"env": {
|
||||||
|
"OPENROUTER_API_KEY": "${OPENROUTER_API_KEY}",
|
||||||
|
"ANTHROPIC_BASE_URL": "https://openrouter.ai/api",
|
||||||
|
"ANTHROPIC_API_KEY": "${OPENROUTER_API_KEY}",
|
||||||
|
"OPENAI_API_KEY": "${OPENROUTER_API_KEY}",
|
||||||
|
"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",
|
||||||
|
"featured_cloud": [
|
||||||
|
"digitalocean",
|
||||||
|
"sprite"
|
||||||
|
],
|
||||||
|
"creator": "Ping.gg",
|
||||||
|
"repo": "pingdotgg/t3code",
|
||||||
|
"license": "MIT",
|
||||||
|
"created": "2025-06",
|
||||||
|
"added": "2026-04",
|
||||||
|
"github_stars": 9500,
|
||||||
|
"stars_updated": "2026-04-18",
|
||||||
|
"language": "TypeScript",
|
||||||
|
"runtime": "node",
|
||||||
|
"category": "gui",
|
||||||
|
"tagline": "Minimal web GUI for coding agents — browse, code, and ship via Claude or Codex",
|
||||||
|
"tags": [
|
||||||
|
"coding",
|
||||||
|
"web-gui",
|
||||||
|
"wrapper",
|
||||||
|
"pinggg"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"clouds": {
|
"clouds": {
|
||||||
|
|
@ -518,6 +555,13 @@
|
||||||
"digitalocean/cursor": "implemented",
|
"digitalocean/cursor": "implemented",
|
||||||
"gcp/cursor": "implemented",
|
"gcp/cursor": "implemented",
|
||||||
"daytona/cursor": "implemented",
|
"daytona/cursor": "implemented",
|
||||||
"sprite/cursor": "implemented"
|
"sprite/cursor": "implemented",
|
||||||
|
"local/t3code": "implemented",
|
||||||
|
"hetzner/t3code": "implemented",
|
||||||
|
"aws/t3code": "implemented",
|
||||||
|
"digitalocean/t3code": "implemented",
|
||||||
|
"gcp/t3code": "implemented",
|
||||||
|
"daytona/t3code": "implemented",
|
||||||
|
"sprite/t3code": "implemented"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@openrouter/spawn",
|
"name": "@openrouter/spawn",
|
||||||
"version": "1.0.16",
|
"version": "1.0.17",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"bin": {
|
"bin": {
|
||||||
"spawn": "cli.js"
|
"spawn": "cli.js"
|
||||||
|
|
|
||||||
|
|
@ -361,6 +361,7 @@ describe("Agent metadata field types", () => {
|
||||||
[
|
[
|
||||||
"cli",
|
"cli",
|
||||||
"tui",
|
"tui",
|
||||||
|
"gui",
|
||||||
"ide-extension",
|
"ide-extension",
|
||||||
],
|
],
|
||||||
`agent "${key}" category value`,
|
`agent "${key}" category value`,
|
||||||
|
|
|
||||||
|
|
@ -1399,6 +1399,34 @@ function createAgents(runner: CloudRunner): Record<string, AgentConfig> {
|
||||||
updateCmd: `${NPM_AUTO_UPDATE_SETUP} && ` + "npm install -g $_NPM_G_FLAGS @mariozechner/pi-coding-agent@latest",
|
updateCmd: `${NPM_AUTO_UPDATE_SETUP} && ` + "npm install -g $_NPM_G_FLAGS @mariozechner/pi-coding-agent@latest",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
t3code: {
|
||||||
|
name: "T3 Code",
|
||||||
|
cloudInitTier: "node" satisfies AgentConfig["cloudInitTier"],
|
||||||
|
preProvision: detectGithubAuth,
|
||||||
|
install: () =>
|
||||||
|
installAgent(
|
||||||
|
runner,
|
||||||
|
"T3 Code",
|
||||||
|
`${NPM_PREFIX_SETUP} && npm install -g \${_NPM_G_FLAGS} t3 && ${NPM_GLOBAL_PATH_PERSIST}`,
|
||||||
|
),
|
||||||
|
envVars: (apiKey) => [
|
||||||
|
`OPENROUTER_API_KEY=${apiKey}`,
|
||||||
|
`ANTHROPIC_API_KEY=${apiKey}`,
|
||||||
|
"ANTHROPIC_BASE_URL=https://openrouter.ai/api",
|
||||||
|
`OPENAI_API_KEY=${apiKey}`,
|
||||||
|
"OPENAI_BASE_URL=https://openrouter.ai/api/v1",
|
||||||
|
],
|
||||||
|
preLaunchMsg: "T3 Code web GUI will open automatically — use it to interact with Claude Code and Codex agents.",
|
||||||
|
launchCmd: () =>
|
||||||
|
"source ~/.spawnrc 2>/dev/null; source ~/.zshrc 2>/dev/null; t3 --port 3773 --host 0.0.0.0 --no-browser",
|
||||||
|
tunnel: {
|
||||||
|
remotePort: 3773,
|
||||||
|
browserUrl: (localPort: number) => `http://localhost:${localPort}`,
|
||||||
|
},
|
||||||
|
updateCmd:
|
||||||
|
'export PATH="$HOME/.npm-global/bin:$HOME/.bun/bin:$PATH"; ' + "npm install -g ${_NPM_G_FLAGS:-} t3@latest",
|
||||||
|
},
|
||||||
|
|
||||||
cursor: {
|
cursor: {
|
||||||
name: "Cursor CLI",
|
name: "Cursor CLI",
|
||||||
cloudInitTier: "bun",
|
cloudInitTier: "bun",
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,12 @@ bash <(curl -fsSL https://openrouter.ai/labs/spawn/aws/cursor.sh)
|
||||||
bash <(curl -fsSL https://openrouter.ai/labs/spawn/aws/pi.sh)
|
bash <(curl -fsSL https://openrouter.ai/labs/spawn/aws/pi.sh)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### T3 Code
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash <(curl -fsSL https://openrouter.ai/labs/spawn/aws/t3code.sh)
|
||||||
|
```
|
||||||
|
|
||||||
## Non-Interactive Mode
|
## Non-Interactive Mode
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
|
||||||
26
sh/aws/t3code.sh
Normal file
26
sh/aws/t3code.sh
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -eo pipefail
|
||||||
|
|
||||||
|
# Thin shim: ensures bun is available, runs bundled aws.js (local or from GitHub release)
|
||||||
|
|
||||||
|
_ensure_bun() {
|
||||||
|
if command -v bun &>/dev/null; then return 0; fi
|
||||||
|
printf '\033[0;36mInstalling bun...\033[0m\n' >&2
|
||||||
|
curl -fsSL --proto '=https' --show-error https://bun.sh/install?version=1.3.9 | bash >/dev/null || { printf '\033[0;31mFailed to install bun\033[0m\n' >&2; exit 1; }
|
||||||
|
export PATH="$HOME/.bun/bin:$PATH"
|
||||||
|
command -v bun &>/dev/null || { printf '\033[0;31mbun not found after install\033[0m\n' >&2; exit 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
_ensure_bun
|
||||||
|
|
||||||
|
# SPAWN_CLI_DIR override — force local source (used by e2e tests)
|
||||||
|
if [[ -n "${SPAWN_CLI_DIR:-}" && -f "$SPAWN_CLI_DIR/packages/cli/src/aws/main.ts" ]]; then
|
||||||
|
exec bun run "$SPAWN_CLI_DIR/packages/cli/src/aws/main.ts" t3code "$@"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Remote — download and run compiled TypeScript bundle
|
||||||
|
AWS_JS=$(mktemp)
|
||||||
|
trap 'rm -f "$AWS_JS"' EXIT
|
||||||
|
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/aws-latest/aws.js" -o "$AWS_JS" \
|
||||||
|
|| { printf '\033[0;31mFailed to download aws.js\033[0m\n' >&2; exit 1; }
|
||||||
|
exec bun run "$AWS_JS" t3code "$@"
|
||||||
|
|
@ -60,6 +60,12 @@ bash <(curl -fsSL https://openrouter.ai/labs/spawn/daytona/cursor.sh)
|
||||||
bash <(curl -fsSL https://openrouter.ai/labs/spawn/daytona/pi.sh)
|
bash <(curl -fsSL https://openrouter.ai/labs/spawn/daytona/pi.sh)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### T3 Code
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash <(curl -fsSL https://openrouter.ai/labs/spawn/daytona/t3code.sh)
|
||||||
|
```
|
||||||
|
|
||||||
## Non-Interactive Mode
|
## Non-Interactive Mode
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
|
||||||
27
sh/daytona/t3code.sh
Normal file
27
sh/daytona/t3code.sh
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -eo pipefail
|
||||||
|
|
||||||
|
# Thin shim: ensures bun is available, runs bundled daytona.js (local or from GitHub release)
|
||||||
|
|
||||||
|
_ensure_bun() {
|
||||||
|
if command -v bun &>/dev/null; then return 0; fi
|
||||||
|
printf '\033[0;36mInstalling bun...\033[0m\n' >&2
|
||||||
|
curl -fsSL --proto '=https' --show-error https://bun.sh/install?version=1.3.9 | bash >/dev/null || { printf '\033[0;31mFailed to install bun\033[0m\n' >&2; exit 1; }
|
||||||
|
export PATH="$HOME/.bun/bin:$PATH"
|
||||||
|
command -v bun &>/dev/null || { printf '\033[0;31mbun not found after install\033[0m\n' >&2; exit 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
_ensure_bun
|
||||||
|
|
||||||
|
# SPAWN_CLI_DIR override — force local source (used by e2e tests)
|
||||||
|
if [[ -n "${SPAWN_CLI_DIR:-}" && -f "$SPAWN_CLI_DIR/packages/cli/src/daytona/main.ts" ]]; then
|
||||||
|
exec bun run "$SPAWN_CLI_DIR/packages/cli/src/daytona/main.ts" t3code "$@"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Remote — download bundled daytona.js from GitHub release
|
||||||
|
DAYTONA_JS=$(mktemp)
|
||||||
|
trap 'rm -f "$DAYTONA_JS"' EXIT
|
||||||
|
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/daytona-latest/daytona.js" -o "$DAYTONA_JS" \
|
||||||
|
|| { printf '\033[0;31mFailed to download daytona.js\033[0m\n' >&2; exit 1; }
|
||||||
|
|
||||||
|
exec bun run "$DAYTONA_JS" t3code "$@"
|
||||||
|
|
@ -58,6 +58,12 @@ bash <(curl -fsSL https://openrouter.ai/labs/spawn/digitalocean/cursor.sh)
|
||||||
bash <(curl -fsSL https://openrouter.ai/labs/spawn/digitalocean/pi.sh)
|
bash <(curl -fsSL https://openrouter.ai/labs/spawn/digitalocean/pi.sh)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### T3 Code
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash <(curl -fsSL https://openrouter.ai/labs/spawn/digitalocean/t3code.sh)
|
||||||
|
```
|
||||||
|
|
||||||
## Environment Variables
|
## Environment Variables
|
||||||
|
|
||||||
| Variable | Description | Default |
|
| Variable | Description | Default |
|
||||||
|
|
|
||||||
26
sh/digitalocean/t3code.sh
Normal file
26
sh/digitalocean/t3code.sh
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -eo pipefail
|
||||||
|
|
||||||
|
# Thin shim: ensures bun is available, runs bundled digitalocean.js (local or from GitHub release)
|
||||||
|
|
||||||
|
_ensure_bun() {
|
||||||
|
if command -v bun &>/dev/null; then return 0; fi
|
||||||
|
printf '\033[0;36mInstalling bun...\033[0m\n' >&2
|
||||||
|
curl -fsSL --proto '=https' --show-error https://bun.sh/install?version=1.3.9 | bash >/dev/null || { printf '\033[0;31mFailed to install bun\033[0m\n' >&2; exit 1; }
|
||||||
|
export PATH="$HOME/.bun/bin:$PATH"
|
||||||
|
command -v bun &>/dev/null || { printf '\033[0;31mbun not found after install\033[0m\n' >&2; exit 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
_ensure_bun
|
||||||
|
|
||||||
|
# SPAWN_CLI_DIR override — force local source (used by e2e tests)
|
||||||
|
if [[ -n "${SPAWN_CLI_DIR:-}" && -f "$SPAWN_CLI_DIR/packages/cli/src/digitalocean/main.ts" ]]; then
|
||||||
|
exec bun run "$SPAWN_CLI_DIR/packages/cli/src/digitalocean/main.ts" t3code "$@"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Remote — download and run compiled TypeScript bundle
|
||||||
|
DO_JS=$(mktemp)
|
||||||
|
trap 'rm -f "$DO_JS"' EXIT
|
||||||
|
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/digitalocean-latest/digitalocean.js" -o "$DO_JS" \
|
||||||
|
|| { printf '\033[0;31mFailed to download digitalocean.js\033[0m\n' >&2; exit 1; }
|
||||||
|
exec bun run "$DO_JS" t3code "$@"
|
||||||
|
|
@ -60,6 +60,12 @@ bash <(curl -fsSL https://openrouter.ai/labs/spawn/gcp/cursor.sh)
|
||||||
bash <(curl -fsSL https://openrouter.ai/labs/spawn/gcp/pi.sh)
|
bash <(curl -fsSL https://openrouter.ai/labs/spawn/gcp/pi.sh)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### T3 Code
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash <(curl -fsSL https://openrouter.ai/labs/spawn/gcp/t3code.sh)
|
||||||
|
```
|
||||||
|
|
||||||
## Non-Interactive Mode
|
## Non-Interactive Mode
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
|
||||||
26
sh/gcp/t3code.sh
Normal file
26
sh/gcp/t3code.sh
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -eo pipefail
|
||||||
|
|
||||||
|
# Thin shim: ensures bun is available, runs bundled gcp.js (local or from GitHub release)
|
||||||
|
|
||||||
|
_ensure_bun() {
|
||||||
|
if command -v bun &>/dev/null; then return 0; fi
|
||||||
|
printf '\033[0;36mInstalling bun...\033[0m\n' >&2
|
||||||
|
curl -fsSL --proto '=https' --show-error https://bun.sh/install?version=1.3.9 | bash >/dev/null || { printf '\033[0;31mFailed to install bun\033[0m\n' >&2; exit 1; }
|
||||||
|
export PATH="$HOME/.bun/bin:$PATH"
|
||||||
|
command -v bun &>/dev/null || { printf '\033[0;31mbun not found after install\033[0m\n' >&2; exit 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
_ensure_bun
|
||||||
|
|
||||||
|
# SPAWN_CLI_DIR override — force local source (used by e2e tests)
|
||||||
|
if [[ -n "${SPAWN_CLI_DIR:-}" && -f "$SPAWN_CLI_DIR/packages/cli/src/gcp/main.ts" ]]; then
|
||||||
|
exec bun run "$SPAWN_CLI_DIR/packages/cli/src/gcp/main.ts" t3code "$@"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Remote — download and run compiled TypeScript bundle
|
||||||
|
GCP_JS=$(mktemp)
|
||||||
|
trap 'rm -f "$GCP_JS"' EXIT
|
||||||
|
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/gcp-latest/gcp.js" -o "$GCP_JS" \
|
||||||
|
|| { printf '\033[0;31mFailed to download gcp.js\033[0m\n' >&2; exit 1; }
|
||||||
|
exec bun run "$GCP_JS" t3code "$@"
|
||||||
|
|
@ -58,6 +58,12 @@ bash <(curl -fsSL https://openrouter.ai/labs/spawn/hetzner/cursor.sh)
|
||||||
bash <(curl -fsSL https://openrouter.ai/labs/spawn/hetzner/pi.sh)
|
bash <(curl -fsSL https://openrouter.ai/labs/spawn/hetzner/pi.sh)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### T3 Code
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash <(curl -fsSL https://openrouter.ai/labs/spawn/hetzner/t3code.sh)
|
||||||
|
```
|
||||||
|
|
||||||
## Non-Interactive Mode
|
## Non-Interactive Mode
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
|
||||||
26
sh/hetzner/t3code.sh
Normal file
26
sh/hetzner/t3code.sh
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -eo pipefail
|
||||||
|
|
||||||
|
# Thin shim: ensures bun is available, runs bundled hetzner.js (local or from GitHub release)
|
||||||
|
|
||||||
|
_ensure_bun() {
|
||||||
|
if command -v bun &>/dev/null; then return 0; fi
|
||||||
|
printf '\033[0;36mInstalling bun...\033[0m\n' >&2
|
||||||
|
curl -fsSL --proto '=https' --show-error https://bun.sh/install?version=1.3.9 | bash >/dev/null || { printf '\033[0;31mFailed to install bun\033[0m\n' >&2; exit 1; }
|
||||||
|
export PATH="$HOME/.bun/bin:$PATH"
|
||||||
|
command -v bun &>/dev/null || { printf '\033[0;31mbun not found after install\033[0m\n' >&2; exit 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
_ensure_bun
|
||||||
|
|
||||||
|
# SPAWN_CLI_DIR override — force local source (used by e2e tests)
|
||||||
|
if [[ -n "${SPAWN_CLI_DIR:-}" && -f "$SPAWN_CLI_DIR/packages/cli/src/hetzner/main.ts" ]]; then
|
||||||
|
exec bun run "$SPAWN_CLI_DIR/packages/cli/src/hetzner/main.ts" t3code "$@"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Remote — download and run compiled TypeScript bundle
|
||||||
|
HETZNER_JS=$(mktemp)
|
||||||
|
trap 'rm -f "$HETZNER_JS"' EXIT
|
||||||
|
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/hetzner-latest/hetzner.js" -o "$HETZNER_JS" \
|
||||||
|
|| { printf '\033[0;31mFailed to download hetzner.js\033[0m\n' >&2; exit 1; }
|
||||||
|
exec bun run "$HETZNER_JS" t3code "$@"
|
||||||
|
|
@ -18,6 +18,7 @@ spawn hermes local
|
||||||
spawn junie local
|
spawn junie local
|
||||||
spawn cursor local
|
spawn cursor local
|
||||||
spawn pi local
|
spawn pi local
|
||||||
|
spawn t3code local
|
||||||
```
|
```
|
||||||
|
|
||||||
Or run directly without the CLI:
|
Or run directly without the CLI:
|
||||||
|
|
@ -32,6 +33,7 @@ bash <(curl -fsSL https://openrouter.ai/labs/spawn/local/hermes.sh)
|
||||||
bash <(curl -fsSL https://openrouter.ai/labs/spawn/local/junie.sh)
|
bash <(curl -fsSL https://openrouter.ai/labs/spawn/local/junie.sh)
|
||||||
bash <(curl -fsSL https://openrouter.ai/labs/spawn/local/cursor.sh)
|
bash <(curl -fsSL https://openrouter.ai/labs/spawn/local/cursor.sh)
|
||||||
bash <(curl -fsSL https://openrouter.ai/labs/spawn/local/pi.sh)
|
bash <(curl -fsSL https://openrouter.ai/labs/spawn/local/pi.sh)
|
||||||
|
bash <(curl -fsSL https://openrouter.ai/labs/spawn/local/t3code.sh)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Non-Interactive Mode
|
## Non-Interactive Mode
|
||||||
|
|
|
||||||
27
sh/local/t3code.sh
Normal file
27
sh/local/t3code.sh
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -eo pipefail
|
||||||
|
|
||||||
|
# Thin shim: ensures bun is available, runs bundled local.js (local or from GitHub release)
|
||||||
|
|
||||||
|
_ensure_bun() {
|
||||||
|
if command -v bun &>/dev/null; then return 0; fi
|
||||||
|
printf '\033[0;36mInstalling bun...\033[0m\n' >&2
|
||||||
|
curl -fsSL --proto '=https' --show-error https://bun.sh/install?version=1.3.9 | bash >/dev/null || { printf '\033[0;31mFailed to install bun\033[0m\n' >&2; exit 1; }
|
||||||
|
export PATH="$HOME/.bun/bin:$PATH"
|
||||||
|
command -v bun &>/dev/null || { printf '\033[0;31mbun not found after install\033[0m\n' >&2; exit 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
_ensure_bun
|
||||||
|
|
||||||
|
# SPAWN_CLI_DIR override — force local source (used by e2e tests)
|
||||||
|
if [[ -n "${SPAWN_CLI_DIR:-}" && -f "$SPAWN_CLI_DIR/packages/cli/src/local/main.ts" ]]; then
|
||||||
|
exec bun run "$SPAWN_CLI_DIR/packages/cli/src/local/main.ts" t3code "$@"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Remote — download bundled local.js from GitHub release
|
||||||
|
LOCAL_JS=$(mktemp)
|
||||||
|
trap 'rm -f "$LOCAL_JS"' EXIT
|
||||||
|
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/local-latest/local.js" -o "$LOCAL_JS" \
|
||||||
|
|| { printf '\033[0;31mFailed to download local.js\033[0m\n' >&2; exit 1; }
|
||||||
|
|
||||||
|
exec bun run "$LOCAL_JS" t3code "$@"
|
||||||
|
|
@ -58,6 +58,12 @@ bash <(curl -fsSL https://openrouter.ai/labs/spawn/sprite/cursor.sh)
|
||||||
bash <(curl -fsSL https://openrouter.ai/labs/spawn/sprite/pi.sh)
|
bash <(curl -fsSL https://openrouter.ai/labs/spawn/sprite/pi.sh)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### T3 Code
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash <(curl -fsSL https://openrouter.ai/labs/spawn/sprite/t3code.sh)
|
||||||
|
```
|
||||||
|
|
||||||
## Non-Interactive Mode
|
## Non-Interactive Mode
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
|
||||||
26
sh/sprite/t3code.sh
Normal file
26
sh/sprite/t3code.sh
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -eo pipefail
|
||||||
|
|
||||||
|
# Thin shim: ensures bun is available, runs bundled sprite.js (local or from GitHub release)
|
||||||
|
|
||||||
|
_ensure_bun() {
|
||||||
|
if command -v bun &>/dev/null; then return 0; fi
|
||||||
|
printf '\033[0;36mInstalling bun...\033[0m\n' >&2
|
||||||
|
curl -fsSL --proto '=https' --show-error https://bun.sh/install?version=1.3.9 | bash >/dev/null || { printf '\033[0;31mFailed to install bun\033[0m\n' >&2; exit 1; }
|
||||||
|
export PATH="$HOME/.bun/bin:$PATH"
|
||||||
|
command -v bun &>/dev/null || { printf '\033[0;31mbun not found after install\033[0m\n' >&2; exit 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
_ensure_bun
|
||||||
|
|
||||||
|
# SPAWN_CLI_DIR override — force local source (used by e2e tests)
|
||||||
|
if [[ -n "${SPAWN_CLI_DIR:-}" && -f "$SPAWN_CLI_DIR/packages/cli/src/sprite/main.ts" ]]; then
|
||||||
|
exec bun run "$SPAWN_CLI_DIR/packages/cli/src/sprite/main.ts" t3code "$@"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Remote — download and run compiled TypeScript bundle
|
||||||
|
SPRITE_JS=$(mktemp)
|
||||||
|
trap 'rm -f "$SPRITE_JS"' EXIT
|
||||||
|
curl -fsSL --proto '=https' "https://github.com/OpenRouterTeam/spawn/releases/download/sprite-latest/sprite.js" -o "$SPRITE_JS" \
|
||||||
|
|| { printf '\033[0;31mFailed to download sprite.js\033[0m\n' >&2; exit 1; }
|
||||||
|
exec bun run "$SPRITE_JS" t3code "$@"
|
||||||
Loading…
Add table
Add a link
Reference in a new issue