Deep Research Report · 27 October 2026

OpenCode vs OpenChamber — which web UI can you actually make yours?

Both are MIT-licensed TypeScript monorepos with a browser interface. They are built with completely different frameworks, at completely different scales, and that decides how much work your own branding, layout and features will cost you.

OpenCode 2.2.0 · SolidJS + Vite OpenChamber 2.5.2 · React 19 + Vite Method: repository source, package manifests, build configs

🎯 TL;DR — the honest answer

There is no Next.js, no Vue, no PHP and no hand-written HTML app in either project. Both interfaces are TypeScript single-page applications built with Vite. The real difference is the UI library and the amount of product surface you inherit:

QuestionOpenCodeOpenChamber
UI frameworkSolidJS 1.9 (fine-grained reactivity)React 19.1
UI source size~680 files / 7.2 MB app~4,388 files / 40.6 MB ui
Who serves the pageThe OpenCode binary itself (opencode web)A separate Express 5 server (openchamber serve)
Branding / theme changeEasy — CSS token file + preload scriptEasiest — JSON theme files, live reload, VS Code theme import
Add a real panel or featureHard — SolidJS, private UI-plugin package, rebuild binaryMedium — React, large codebase, SDK extension surface
Host it for other peopleBasic auth + CORS flagsPurpose-built: PWA, WebAuthn, relay, tunnels, reverse proxy
Verdict for "I want my own version"Best as the engine, not the skinBest as the product you rebrand and host
The short recommendation

If you want to change how the agent works → fork OpenCode core and keep its UI. If you want a custom workspace you host for yourself or a team → fork OpenChamber and change its theme and a dozen components. If you want your own product UI → do not fork either one; build a thin frontend against the OpenCode HTTP/SSE API. That last path is the one most people actually want and it is the least painful.

🧱 Stack comparison — what is actually inside

LayerOpenCode (anomalyco/opencode)OpenChamber (openchamber/openchamber)
Primary languageTypeScript (frontend, server, CLI, TUI)TypeScript; compiled JS in the server bundle
UI frameworkSolidJS 1.9.15 + @solidjs/routerReact 19.1 + react-dom
App bundlerVite 8.2.2 (rolldown) + vite-plugin-solidVite 7.1 + @vitejs/plugin-react
StylingTailwind CSS 4.3.3 + CSS custom-property tokens (--v2-*)Tailwind CSS 4 + a token-based design system CSS
Component primitivesKobalte, Corvu drawer, DnD Kit SolidBase UI 1.4, Radix primitives, cmdk, sonner
Data / stateTanStack Solid Query, EffectZustand 5, TanStack Virtual
ServerTypeScript server in packages/server, Bun runtimeExpress 5 on Node ≥ 24.14, ws, http-proxy-middleware
Desktop shellElectron 44 (electron-vite)Electron (separate package)
Mobile— (PWA only)Capacitor 8 (iOS + Android)
VS CodeEditor extension in sdks/vscodeFull webview extension package
Docs / marketing siteAstro 5 + Starlight + Solid islands (packages/web, 560 MDX pages)Docs inside the same monorepo
Package manager / runtimeBun 1.4.4, TurborepoBun 1.4.4 for build, Node ≥ 24.14 to run
LicenseMITMIT
Repo scale (blobs)~9,964 files · ~606 MB~7,945 files · ~439 MB

Two things surprise most people:

🗺️ Architecture: who serves what

This is the single most important structural difference for customisation, because it decides what you have to rebuild and redeploy.

OpenCode ┌──────────────────────────────────────────────────────────────┐ │ opencode (single Bun binary) │ │ │ │ packages/app (SolidJS SPA, built with Vite) │ │ │ embedded static assets │ │ ▼ │ │ packages/server ── HTTP API + SSE ──► core / tools / LLM │ │ ▲ │ │ └── TUI (packages/tui) · Desktop (packages/desktop) │ └──────────────────────────────────────────────────────────────┘ opencode web → http://127.0.0.1:4096 (UI and API, same origin) opencode serve → headless API only, --cors for custom frontends OpenChamber ┌──────────────────────────────────────────────────────────────┐ │ openchamber serve (Node + Express 5, port 3001) │ │ │ │ serves built SPA ──► packages/ui (React 19) │ │ auth (WebAuthn) · PWA · relay · push · tunnels │ │ │ proxy + WebSocket bridge │ │ ▼ │ │ OpenCode server (HTTP API + SSE) │ └──────────────────────────────────────────────────────────────┘ Same UI bundle is reused by Electron, Capacitor mobile, VS Code

OpenCode ships one artifact that is both UI host and API. OpenChamber is a separate application server that talks to OpenCode from outside.

Practical consequence: in OpenCode, changing the UI means rebuilding the app and repackaging it into the binary (or running the Vite dev server against a live server). In OpenChamber, the UI is a static bundle served by a normal Node process — you can drop a rebuilt dist/ in, run it behind Nginx or Cloudflare, restart the process, and you are done. That is a big operational difference if you intend to run this for more than one machine.

🔵 OpenCode web in depth

What the web surface is made of

PackageRoleFiles / size
packages/appThe web application: routes, session timeline, composer, settings, i18n for ~30 locales680 · 7.2 MB
packages/uiShared component library + design tokens + 1,213 SVG icons + sounds1,691 · 7.1 MB
packages/session-uiChat timeline, tool renderers, diffs, markdown rendering159 · 1.1 MB
packages/gui-pluginsBrowser-side plugin host (browser panel, Office previews)internal, not published
packages/serverHTTP API, SSE, runtime composition55 · 0.2 MB
packages/webDocumentation site (Astro/Starlight) — not the app627 · 11 MB

The honest scale note: the average file is small (7.2 MB over 680 files), the biggest frontend files are translation dictionaries, and the component library is mostly icons. That makes the app less intimidating than the numbers suggest — but it is still SolidJS, which many developers have never written.

How you run and edit it

# use it
opencode web --port 4096                 # UI + API on one origin
OPENCODE_SERVER_PASSWORD=secret opencode web --hostname 0.0.0.0
opencode serve --cors https://my-ui.example   # API only, for your own frontend

# develop it (two terminals, from the repo root)
bun install
bun dev serve --port 4096                # backend
bun run dev:web                          # Vite dev server for packages/app
bun run dev:desktop                      # Electron shell
bun run dev:www                          # docs site

Theming reality

Colours are not hard-coded into components. The app imports @opencode/ui/styles/tokens and styles everything from semantic variables such as --v2-background-bg-base, --v2-text-text-base, --v2-border-border-base and --v2-icon-icon-accent. A compact theme preload script (packages/app/public/oc-theme-preload.js, inlined at build time) applies the saved theme before first paint, so a rebrand does not flash.

This means a visual rebrand is genuinely a small job: edit packages/ui/src/styles/tokens/theme.css (or override the variables), swap the logo and fonts in packages/app/src/index.css, rebuild. No component surgery required.

Extensibility without forking

So: you can extend the engine cleanly without touching its UI, but you cannot plug arbitrary new UI panels into the stock web client without forking packages/app.

Most underrated feature

opencode serve exposes the full agent (sessions, streaming tokens, tool events, permissions) over HTTP + SSE, with generated TypeScript clients in packages/client, and the documented --cors flag exists specifically for custom frontends. That is an invitation to write your own UI instead of fighting someone else's.

🟢 OpenChamber web in depth

Monorepo map

PackageRoleNotes
packages/uiAll shared UI: chat, files, diffs, terminal, settings, themes, i18n4,388 files / 40.6 MB — the biggest piece by far
packages/webExpress server + Vite build + the openchamber CLI1,272 files; server side is mostly compiled JS
packages/electronDesktop appReuses the same UI bundle
packages/mobileCapacitor 8 iOS/AndroidSame UI, native bridge
packages/vscodeVS Code webview extensionSame UI
packages/sdkPublic extension SDK + docsPanels, services, guest services
packages/extensionsBuilt-in extension registryRegistry currently empty, contract in place

How you run and edit it

# install / run
bunx @openchamber/web serve --port 3001     # or: openchamber serve
# it connects to your local OpenCode server, then proxies sessions to the browser

# develop it (from the repo root)
bun install
bun run dev            # HMR: UI on :5180, API on :3902
bun run build:web      # production UI bundle
node ./scripts/dev-web-hmr.mjs

Theming is a first-class product feature

This is where OpenChamber clearly wins. Themes are data, not code:

{
  "metadata": { "id": "my-theme", "name": "My theme", "variant": "dark" },
  "colors": {
    "primary": { "base": "#da7c47" },
    "surface": {
      "background": "#120f0e",
      "foreground": "#c9c5ba",
      "muted": "#0e0c0b",
      "mutedForeground": "#8f8b81",
      "elevated": "#181715"
    },
    "interactive": { "border": "#242323" },
    "status": { "error": "#da5b4a", "warning": "#c67f13", "success": "#76ad4f", "info": "#479fe6" }
  }
}

Extensibility and hosting

The cost of all that

4,388 UI files and 40 MB is not a small codebase to learn. Themes and small component tweaks are cheap; understanding the session store, streaming bridge and settings registry well enough to add a feature takes real time. It also pins a specific OpenCode client version, so upstream API changes can require upgrades on your side.

📊 Editability scorecard

Scores are my assessment from source structure, build configuration and dependency weight — 1 is painful, 5 is easy. They are opinion, not upstream data.

CriterionOpenCodeOpenChamberWhy
Rebrand colours / logo45Token CSS either way; OpenChamber's JSON themes need no rebuild
Adjust an existing screen34SolidJS vs React familiarity; both componentised
Add a new panel / feature24OpenCode's web plugin API is private; OpenChamber has a public SDK
Build & dev friction23OpenCode rebuilds into a Bun binary; OpenChamber is a Node server
Learning curve24SolidJS is niche; React 19 is mainstream
Host for other people25Auth, PWA, relay, proxy and mobile are already there
Extend without forking34OpenCode: engine plugins only. OpenChamber: SDK panels + services
Upstream churn risk23OpenCode moves fast on dev with 222k stars; OpenChamber pins versions
Total20 / 4032 / 40For "make it mine", OpenChamber is the easier base

A third option beats both on control and is often overlooked: your own frontend on top of opencode serve. You write exactly the screens you want in whatever framework you like, and you inherit zero UI debt. It scores ~34/40 on these criteria but costs more upfront than a theme change.

🧩 Where to touch for your changes

OpenCode

Theme & brand

packages/ui/src/styles/tokens/theme.css
packages/ui/src/styles/colors.css
packages/app/src/index.css (fonts)
packages/app/public/oc-theme-preload.js

OpenCode

Layout & screens

packages/app/src (routes, shell)
packages/session-ui/src (chat, tools)
packages/ui/src (primitives)

OpenChamber

Theme & brand

packages/ui/src/styles/design-system.css
packages/ui/src/lib/theme/themes/*.json
~/.config/openchamber/themes/*.json (no rebuild)

OpenChamber

Layout & screens

packages/ui/src/App.tsx
packages/ui/src/components/…
packages/web/server (auth, proxy, API)

Two editing rules that will save you days on either repo:

  1. Never start by editing components. Change tokens first and screenshot. Half of "customisation" ends there.
  2. Never let your fork drift on main/dev. Keep your changes in a small set of theme files and a handful of components, so upstream pulls stay trivial. The moment you rewrite the session layer, you have adopted the project.

🧭 Decision guide by goal

What you actually wantPickEffort
"I just want it to look like my brand"Either — OpenChamber if you also want themes to be editable at runtimehours
"I want to host it and use it from my phone / another machine"OpenChamberdays
"I want to add my own sidebar, dashboard or workflow screen"OpenChamber fork, or your own frontend1–2 weeks
"I want a completely different UI, my own design language"Own SPA on opencode serve2–4 weeks
"I want to change how the agent thinks: tools, prompts, providers"OpenCode core forkvaries
"I want to embed the agent inside my existing product"OpenCode API/SDK — do not ship their UIdays
Why not "just fork OpenCode's app"?

You would take on SolidJS, a private UI-plugin surface, and a build that produces a Bun binary — all to get a UI you still have to design. If your goal is your own interface, forking the smallest polished React app (OpenChamber) or writing a thin client is strictly less work.

🚀 Recommended plan

Step 1 — Decide what "customise" means (30 minutes)

Write down which of these you actually need: colours/logo, layout changes, new screens, different agent behaviour, multi-user hosting. The answer selects the path; mixing them is how projects stall.

Step 2 — Theme-only spike (half a day)

Step 3 — Build the fork properly

Step 4 — Only then consider your own frontend

If, after two weeks of forking, you keep fighting the original layout, stop and build the thin client. The API is stable enough, the streaming model is documented, and you keep the agent while owning the interface.

⚠️ Risks, limits, what I did not verify

ItemStatus
Versions, file counts, dependenciesRead from the repositories and package manifests on 27 Oct 2026 (dev and main)
Theme mechanics in OpenCode / OpenChamberVerified in source files and official theme documentation
Actual runtime behaviour of both appsNot executed here — this is source-level research, not a hands-on benchmark
Build times, bundle sizes, memory useNot measured; do not quote as fact
Scorecard numbersMy judgement, weighted for a solo developer rebranding and hosting
Upstream velocityBoth repos were pushed within minutes of this report; APIs can move under you. Pin tags.

📚 Sources