## What / Why This PR finishes the desktop refactor: the Tauri app is now a thin shell that launches the web server as a sidecar and loads the UI from `http://127.0.0.1:<port>`. All real backend logic lives in `packages/web/server/index.js`; desktop Rust keeps only native integrations (menu/dialog/notifications/updater/deep-link + window chrome). This unblocks: - consistent behavior across web/desktop/vscode (single backend) - simpler desktop maintenance (no duplicated Rust backend) - host switching between Local + remote instances in desktop - reliable cold-start behavior on slow machines (VSCode + desktop) ## Key changes - Desktop sidecar runtime - build pipeline to bundle web dist + `openchamber-server` sidecar (`packages/desktop/scripts/build-sidecar.mjs`) - robust local port selection (prefer saved/default, fallback to random; persisted in `~/.config/openchamber/settings.json`) - improved PATH handling so the sidecar can locate `opencode` CLI (incl `~/.opencode/bin`, overrides, common bins) - disable native right-click context menu in production builds (dev keeps it) - Desktop instance switcher (Tauri-only) - header button + modal to add/edit/delete remote hosts, set default, probe status/ping, switch back to Local escape hatch - auth gate includes host switcher so you can recover when a remote host is broken/auth-required - host list stored desktop-locally (not tied to the currently selected remote server) - Notifications - decision logic moved server-side; desktop notifications emitted via sidecar stdout and shown natively by Tauri - prevent double-notifications on desktop Local origin (UI ignores SSE notification when native path is active) - restore macOS notification sound - Updates - Tauri updater used only when viewing Local instance in desktop shell (avoid “remote web update” triggering desktop restart) - Settings persistence & UX polish - persist model favorites/recents via `/api/config/settings` (works for web + desktop; not origin-dependent) - persist per-project sidebar collapse state in `projects[].sidebarCollapsed` via `/api/config/settings` (with debounce on toggles) - macOS header sizing/traffic-lights offsets fixed (marketing macOS major injected from desktop; MultiRun header aligned) - VSCode cold-start: keep retrying provider/agent loads after connection to avoid empty UI on slow machines - misc lint/type fixes + bun.lock sync - Desktop bootstrap / resiliency - show onboarding screen when OpenCode CLI is missing (desktop Local origin), with retry hook to restart OpenCode after install ## Testing notes - Desktop (macOS): switch Local <-> remote, set default host, verify auth gate recovery, native notifications (with sound), updater gated to Local - Web: favorites/recents + per-project collapsed state persist across reload/restart - VSCode: slow startup no longer results in missing providers/agents/models
4.8 KiB
4.8 KiB
OpenChamber - AI Agent Reference (verified)
Core purpose
OpenChamber provides UI runtimes (web/desktop/VS Code) for interacting with an OpenCode server (local auto-start or remote URL). UI uses HTTP + SSE via @opencode-ai/sdk.
Runtime architecture (IMPORTANT)
Desktopis a thin Tauri shell that starts the web server sidecar and loads the web UI fromhttp://127.0.0.1:<port>.- All backend logic lives in
packages/web/server/*(andpackages/vscode/*for the VS Code runtime). Desktop Rust is not a feature backend. - Tauri is used only for stable native integrations: menu, dialog (open folder), notifications, updater, deep-links.
Tech stack (source of truth: package.json, resolved: bun.lock)
- Runtime/tooling: Bun (
package.jsonpackageManager), Node >=20 (package.jsonengines) - UI: React, TypeScript, Vite, Tailwind v4
- State: Zustand (
packages/ui/src/stores/) - UI primitives: Radix UI (
package.jsondeps), HeroUI (package.jsondeps), Remixicon (package.jsondeps) - Server: Express (
packages/web/server/index.js) - Desktop: Tauri v2 (
packages/desktop/src-tauri/) - VS Code: extension + webview (
packages/vscode/)
Monorepo layout
Workspaces are packages/* (see package.json).
- Shared UI:
packages/ui - Web app + server + CLI:
packages/web - Desktop app (Tauri):
packages/desktop - VS Code extension:
packages/vscode
Build / dev commands (verified)
All scripts are in package.json.
- Validate:
bun run type-check,bun run lint - Build all:
bun run build - Desktop build:
bun run desktop:build - VS Code build:
bun run vscode:build - Release smoke build:
bun run release:test(shell script:scripts/test-release-build.sh)
Runtime entry points
- Web bootstrap:
packages/web/src/main.tsx - Web server:
packages/web/server/index.js - Web CLI:
packages/web/bin/cli.js(package bin:packages/web/package.json) - Desktop: Tauri entry
packages/desktop/src-tauri/src/main.rs(spawns web server sidecar + loads web UI) - Tauri backend:
packages/desktop/src-tauri/src/main.rs - VS Code extension host:
packages/vscode/src/extension.ts - VS Code webview bootstrap:
packages/vscode/webview/main.tsx
OpenCode integration
- UI client wrapper:
packages/ui/src/lib/opencode/client.ts(imports@opencode-ai/sdk/v2) - SSE hookup:
packages/ui/src/hooks/useEventStream.ts - Web server embeds/starts OpenCode server:
packages/web/server/index.js(createOpencodeServer) - Web runtime filesystem endpoints: search
packages/web/server/index.jsfor/api/fs/ - External server support: Set
OPENCODE_PORTandOPENCODE_SKIP_START=trueto connect to existing OpenCode instance
Key UI patterns (reference files)
- Settings shell:
packages/ui/src/components/views/SettingsView.tsx - Settings shared primitives:
packages/ui/src/components/sections/shared/ - Settings sections:
packages/ui/src/components/sections/(inclskills/) - Chat UI:
packages/ui/src/components/chat/andpackages/ui/src/components/chat/message/ - Theme + typography:
packages/ui/src/lib/theme/,packages/ui/src/lib/typography.ts - Terminal UI:
packages/ui/src/components/terminal/(usesghostty-web)
External / system integrations (active)
- Git:
packages/ui/src/lib/gitApi.ts,packages/web/server/index.js(simple-git) - Terminal PTY:
packages/web/server/index.js(bun-pty/node-pty) - Skills catalog:
packages/web/server/lib/skills-catalog/, UI:packages/ui/src/components/sections/skills/
Agent constraints
- Do not modify
../opencode(separate repo). - Do not run git/GitHub commands unless explicitly asked.
- Keep baseline green (run
bun run type-check,bun run lint,bun run buildbefore finalizing changes).
Development rules
- Keep diffs tight; avoid drive-by refactors.
- Backend changes: keep web/desktop/vscode runtimes consistent (if relevant).
- Follow local precedent; search nearby code first.
- TypeScript: avoid
any/blind casts; keep ESLint/TS green. - React: prefer function components + hooks; class only when needed (e.g. error boundaries).
- Control flow: avoid nested ternaries; prefer early returns +
if/else/switch. - Styling: Tailwind v4; typography via
packages/ui/src/lib/typography.ts; theme vars viapackages/ui/src/lib/theme/. - No new deps unless asked.
- Never add secrets (
.env, keys) or log sensitive data.
Theme System (MANDATORY for UI work)
When working on any UI components, styling, or visual changes, agents MUST study the theme system skill first.
Before starting any UI work:
skill({ name: "theme-system" })
This skill contains all color tokens, semantic logic, decision tree, and usage patterns. All UI colors must use theme tokens - never hardcoded values or Tailwind color classes.
Recent changes
- Releases + high-level changes:
CHANGELOG.md - Recent commits:
git log --oneline(latest tags:v1.4.6,v1.4.5)