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
5 changes: 5 additions & 0 deletions .changeset/warm-toon-acp.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"opencode": minor
---

Add typed JSON/TOON RPC session reads, opt-in TOON-RPC ACP framing, and a native framed RPC sidecar in every Redcode platform package.
103 changes: 103 additions & 0 deletions .github/workflows/red-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,104 @@ concurrency:
cancel-in-progress: false

jobs:
sidecar:
if: github.repository == 'reddb-io/redcode'
name: sidecar (${{ matrix.name }})
strategy:
fail-fast: false
matrix:
include:
- name: linux-x64
host: ubuntu-latest
target: x86_64-linux-gnu.2.29
file: redcode-rpc-sidecar-linux-x64
identity: "ELF 64-bit LSB executable, x86-64"
linkage: dynamically linked
- name: linux-arm64
host: ubuntu-latest
target: aarch64-linux-gnu.2.29
file: redcode-rpc-sidecar-linux-arm64
identity: "ELF 64-bit LSB executable, ARM aarch64"
linkage: dynamically linked
- name: linux-x64-musl
host: ubuntu-latest
target: x86_64-linux-musl
file: redcode-rpc-sidecar-linux-x64-musl
identity: "ELF 64-bit LSB executable, x86-64"
linkage: statically linked
- name: linux-arm64-musl
host: ubuntu-latest
target: aarch64-linux-musl
file: redcode-rpc-sidecar-linux-arm64-musl
identity: "ELF 64-bit LSB executable, ARM aarch64"
linkage: statically linked
- name: windows-x64
host: ubuntu-latest
target: x86_64-windows-gnu
file: redcode-rpc-sidecar-windows-x64.exe
identity: "PE32+ executable (console) x86-64"
linkage: ""
- name: windows-arm64
host: ubuntu-latest
target: aarch64-windows-gnu
file: redcode-rpc-sidecar-windows-arm64.exe
identity: "PE32+ executable (console) Aarch64"
linkage: ""
- name: darwin-x64
host: macos-15-intel
target: ""
deployment: "11.0"
developer: /Applications/Xcode_16.4.app/Contents/Developer
file: redcode-rpc-sidecar-darwin-x64
identity: "Mach-O 64-bit executable x86_64"
linkage: ""
- name: darwin-arm64
host: macos-15
target: ""
deployment: "11.0"
developer: /Applications/Xcode_16.4.app/Contents/Developer
file: redcode-rpc-sidecar-darwin-arm64
identity: "Mach-O 64-bit executable arm64"
linkage: ""
runs-on: ${{ matrix.host }}
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
- uses: ./.github/actions/setup-bun
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020
with:
node-version: 24.11.1
- name: Install pinned Zig toolchain
if: runner.os == 'Linux'
run: |
set -euo pipefail
curl --fail --location --output /tmp/zig.tar.xz https://ziglang.org/builds/zig-x86_64-linux-0.17.0-dev.1857+3c46da14d.tar.xz
echo "0825e4a55baf4a6647c3ce3077a7236c9ffec5b17e1ca0102a930fe33d631bc6 /tmp/zig.tar.xz" | sha256sum --check -
tar -xf /tmp/zig.tar.xz -C /tmp
echo "/tmp/zig-x86_64-linux-0.17.0-dev.1857+3c46da14d" >> "$GITHUB_PATH"
- name: Build RPC sidecar
working-directory: packages/rpc-sidecar
env:
DEVELOPER_DIR: ${{ matrix.developer }}
MACOSX_DEPLOYMENT_TARGET: ${{ matrix.deployment }}
REDCODE_RPC_SIDECAR_OUTPUT: dist/release/${{ matrix.file }}
REDCODE_RPC_SIDECAR_TARGET: ${{ matrix.target }}
run: bun run build
- name: Verify RPC sidecar target
run: |
set -euo pipefail
metadata="$(file "packages/rpc-sidecar/dist/release/${{ matrix.file }}")"
grep -F "${{ matrix.identity }}" <<<"$metadata"
if [ -n "${{ matrix.linkage }}" ]; then grep -F "${{ matrix.linkage }}" <<<"$metadata"; fi
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
with:
name: rpc-sidecar-${{ matrix.name }}
path: packages/rpc-sidecar/dist/release/${{ matrix.file }}
if-no-files-found: error
retention-days: 1

publish:
if: github.repository == 'reddb-io/redcode'
needs: sidecar
runs-on: ubuntu-latest
environment:
name: red-release
Expand Down Expand Up @@ -71,11 +167,17 @@ jobs:
exit 1
fi
echo "resuming existing draft $TAG"
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093
with:
pattern: rpc-sidecar-*
path: packages/rpc-sidecar/dist/release
merge-multiple: true
- name: Build and upload native binaries
env:
GH_REPO: reddb-io/redcode
GH_TOKEN: ${{ github.token }}
OPENCODE_RELEASE: "1"
REDCODE_RPC_SIDECAR_DIR: ${{ github.workspace }}/packages/rpc-sidecar/dist/release
VERSION: ${{ steps.release.outputs.version }}
run: OPENCODE_VERSION="$VERSION" ./packages/opencode/script/build.ts
- name: Normalize native npm metadata
Expand Down Expand Up @@ -118,6 +220,7 @@ jobs:
for attempt in 1 2 3 4 5 6 7 8 9 10; do
if npm install --prefix "$root" --no-audit --no-fund "@reddb-io/redcode@${VERSION}"; then
"$root/node_modules/.bin/redcode" --version | grep -Fx "$VERSION"
REDCODE_RPC_URL=http://127.0.0.1:1/rpc "$root/node_modules/.bin/redcode-rpc-sidecar" </dev/null
exit 0
fi
if [ "$attempt" -eq 10 ]; then
Expand Down
11 changes: 10 additions & 1 deletion .github/workflows/red-workspace-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,22 @@ jobs:
- uses: ./.github/actions/setup-bun
- name: Check binary-only workflow posture
run: bun script/test-redcode-release-contract.ts
- name: Build the current RPC sidecar
working-directory: packages/rpc-sidecar
env:
REDCODE_RPC_SIDECAR_OUTPUT: dist/release/redcode-rpc-sidecar-linux-x64
run: bun run build
- name: Build the current native binary
env:
REDCODE_RPC_SIDECAR_DIR: ${{ github.workspace }}/packages/rpc-sidecar/dist/release
run: OPENCODE_VERSION="$(node -p "require('./package.json').version")" OPENCODE_CHANNEL=latest OPENCODE_RELEASE=1 ./packages/opencode/script/build.ts --single --skip-install --skip-embed-web-ui --skip-upload
- name: Verify the native package contains the RPC sidecar
run: test -x packages/opencode/dist/redcode-linux-x64/bin/redcode-rpc-sidecar
- name: Pack the npm distribution without publishing
run: OPENCODE_VERSION="$(node -p "require('./package.json').version")" OPENCODE_CHANNEL=latest ./packages/opencode/script/publish.ts --pack-only
- name: Inspect packed package identity
run: |
tarball="$(find packages/opencode/dist/redcode-package -maxdepth 1 -name 'reddb-io-redcode-*.tgz' -print -quit)"
test -n "$tarball"
tar -xOf "$tarball" package/package.json |
node -e 'let text=""; process.stdin.on("data", (chunk) => text += chunk); process.stdin.on("end", () => { const pkg = JSON.parse(text); const expected = require("./package.json").version; if (pkg.name !== "@reddb-io/redcode" || pkg.version !== expected || pkg.bin.redcode === undefined) process.exit(1) })'
node -e 'let text=""; process.stdin.on("data", (chunk) => text += chunk); process.stdin.on("end", () => { const pkg = JSON.parse(text); const expected = require("./package.json").version; if (pkg.name !== "@reddb-io/redcode" || pkg.version !== expected || pkg.bin.redcode === undefined || pkg.bin["redcode-rpc-sidecar"] === undefined) process.exit(1) })'
5 changes: 5 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ jobs:
working-directory: packages/client
run: bun run check:generated

- name: Build native RPC sidecar
if: runner.os == 'Linux'
working-directory: packages/rpc-sidecar
run: bun run test:native

- name: Run HttpApi exerciser gates
if: runner.os == 'Linux'
working-directory: packages/opencode
Expand Down
20 changes: 16 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ larger surface than Redcode targets. Telling the two apart is the fastest way to

| Piece | What it is | Where |
| --- | --- | --- |
| `@reddb-io/redcode` | One native CLI binary, `redcode`. The whole product. | [Install](#install) |
| `@reddb-io/redcode` | The native `redcode` CLI and its `redcode-rpc-sidecar` companion. | [Install](#install) |
| The TUI | Sessions, diffs, permissions, and the Worker fleet | [Use](#use) |
| The server, ACP agent, MCP client | The same binary, other entry points | [Use](#use) |

Expand Down Expand Up @@ -168,9 +168,10 @@ npm install -g @reddb-io/redcode
redcode
```

Bun, pnpm, and Yarn work too. The install resolves one native binary for your platform — Linux
Bun, pnpm, and Yarn work too. The install resolves one native package for your platform — Linux
(glibc and musl, x64 and arm64), macOS (x64 and arm64), and Windows (x64 and arm64), with non-AVX2
variants where the architecture needs them.
variants where the architecture needs them. Each package contains `redcode` and the matching
`redcode-rpc-sidecar` companion.

There is no beta channel, no container image, no desktop build, no package-manager tap, and no
hosted deployment. See [What Ships And What Doesn't](#what-ships-and-what-doesnt) for why that is
Expand All @@ -185,7 +186,7 @@ Running `redcode` with no arguments opens the TUI directly in a new session.
| `redcode` | Terminal UI — sessions, diffs, permissions, and the Workers fleet |
| `redcode run` | Non-interactive prompt; `--format json` emits structured records |
| `redcode serve` | Headless HTTP server exposing the Protocol API |
| `redcode acp` | Agent Client Protocol over stdio, for editors that speak ACP |
| `redcode acp` | Agent Client Protocol over stdio; `--experimental-toon` selects TOON-RPC framing |
| `redcode mcp` | Manage the MCP servers Redcode connects to — it is an MCP client, not a server |
| `redcode attach` | Attach to a running server |
| `redcode web` | Start the server and open the local web interface |
Expand All @@ -198,6 +199,16 @@ Running `redcode` with no arguments opens the TUI directly in a new session.

`redcode --help` lists everything, including `upgrade`, `uninstall`, `generate`, and `console`.

`redcode serve` prints both its base URL and the exact `POST /rpc` endpoint. That endpoint accepts
JSON-RPC 2.0 (`application/json`) and TOON-RPC 1.0 (`application/toon`) for the same typed read-only
methods: `health.get`, `session.list`, and `session.active`. `session.list` accepts the same filters,
ordering, limit, and cursor semantics as `GET /api/session`.

The sibling `redcode-rpc-sidecar` bridges bounded `Content-Length` frames on stdin/stdout to that
HTTP endpoint. Set `REDCODE_RPC_URL` to the printed URL. It reuses
`OPENCODE_SERVER_USERNAME`/`OPENCODE_SERVER_PASSWORD`, or accepts a complete
`REDCODE_AUTHORIZATION` header.

## Architecture

```
Expand All @@ -224,6 +235,7 @@ does not import the CLI that hosts it.
| `packages/client` | Generated clients — zero-Effect root, `/effect` variant |
| `packages/tui` | Terminal UI (OpenTUI + Solid) |
| `packages/opencode` | The CLI that becomes the `redcode` binary |
| `packages/rpc-sidecar` | Static native companion that bridges framed JSON/TOON RPC to `/rpc` |
| `packages/plugin` | Public plugin API |
| `packages/sdk/js` | The SDK the TUI, CLI, and ACP agent all talk through |

Expand Down
Loading
Loading