A ground-up, interop-first alternative to opencode: a Go daemon that is wire-compatible with opencode's HTTP+SSE+WebSocket API.
opencode is amazing. This is a personal exercise in reimplementing it from scratch in Go — to see how far the rewrite gets, and as a bonus ship the mobile client that opencode is missing.
Wire compatibility is kept deliberately until interop becomes a wall worth breaking.
Daemon
- 131 ops / 113 paths — HTTP/REST, SSE event bus, WebSocket PTY (opencode contract)
- Basic auth +
?auth_token=, per-directory instance routing (x-opencode-directory) - SQLite store (sessions / messages / parts), single static CGO-free binary
- Agent engine: LLM stream + tool loop, 14 built-in tools, permissions & questions
- Providers: Anthropic, OpenAI
Ecosystem (opencode-format, unmodified)
- MCP clients — stdio + StreamableHTTP/SSE + OAuth
- LSP servers (go.lsp.dev / jsonrpc2)
- Agents, commands, rules, skills, providers, plugins loaders
- Plugin host — Node/Bun sidecar running opencode-format TS plugins
Mobile (Android, primary client)
- mDNS LAN discovery · streaming chat (markdown + syntax highlight + word-level diff)
- Embedded PTY terminal over WebSocket · FCM push notifications
- Adaptive triptych: phone → foldable → tablet
SDKs — generated from the OpenAPI contract: Go · Kotlin · Swift
TUI — Go Bubble Tea v2, pure HTTP+SSE client (dogfood + visual-diff vs opencode TUI)
Conformance — self-diff gate vs real opencode; required-green on every API change
| opencode | Opcode42 | |
|---|---|---|
| Wire protocol (REST/SSE/WS) | reference | matches |
| Config & resource formats | reference | compatible |
| Web/desktop client | original | runs unmodified |
| Mobile client | — | Android (primary) |
| TUI | original (TS) | Go (Bubble Tea v2) |
Chat with reasoning blocks, compact tool-call rows, one-line composer.
Two-pane at medium width - chat with inline git diff and session info panel.
Expanded triptych — sessions rail · chat with streaming tool rows · session info panel.
More: android/README.md · build & install android/BUILD.md · engineering plan plans/07-client-mobile.md · UX overhaul plans/15-android-ux-overhaul.md
┌─────────────────────────────────────────────┐
Mobile ─────┤ Opcode42 Daemon (Go, static binary) │── SQLite (sessions/msgs/parts)
(primary) ────┤ HTTP/REST + SSE bus + WS PTY │── repo + built-in tools
TUI (Go) ────┤ Auth + per-directory instance routing │── MCP clients (stdio/http/sse)
opencode's │ Agent engine (LLM stream + tool loop) │── LSP servers (jsonrpc)
web/desktop │ Ecosystem loaders │
(unmodified) │ Plugin host sidecar (Node/Bun) ◄──────────┼── opencode-format TS plugins
└─────────────────────────────────────────────┘
all clients speak the SAME opencode wire protocol
Prerequisites: Go 1.22+
git clone https://github.com/rotemmiz/opcode42
cd opcode42
make build # outputs bin/opcoded
./bin/opcoded # flags: --host, --port, --mdns, --version, ...The daemon listens on localhost:4096 by default. Clients authenticate via HTTP Basic or ?auth_token=base64(user:pass) and route to per-directory instances using the x-opencode-directory header.
By default the daemon binds loopback only. Binding a non-loopback interface (--host 0.0.0.0, or --mdns which implies it) requires a password — set OPENCODE_SERVER_PASSWORD or the daemon refuses to start.
Releases ship a single static, CGO-free binary per platform plus multi-arch container images, built with goreleaser (.goreleaser.yaml). Tagging vX.Y.Z runs the release workflow; PR CI validates the same config via a snapshot dry-run.
# Container (binds 0.0.0.0, so a password is required):
docker run -d -p 4096:4096 -e OPENCODE_SERVER_PASSWORD=secret \
ghcr.io/rotemmiz/opcode42:latest --host 0.0.0.0 --port 4096Service unit templates live under packaging/: a hardened systemd unit (packaging/systemd/opcode42.service) and a macOS launchd agent (packaging/launchd/dev.opcode42.daemon.plist). For remote access, prefer Tailscale, an SSH tunnel, or a TLS-terminating reverse proxy (SSE needs unbuffered proxying) over an open port — see plans/13-remote-ops.md.
make test # unit tests
make conformance # conformance suite against TARGET= (default: localhost:4096)
make selfdiff # opencode-vs-opencode self-diff gateOr directly:
go test ./...
scripts/run-conformance.sh self| Works | In progress |
|---|---|
| Daemon transport, auth, instance routing | Plugin host hardening |
| Agent engine + 14 built-in tools | Perf head-to-head vs opencode |
| MCP (stdio/HTTP/SSE) + LSP | Additional providers |
| Android client (6 feature modules) | TUI visual-parity finish |
| Conformance self-diff gate |
Passing make selfdiff clean is required before merging any change that touches an API endpoint.
MIT — see LICENSE.
plans/00-masterplan.md— vision, frozen wire contract, build sequenceCONTRIBUTING.md— git workflow, local CI gate, code styleDEPENDENCIES.md— vetted library choices and rationaleCLAUDE.md— instructions for agents


