Skip to content

Commit 004a773

Browse files
committed
ci: stabilize bridge e2e
Use prebuilt bridge binaries in the e2e path so CI does not wait on cold go run startup, and restore the README as a fuller usage guide.
1 parent c98c460 commit 004a773

3 files changed

Lines changed: 70 additions & 9 deletions

File tree

.github/workflows/ci.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,5 +45,9 @@ jobs:
4545
env:
4646
BUILD_TARGETS: windows_amd64
4747

48+
- name: Test bridge
49+
working-directory: bridge
50+
run: go test ./...
51+
4852
- name: Run tests
4953
run: bun test

README.md

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,51 @@
11
# CYA
22

3-
AI agent shell relay. **Dev:** `bun install && bun dev` (needs **Go ≥ 1.22** so the bridge binaries can compile into `public/bin/`).
3+
Connect Your Agent. Give an AI agent temporary, user-approved command access to a machine.
44

5-
**Docker:** `docker build -t cya . && docker run --rm -p 8765:8765 -e BASE_URL=http://localhost:8765 cya`
5+
CYA starts an in-memory session, shows a one-line install command for the target machine, and gives you a prompt URL to paste into Claude Code, Codex, OpenClaw, or another agent. The bridge connects back over WebSocket and executes one command at a time through the HTTP API.
6+
7+
## Quick Start
8+
9+
```sh
10+
bun install
11+
bun dev
12+
```
13+
14+
Open `http://localhost:8765`, create a session, run the displayed command on the target machine, then paste the generated prompt into your agent.
15+
16+
The bridge binaries are built with Go, so local development needs **Go 1.22+**.
17+
18+
## Docker
19+
20+
```sh
21+
docker build -t cya .
22+
docker run --rm -p 8765:8765 -e BASE_URL=http://localhost:8765 cya
23+
```
24+
25+
## Supported Targets
26+
27+
- macOS Intel / Apple Silicon
28+
- Linux x64 / arm64
29+
- OpenWrt-style Linux MIPS / MIPS64, big-endian and little-endian
30+
- Windows x64
31+
32+
## How It Works
33+
34+
1. Browser creates a short-lived session code.
35+
2. Target machine runs the install command for its OS.
36+
3. The Go bridge connects to `/ws` and joins the session.
37+
4. Agents call `/api/session/:code/run` with `cmd`, `cmd_b64`, and optional `timeout`.
38+
5. The response includes merged stdout/stderr, `exit_code`, and `truncated`.
39+
40+
Sessions are in-memory only. Nothing is persisted by the server.
41+
42+
## Development
43+
44+
```sh
45+
bun run typecheck
46+
bun test
47+
(cd bridge && go test ./...)
48+
bun run build
49+
```
50+
51+
`bun run build` compiles bridge binaries into `public/bin/`.

server/app.test.ts

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -269,11 +269,8 @@ const wsUrl = `ws://127.0.0.1:${port}/ws`;
269269
let server: Bun.Subprocess | null = null;
270270
let bridge: Bun.Subprocess | null = null;
271271

272-
const bridgeModuleDir = join(
273-
dirname(fileURLToPath(import.meta.url)),
274-
"..",
275-
"bridge",
276-
);
272+
const repoRoot = join(dirname(fileURLToPath(import.meta.url)), "..");
273+
const bridgeModuleDir = join(repoRoot, "bridge");
277274

278275
beforeAll(async () => {
279276
server = Bun.spawn(["bun", "run", "server/index.ts"], {
@@ -298,8 +295,9 @@ describe("full local server and bridge flow", () => {
298295
const session = await postJson(`${baseUrl}/api/session`, {}) as { code: string };
299296
expect(session.code).toMatch(/^[0-9a-f]{12}$/);
300297

301-
bridge = Bun.spawn(["go", "run", ".", session.code], {
302-
cwd: bridgeModuleDir,
298+
const bridgeCommand = await bridgeSpawnCommand(session.code);
299+
bridge = Bun.spawn(bridgeCommand.argv, {
300+
cwd: bridgeCommand.cwd,
303301
stdout: "inherit",
304302
stderr: "inherit",
305303
env: { ...process.env, BRIDGE_WS_URL: wsUrl },
@@ -396,3 +394,16 @@ function sleepCommand(seconds: number): string {
396394
}
397395
return `sleep ${seconds}`;
398396
}
397+
398+
async function bridgeSpawnCommand(code: string): Promise<{
399+
argv: string[];
400+
cwd: string;
401+
}> {
402+
const os = process.platform === "win32" ? "windows" : process.platform;
403+
const exe = os === "windows" ? ".exe" : "";
404+
const binary = join(repoRoot, "public", "bin", `cya-bridge-${os}-${process.arch}${exe}`);
405+
if (await Bun.file(binary).exists()) {
406+
return { argv: [binary, code], cwd: repoRoot };
407+
}
408+
return { argv: ["go", "run", ".", code], cwd: bridgeModuleDir };
409+
}

0 commit comments

Comments
 (0)