Navigation model rebuilt around two full-width drawers and a minimal
header (sessions / title-switcher / usage ring / workspace):
- Left sessions drawer: cross-project tree with live status indicators,
swipe actions on sessions (rename/archive/delete) and on group headers
(project edit / two-step close, worktree delete), reorder-only edit
mode with collapsible project cards and draggable worktrees, app-level
footer (connected instance, settings, pending web update).
- Right workspace drawer: Changes / Files / Terminal / Notes / MCP as
pill tabs (inactive tabs icon-only); panes stay mounted once visited.
The full desktop file editor serves the Files tab; read/skill tool taps
in chat open the file there at the requested line.
- Header session switcher on title tap: 10 cross-project recents with
live busy/attention indicators and project · branch metadata; the
usage ring opens a metadata overlay with an explicit loading state.
- The overflow menu is gone on phones (its destinations moved into the
drawers); iPad keeps it until its dedicated layout pass.
Correctness and continuity:
- /auth/session answers bearer-first, so a stale WebView cookie can no
longer mask a revoked device token; cold launches classify failures
fast and land on an explicit connect screen.
- Authoritative session snapshots raise frozen ordering baselines and
stale live ranks — recents stay truthful after the app slept.
- Cold launches reopen the last active session per instance (persisted
pointer, confirmed against a sessions snapshot; a user-opened draft
clears it), with a logo hold instead of a draft flash.
Also: collapsed pill composer gains the stop control; chat tool rows
share one 36px rhythm; Task subtool rows truncate; larger bottom safe
area so the composer clears big-screen corner radii; Capacitor build
hides About/Update (store updates apply there); widgets link to the
sessions drawer with a list icon; MobileApp split into focused modules;
five mobile-surface detectors unified; translucent borders normalized to
70%; all new strings translated across the 10 locales.
iPad and foldable layouts are intentionally untouched - separate next version PR.
linux-x86_64.AppImage for 64-bit Intel or AMD systems
linux-arm64.AppImage for ARM64/aarch64 systems
Make the AppImage executable before launching it, for example with chmod +x <downloaded-appimage>. Keep the AppImage in a location your user can write to so OpenChamber can download and apply in-app updates.
Linux AppImages need FUSE (libfuse.so.2). On Ubuntu/Debian install libfuse2 (or fuse / libfuse2t64 on newer releases). If FUSE is unavailable, run with extraction instead:
openchamber --port 8080# Custom port
openchamber --lan --port 3000# Listen on LAN (0.0.0.0)
openchamber --ui-password secret # Password-protect UI
openchamber startup enable# Start at login as a native serviceOPENCHAMBER_UI_PASSWORD=secret openchamber startup enable# Save service password env
openchamber startup status # Show startup service status
openchamber startup disable # Remove startup service
openchamber tunnel help# Tunnel lifecycle commands
openchamber tunnel providers # Show provider capabilities
openchamber tunnel profile add --provider cloudflare --mode managed-remote --name prod-main --hostname app.example.com --token <token>
openchamber tunnel start --profile prod-main
openchamber tunnel start --provider cloudflare --mode quick --qr
openchamber tunnel start --provider cloudflare --mode managed-local --config ~/.cloudflared/config.yml
openchamber tunnel status --all # Show tunnel state across instances
openchamber tunnel stop --port 3000# Stop tunnel only (server stays running)
openchamber connect-url --port 3000# Add this server to OpenChamber Desktop
openchamber connect-url --server http://host:3000 --qr
openchamber connect-url --port 3000 --qr
openchamber logs # Follow latest instance logsOPENCODE_PORT=4096OPENCODE_SKIP_START=true openchamber # Connect to external OpenCode serverOPENCODE_HOST=https://myhost:4096 OPENCODE_SKIP_START=true openchamber # Connect via custom host/HTTPS
openchamber stop # Stop server
openchamber update # Update to latest
startup enable snapshots your current environment into the native service so startup behaves like you launched openchamber from the same shell. This preserves provider tokens, PATH, SSH agent settings, and other CLI auth/config env vars. Use --no-env-snapshot if you want a minimal service env.
This runs OpenChamber as an API-only server without the desktop app or browser UI assets on that machine, then creates a link for Desktop to import. --lan makes the server reachable from other machines. --server is the address Desktop should use.
When OpenChamber was started with --lan or --host 0.0.0.0, connect-url automatically uses a detected LAN IP instead of 127.0.0.1. Use --server http://host:3000 to override the advertised address, and include --lan when connect-url needs to start the server for LAN access.
Paste the printed openchamber://connect?... link in Desktop under Settings -> Remote Instances -> Direct Instances -> Import Link. The link contains the server URL and a client token. It does not enable browser UI password protection; use --ui-password when exposing a server beyond localhost.
systemd service (VPN / LAN access)
Run OpenChamber and OpenCode as separate persistent services — useful when you want to access your
dev machine over a VPN (e.g. Tailscale) or LAN without a Cloudflare tunnel.
How it works:
OpenCode runs as its own service, binding only to localhost.
OpenChamber connects to it via OPENCODE_HOST and --lan makes it reachable on your VPN IP.
--foreground keeps the CLI process alive so systemd can track and restart it.
Why set PATH and SSH_AUTH_SOCK?
systemd user services start with a minimal environment — no shell profile is sourced.
Without an explicit PATH, OpenCode won't find tools installed via Homebrew, npm, or ~/.local/bin.
Without SSH_AUTH_SOCK, git operations over SSH (push, pull, clone) will fail because the agent socket isn't inherited.
Adjust the PATH to match your own tool installation paths.
%t expands to $XDG_RUNTIME_DIR (e.g. /run/user/1000), where most SSH agents write their socket.
OpenChamber will be reachable at http://<your-vpn-hostname>:3000 from any device on your VPN.
Note:--host 0.0.0.0 is required to listen on all interfaces. The default
bind address is 127.0.0.1 (localhost only). Use --host <ip> or
OPENCHAMBER_HOST=<ip> to bind to a specific interface instead.
Managed-local path note: OPENCHAMBER_TUNNEL_CONFIG must point to a path inside the container user home (/home/openchamber/...). If your Cloudflare config references a credentials JSON file, that file path must also be accessible inside the container (mount with volumes).
Website docs source lives at packages/docs/content/docs/reverse-proxy.mdx.
Tunnel behavior notes
OpenChamber supports one active tunnel per running instance (port).
Starting a tunnel with a different mode/provider on the same instance replaces the current tunnel.
Replacing or stopping a tunnel revokes existing connect links and invalidates remote tunnel sessions for that instance.
Connect links are one-time tokens; generating a new link revokes the previous unused link.
Data Directory Permission Note: The data/ directory is mounted into the container for persistent storage (config, sessions, SSH keys, workspaces). Before running, ensure the directory exists and has proper permissions:
My wife, who - with zero AI background - sat down with the app for the first time and built the firework celebration that plays on every successful push.
Every contributor who shaped this project with their PRs, ideas, and attention to detail.