The env var was already read and passed to the managed OpenCode server
spawn, but any non-empty string was accepted. Reject values that are
not a valid IP (IPv4/IPv6, brackets allowed) or DNS-style hostname with
a clear [config] error and fall back to the secure loopback default so
a typo can never silently bind a non-loopback address.
Refs OPE-231
Add an opt-in OpenCode plugin that replaces the built-in provider behavioral prompt with a minimal identity while preserving environment, project, MCP, skill, history, and tool context.
Track the active agent per session and apply the transform only to build and plan. Keep plan/build mode reminders and permission enforcement owned by OpenCode, leave all other agents untouched, and fail safely when the expected prompt boundary is absent.
Expose the feature in Behavior settings with localized guidance, explicit Save + Reload application, settings search integration, persisted boolean validation, and managed-runtime lifecycle composition that does not load the plugin while disabled or on external OpenCode servers.
Document the runtime contract and cover plugin materialization, config preservation, build/plan selection, agent switching, unknown prompt formats, and settings sanitization.
Add a shared OpenChamber control service with two thin adapters — a native
`openchamber` tool injected into managed OpenCode, and new CLI commands — so
users can manage parallel sessions, worktrees, and scheduled tasks
conversationally through agents or from the terminal.
Control plane:
- New openchamber-control service owning a fixed action contract:
projects.list, models.list, session list/create/send/fork/status/messages,
and schedule list/create/run/delete/toggle. Session and worktree deletion
and project registration are deliberately not exposed.
- New openchamber-sessions module owning create/worktree/prompt orchestration,
Goal Mode dispatch, wait semantics (initial idle never counts as completion;
timeout and cancellation are failures), and explicit partial-failure results.
- Scheduled-task logic extracted into a service shared by routes, CLI, and the
agent tool.
Agent tool:
- Managed OpenCode gets a materialized plugin registering one typed tool with
a loopback-only callback, per-child ephemeral bearer (timing-safe, never
persisted or logged), and abort propagation into the service.
- The ~1.5k-token schema applies progressive disclosure: short descriptions,
server-side validation returning actionable usage errors, and intent
guardrails — created sessions/tasks are user-facing work (not age
self-delegation); worktree/goal/agent/variant/wait are omit-by-default;
dispatches produce no completion notification, and later result r
to session.messages, which now returns the authoritative sessionStatus.
- session.create without a user-named model picks from favorites/re
send/fork omit the selection and the service reuses the target session's
last user-message model, agent, and variant before falling back t
- An "Agent control tool" setting (default on, Save + Reload to apply)
disables plugin injection entirely.
CLI:
- New `openchamber session`, `schedule`, `projects`, and `models` commands
with automatic instance targeting, --wait/--timeout/--last-assist
worktree flags, and Goal Mode, preserving interactive, non-TTY, --quiet,
and --json contracts. The control HTTP timeout derives from the w
instead of the 4-second default.
UI:
- New built-in "Schedule a Task" starter (/schedule-task) running a
dialogue that defines a task and offers to create it via the tool after
explicit confirmation; Craft a Goal and Feature Planning gain the
handoff offer, and guided starters reserve the question tool for concrete
option choices. Localized in all 10 locales, migrated into custom
starter lists, hidden on VS Code.
- Sidebar shows CLI/agent-created sessions live via the control eve
- openchamber tool calls render with per-action titles and metadata.
Replace the legacy terminal flow with a shared authenticated WebSocket
runtime used across web, desktop, relay, and mobile surfaces.
- introduce the v3 terminal protocol with scoped attachments, snapshots,
ordered output, bounded replay history, reconnects, and explicit lifecycle
- harden PTY creation, restart, resize, close, force-kill, idle cleanup,
shell selection, login mode, environment sanitization, and appearance sync
- add runtime-aware terminal APIs with relay authentication and Electron parity
- add a fullscreen mobile terminal workspace with touch scrolling,
long-press selection, safe-area controls, quick keys, and Ctrl/Alt input
- add terminal selection attachments, preview detection, project actions,
shell settings, and localized UI
- harden Ghostty rendering, resize recovery, Unicode handling, block
characters, line height, and stale-row behavior
- remove the obsolete terminal SSE path and update reverse-proxy guidance
- expand terminal runtime, transport, input, selection, and store coverage
- avoid duplicate web builds when preparing mobile assets in root CI builds
* feat(electron): add Linux AppImage releases
* ci: cache Linux OpenCode CLI artifacts
* fix(ci): await Linux release inventory check
* fix(electron): add frameless window controls on Linux desktop
Linux AppImages were created without native WM decorations and without
in-app controls, leaving users unable to close the window with a mouse.
Treat Linux like Windows: frameless BrowserWindow plus the existing
WindowsWindowControls header buttons and app-menu entry. macOS keeps
hidden title bar with traffic lights unchanged.
Shared usesFramelessElectronChrome() helper drives main window, mini
chat, header insets, and titlebar controls.
Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
* feat(desktop): add configurable window controls position by OS
Add desktopWindowControlsPosition setting (auto/left/right) with OS-aware
defaults: Linux left, Windows right. Wire frameless chrome controls in
Header, TitlebarLeftControls, and MiniChatLayout, plus a Sessions settings
control for Windows and Linux desktop shells.
Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
* fix(desktop): address Linux AppImage release review findings
Propagate updater capability errors to the UI, treat missing
latest-linux.yml feeds as no-update, stop installed-apps IPC spam on
Linux, document FUSE/AppImage limits, add CHANGELOG entry, migrate
remaining btriapitsyn URLs, and run Electron Linux unit tests on PRs.
Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
---------
Co-authored-by: jibanez-staticduo <staticduo@gmail.com>
Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
Add a packaged-client runtime boundary so the shared UI can talk to local,
desktop, remote, and VS Code runtimes through the right transport instead of
assuming one same-origin web server.
Centralize OpenChamber-owned API access behind RuntimeAPIs, runtimeFetch, and
runtime URL helpers, while keeping official OpenCode traffic on the SDK path.
Support runtime switching, remote host selection, desktop client credentials,
and headless connection links for pairing packaged clients with remote
OpenChamber servers.
Harden the new auth model by moving long-lived client tokens out of browser
URLs, introducing short-lived scoped URL tokens for browser-owned transports,
restricting URL-token access to explicit readable/realtime routes, and making
client-token management session-scoped or self-scoped as appropriate.
Update browser-owned assets and preview proxy flows to work with the split
runtime model, including authenticated project icons, preview token propagation,
CSP-safe preview bridge injection, and preview proxy auth that survives
short-lived URL-token expiry.
Tighten Electron security boundaries for packaged clients by gating privileged
preload state to trusted origins and requiring explicit confirmation before
connect deep-links import or switch remote runtimes.
Also refresh agent guidance and project skills so future runtime/API, auth,
preview, UI, CLI, settings, locale, and drag-to-reorder work follows the new
architecture.
Add launch-at-startup support across the Electron desktop app and the web CLI.
Electron now supports macOS launch-at-login through the native login item API. Login launches start OpenChamber in the background without opening a window, while Dock activation, deep links, and second-instance launches still open or focus the normal app window. The desktop Settings UI now exposes a localized launch-at-login toggle in Desktop Network Access.
The web CLI now includes `openchamber startup status|enable|disable`, backed by native user services:
- macOS: launchd LaunchAgent
- Linux: systemd --user service
- Windows: Task Scheduler
Startup services run `openchamber serve --foreground` so the OS service manager owns process lifetime and restarts. Foreground service updates now defer restarts to the service manager instead of spawning duplicate CLI restarts.
Startup services snapshot useful environment variables by default so provider tokens, PATH, SSH agent settings, and OpenCode configuration survive login/reboot starts. The snapshot avoids shell/session-only state, uses systemd-compatible env quoting on Linux, and avoids unused env artifacts on macOS.
Also adds localized docs for startup services and environment variables.
* feat(cli): add --foreground flag for systemd and process manager deployments
Adds --foreground / --no-daemon to `openchamber serve` which runs the
server inline in the CLI process instead of spawning a detached daemon child.
Required for systemd Type=simple (and other process managers) that track the
direct child — the always-daemon behavior introduced in #640 broke this use case.
Also documents OPENCHAMBER_HOST (bind address) in --help, which was
implemented but never exposed to users.
* docs: add systemd service guide for VPN/LAN deployments
Documents how to run OpenCode and OpenChamber as separate systemd
user services for persistent access over Tailscale or LAN, using
the new --foreground flag and OPENCODE_HOST to wire them together.
* fix(cli): address foreground mode parity issues from PR review
- Fix Ctrl+C handling: CLI SIGINT handler now defers to server in
foreground mode; dedicated signal handlers perform graceful shutdown
and clean exit
- Restore lifecycle parity: foreground instances write PID/instance
files so status, stop, and restart can discover them
- Add deterministic --foreground --json output: emits stable startup
JSON with port, pid, url, and foreground flag before blocking
* fix(cli): tighten inline foreground behavior for restart UX and JSON-only output
* fix(cli): pass --host to foreground server, reject --json, add --quiet output
- Pass options.host through to startWebUiServer() in foreground mode so
the bind address is respected (fixes localhost-only regression from #750)
- Reject --foreground --json with a clear usage error; --json is only
supported in background (daemon) mode
- Emit resolved port on stdout in --quiet foreground mode, matching
daemon parity
- Update systemd docs to include --host 0.0.0.0 for LAN/VPN access
now that the default bind is 127.0.0.1
* fix(cli): remove duplicate OPENCHAMBER_HOST entry from help text
* fix(cli): emit restart summary before foreground serve() blocks
restart --json (and --quiet / human) with a foreground instance would
hang forever without output because serve() blocks and the post-loop
summary was unreachable. Emit the final output after stop succeeds
but before the blocking serve call — foreground is always sorted last
so all daemon results are already collected.
* fix(cli): restart stops foreground instances without re-attaching
Foreground instances are managed by a process manager (systemd, Docker,
etc.) that will restart them automatically. The restart command now
just stops the foreground instance, records the result, and exits —
no serve() call, no blocking. This makes restart --json and all
other output modes work correctly for foreground instances.
* feat(server): support configurable hostname for managed OpenCode server spawn
Allow the managed OpenCode server bind hostname to be configured via
OPENCHAMBER_OPENCODE_HOSTNAME environment variable (default: 127.0.0.1).
This enables LAN/Tailscale access without a reverse proxy by setting
the hostname to 0.0.0.0.
Closes#597
* fix: address review feedback — input validation, port probe hostname, security docs
- Add defensive parsing for OPENCHAMBER_OPENCODE_HOSTNAME with trim/empty
check and warning log, matching OPENCODE_HOST validation pattern
- Pass configured hostname to resolveManagedOpenCodePort() so port
availability is probed on the actual bind address, avoiding EADDRINUSE
- Add security note in README docs warning about 0.0.0.0 exposure on
untrusted networks
Main README restructured: collapsable features, quick start with secure defaults, Why a GUI section, roadmap
Package READMEs (web/desktop/vscode) rewritten with runtime-specific focus; VSCode includes full commands and settings
Added SECURITY.md, non-dev contributing guide, and updated CONTRIBUTING.md with dev scripts and ports
* docs: clarify named and quick Cloudflare tunnel usage
* feat: make chat file paths openable from rendered responses
* perf: speed up chat file-path links and open behavior
* fix: open chat file references at mentioned lines
* fix: prevent context panel flicker on blocked file opens
* feat(server): add OPENCODE_HOST env var for external OpenCode connections
Allows specifying a full base URL (e.g. https://hostname:4096) for external
OpenCode connections, supporting custom hostnames and HTTPS. When set,
OPENCODE_HOST overrides OPENCODE_PORT. Malformed values are fatal at startup.
* docs: document OPENCODE_HOST env var in README and AGENTS
* Fatal error when OPENCODE_HOST has path, search or hash
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Colin Mollenhour <colin@mollenhour.com>
* fix(server): use external origin when re-probing OpenCode
---------
Signed-off-by: Colin Mollenhour <colin@mollenhour.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* 🐛 Fix UI crash when subagent is active
Remove sessions dependency from hooks to prevent cascading re-renders.
Use getState() instead and switch to getGlobalSessionStatus().
* ✨ Add support for connecting to external OpenCode server
Add OPENCODE_SKIP_START env var to skip starting embedded server.
Use OPENCODE_PORT to connect to existing OpenCode instance.
Update help text to document the new environment variables.
* 📝 Document external OpenCode server support
Add OPENCODE_PORT and OPENCODE_SKIP_START to READMEs.
Update AGENTS.md with external server integration notes.
* ✨ Add URL-based routing for shareable session links
- Add react-router-dom dependency
- Create URL store for bi-directional sync with Zustand
- Add WebRouter/DesktopRouter context for runtime-aware routing
- Add useURLSync hook to sync URL with session/tab state
- Add useNavigation hook with copySessionLink utility
- Add share button in Header for copying session links
- Update App.tsx to use router wrappers
URL structure:
/session/:sessionId?tab={chat|git|diff|terminal|files}&directory=/path
/settings
This enables shareable links and deep-linking to specific sessions.
* Revert "✨ Add URL-based routing for shareable session links"
This reverts commit b53ee304950a789538fa3d4a236d6361e634ea61.