Skip to content

Latest commit

 

History

348 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

opencoder

The desktop & mobile client for OpenCode — one codebase, five platforms (macOS / Windows / Linux / iOS / Android), built with Tauri 2 and SolidJS. v1.0.0 ships the three desktop platforms; iOS and Android are in development (see docs/mobile-signing.md).

Build status License Version 简体中文

Features

  • Multi-server management — connect to any number of opencode serve instances from one app: live health checks (with version/latency readouts), automatic reconnection with state realignment, mDNS auto-discovery on your LAN, and a server home page with a QR code to share any server with your phone
  • Dual-form UI — a desktop shell (mouse + shortcuts + custom title bar + tray) and a mobile shell (touch-first, system back, haptics, share-receive), sharing one component library
  • Full API coverage — the entire 162-endpoint OpenAPI contract implemented stage by stage (see docs/api-coverage.md)
  • Streaming-first chat — text, tool calls, reasoning and todos stream in live; interrupt, permission requests, questions, slash commands, fork / revert / share, session diff and AGENTS.md generation included
  • Files, search, diff & VCS — file tree with lazy loading, ⌘P quick open, full-text search with hit jumps, unified/split session diffs and a git-aware status bar
  • Built-in terminal — xterm.js over a Rust PTY channel, on desktop and mobile
  • Liquid Glass (iOS 26) — native translucent tab bar + materials on Apple's new design language (see docs/ui-design.md)
  • Mascot pet — a desktop companion in its own always-on-top window that reacts to coding events (working, waiting for permission, success, error…)
  • i18n first — English and Simplified Chinese from day one, switchable at runtime
  • Themes & accents — dark / light / system (+ OLED true-black on mobile) with six accent presets or a custom color, per-server overrides
  • Private by design — the WebView never talks to your servers directly: all REST/SSE/WebSocket traffic flows through the Rust transport layer (ADR-002), immune to CORS and iOS ATS restrictions

Screenshots

Desktop — servers home Desktop — chat Desktop — files Desktop — chat (dark)
Desktop servers home Desktop chat Desktop files Desktop chat dark

Desktop screenshots show the app UI driven by the Mock OpenCode Server in dev mode.

Requirements

opencoder is a pure client: it talks to one or more OpenCode servers.

  • Server: the opencode CLI, v1.18.11 or later — the API contract is version-locked at docs/openapi_v1.18.11.json (OpenAPI 3.1)

  • Start a server:

    opencode serve --port 4096         # listen on TCP port 4096
    opencode serve --port 4096 --mdns  # also broadcast on the LAN for one-click mDNS discovery
  • Password auth (optional): set the OPENCODE_SERVER_PASSWORD environment variable before starting the server; the app prompts for the password when connecting and sends it as HTTP Basic Auth

  • LAN / remote servers: any reachable opencode serve instance works — add it by URL, or scan its QR code with your phone

Install

Platform Channel
macOS Universal .dmg (arm64 + x86_64) from GitHub Releases; signed + notarized when Apple credentials are configured
Windows NSIS .exe and MSI .msi installers
Linux .deb and AppImage packages
iOS In development — TestFlight / App Store pending (device builds need an Apple team; unsigned simulator builds are used for development)
Android In development — APK/AAB from CI builds; release signing (keystore) is pending

Desktop apps ship with built-in auto-update. Signing and mobile release details are in docs/mobile-signing.md and docs/release-signing.md.

Quick Start

  1. Install the app for your platform (see above) and start a server (opencode serve --port 4096).
  2. Add the server — Servers home → Add server → name + URL → Test connection → Save. On the same LAN, pick the server from the mDNS-discovered list; on mobile, scan the QR code.
  3. Create a session and send a message — hit ⌘Enter (or Ctrl+Enter). Text, tool calls, reasoning and todos stream in live.

Keyboard Shortcuts

The primary modifier is on macOS and Ctrl elsewhere (both are accepted on every platform). Every shortcut is remappable in Settings → Shortcuts.

Shortcut Action
⌘K Command palette
⌘N New session
⌘P Quick open file
⌘⇧F Full-text search
⌘1⌘9 Switch server
⌘[ / ⌘] Previous / next session
⌘Enter Send message (in chat input)
Esc Interrupt generation / close overlay
⌘B Toggle sidebar
⌘J Toggle terminal
⌘D Session diff
⌘, Open settings
Tab Cycle agent in input (in chat input)
Recall last prompt (empty input)

Architecture

┌───────────────────────────────────────────────────────────┐
│                  SolidJS Frontend (one codebase)          │
│  Desktop Shell · Mobile Shell · Shared Features           │
│  Stores (per server) ← Services (API abstraction)         │
│               ApiClient / SSE facade (TS)                 │
└───────────────────────────┬───────────────────────────────┘
                    Tauri IPC (invoke / Channel)
┌───────────────────────────▼───────────────────────────────┐
│                     Rust Core (src-tauri)                 │
│   transport: http (REST) · sse · ws (PTY)                 │
│   connections · health monitor · mDNS discovery           │
│   pet window · glass plugin (iOS/macOS)                   │
└───────────────────────────┬───────────────────────────────┘
                 HTTP / SSE / WebSocket (reqwest)
      opencode serve (local)    (LAN / mDNS)    (remote)

All network traffic to OpenCode servers flows through the Rust transport layer (ADR-002): the WebView never makes a cross-origin request, which sidesteps CORS and iOS ATS, and SSE/WebSocket connections stay alive independently of the WebView lifecycle. SSE deltas are batched (16 ms frames) and filtered Rust-side; the health monitor polls /global/health and drives the reconnection state machine. See docs/architecture.md for details.

Tech Stack

Layer Choice
App framework Tauri 2.x (Rust)
Frontend SolidJS + TypeScript
Build Vite 6 + @solidjs/router
Styling Tailwind CSS v4 + CSS variable design tokens
Components Kobalte (accessible headless components)
API types openapi-typescript generated from the OpenAPI 3.1 spec
Transport Rust reqwest (REST + SSE + WebSocket), WebView never connects directly
Terminal xterm.js over a Rust WebSocket/PTY channel
State Solid stores, sliced per server
i18n i18next + solid-i18next (English + 简体中文)
Mascot Always-on-top transparent window (desktop); Rive-ready renderer interface
Quality ESLint + Prettier + clippy/fmt + husky/lint-staged + axe-core a11y sweeps

Development

Prerequisites: Node.js >= 20, pnpm, and a Rust toolchain (for desktop builds).

pnpm install        # install dependencies
pnpm tauri dev      # run the desktop app in dev mode (Rust transport)

Useful scripts:

Command Purpose
pnpm verify Quality gate: lint + format + typecheck + links + tests + codegen drift (must pass before commit)
pnpm test Unit tests (vitest)
pnpm test:coverage Unit tests with the coverage gate (src/services/**, src/stores/**)
pnpm test:e2e Playwright end-to-end journeys (12) against the mock server
pnpm check:links Markdown link check over the user-facing docs
pnpm check:i18n i18n key completeness + en/zh key-set equality
pnpm mock:start Start the Mock OpenCode Server (Node, REST + SSE + scenarios)
pnpm mock:test Mock server self-test
pnpm gen:api Regenerate API types from the OpenAPI contract
pnpm gen:api:check Drift-check committed types against the contract (used in CI)
pnpm fixtures:record Record fixtures from a real opencode serve (needs a base URL)

Browser-only development uses a dev transport: VITE_TRANSPORT=fetch pnpm dev talks to the mock server directly, with the Tauri bridge shimmed in for E2E (see docs/testing.md §3 L4).

Mobile builds:

  • iOS: pnpm tauri ios build --target aarch64-sim --ci --no-sign builds an unsigned simulator app; device builds and TestFlight/App Store steps are in docs/mobile-signing.md
  • Android: requires the Android SDK/JDK locally (tauri android init scaffolds gen/android, generated by CI otherwise); debug builds are auto-signed, release builds need a keystore — see docs/mobile-signing.md

API Contract & Type Generation

  • Source of truth: docs/openapi_v1.18.11.json (OpenAPI 3.1, version-locked)
  • Generated types: src/services/api/schema.d.ts (via openapi-typescript, script scripts/gen-api.mjs)

Contract upgrade flow: replace the versioned spec file → pnpm gen:apipnpm gen:api:checkpnpm exec tsc -b → commit both files.

Documentation

Doc Contents
docs/PLAN.md Overall plan, milestones, decision points
docs/architecture.md Technical architecture, directory layout, data flows
docs/api-coverage.md 162 endpoints → feature domain → priority/milestone mapping
docs/ui-design.md Design system, desktop/mobile shells, Liquid Glass, mascot
docs/testing.md Layered test strategy, Mock Server, CI
docs/glossary.md Terminology contract (en/zh)
docs/a11y-report.md Accessibility sweep report (axe-core, WCAG 2.x AA)
docs/performance.md Performance budgets and measurements
docs/mobile-signing.md iOS/Android signing, TestFlight, App Store checklist
docs/release-signing.md Desktop three-platform signing and notarization
docs/AGENT_PLAYBOOK.md Agent execution manual (task card format, commit rules)
docs/tasks/M0.md … M10.md Executable task cards (83 total)

Contributing

See CONTRIBUTING.md for development setup, branch and commit conventions, and testing discipline.

Changelog

See CHANGELOG.md for release history.

License

MIT

About

vide coding in a single hand, app client for opencode

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages