Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

344 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Opcode42

Opcode42

CI Conformance License: MIT

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.

Features

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

Compatibility

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)

Screenshots

Phone

Opcode42 on phone — chat

Chat with reasoning blocks, compact tool-call rows, one-line composer.

Foldable

Opcode42 on foldable — in-chat git diff

Two-pane at medium width - chat with inline git diff and session info panel.

Tablet

Opcode42 on tablet — triptych layout

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

Architecture

                ┌─────────────────────────────────────────────┐
   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

Quick Start

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.

Deployment & Packaging

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 4096

Service 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.

Testing

make test                 # unit tests
make conformance          # conformance suite against TARGET= (default: localhost:4096)
make selfdiff             # opencode-vs-opencode self-diff gate

Or directly:

go test ./...
scripts/run-conformance.sh self

Project Status

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.

License

MIT — see LICENSE.

Further Reading

About

A ground-up, interop-first alternative to opencode - with Android and TUI clients

Topics

Resources

Contributing

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages