feat(desktop): web server mirror — true 1:1 remote access via TCP reverse proxy#12000
Open
mguttmann wants to merge 10 commits intoanomalyco:devfrom
Open
feat(desktop): web server mirror — true 1:1 remote access via TCP reverse proxy#12000mguttmann wants to merge 10 commits intoanomalyco:devfrom
mguttmann wants to merge 10 commits intoanomalyco:devfrom
Conversation
Contributor
|
The following comment was made by an LLM, it may be inaccurate: No duplicate PRs found |
aa38bde to
f56f7f2
Compare
Author
91436b3 to
6f7552b
Compare
Author
Author
299f411 to
6daa962
Compare
152738c to
abebec3
Compare
|
Would sessions sync between the terminal and the remote client? I work with OpenCode through the terminal but need a way to monitor and continue sessions from my phone. I've tried Thanks for the great work, btw! |
cbdf097 to
e5a8041
Compare
e54ebbf to
b743cda
Compare
8b41d2a to
e9ce8fa
Compare
added 5 commits
March 6, 2026 08:47
…he network TCP reverse proxy in Rust (tokio) binds on 0.0.0.0:<port> and forwards to sidecar. Mirror web UI bundled as Tauri resource, served via OPENCODE_WEB_DIR. HTTP Basic Auth, sidebar sync (Desktop→Server→Mirror), terminal/add-project hidden in mirror. Settings UI for enable/disable, port, credentials. i18n for all 15 languages.
platform.storage is undefined in both the mirror and the regular web version. Use the mirror-specific check (platform === desktop && !storage) so the Open Project button remains visible in web mode and e2e tests.
The platform variable was already declared at the top of the Layout init function; remove the second declaration that caused a TypeScript redeclaration error.
added 4 commits
March 6, 2026 08:47
…urce retention Align with upstream memory leak fix pattern (fc37337): use globalThis.fetch instead of platform.fetch for local server requests. Also add onCleanup for the debounce timer.
e9ce8fa to
827d651
Compare
6 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Summary
Adds a Web Server Mirror to the desktop app — a TCP reverse proxy that exposes the desktop's existing server to the local network, giving a true 1:1 mirror of the desktop UI accessible from any browser (phone, tablet, second laptop).
Closes #11997
Why not just use
opencode web?Running
opencode webspawns a completely separate server instance. While it shares the filesystem, it has its own in-memory state — meaning SSE events, WebSocket streams, and live session updates don't sync between desktop and web. You'd see stale data, miss notifications, and have to manually manage the lifecycle.A TCP reverse proxy is the right solution: it pipes raw bytes through, so the browser talks directly to the desktop server. Same auth, same events, same state — zero duplication.
opencode web(separate server)How it works
One-way Sidebar Sync
The mirror shows the same projects in the same order as the desktop:
PUT /mirror/sidebaron every change (debounced 300ms)mirror.sidebar.updated)Strictly one-way (Desktop → Mirror) — no reactive loops, no conflict resolution needed.
Security: What's disabled in the mirror and why
Mirror UI Detection
The mirror entry point sets
platform: "desktop"(same UI) but withoutplatform.storage(no Tauri APIs):platform === "desktop" && storage !== undefinedplatform === "desktop" && storage === undefinedAuthentication
HTTP Basic Auth with credential resolution:
OPENCODE_SERVER_USERNAME/OPENCODE_SERVER_PASSWORD)opencode/ random UUID)Features
dist-mirror/, embedded as Tauri resourceUse Cases
Files changed (39 files, +1362 lines)
Rust (desktop core)
lib.rs—WebMirrorState, TCP proxy, 3 Tauri commands, auto-start/stop, orphan cleanup, credential resolutioncli.rs—probe_shell_env()for reading env vars from login shellTypeScript (desktop bindings)
bindings.ts— Tauri command bindings + typesindex.tsx— Platform integrationApp (shared UI)
entry-mirror.tsx— Mirror entry point (platform: "desktop"without Tauri)mirror.html+vite.mirror.config.ts— Mirror buildplatform.tsx— Type definitionssettings-general.tsx— Settings sectionstatus-popover.tsx— Status indicatorlayout.tsx— One-way sidebar syncglobal-sync.tsx— SSE field for mirror sidebarsession-header.tsx,home.tsx,layout.tsx(pages),session.tsx— Hide terminal / add-project in mirrorServer (Hono)
server.ts—GET/PUT /mirror/sidebar+ SSE broadcastflag.ts—OPENCODE_WEB_DIRenv flagBuild
predev.ts/prepare.ts— Mirror build stepstauri.conf.json—web-uiresourcei18n (15 files)
All language files with native translations (ar, br, da, de, en, es, fr, ja, ko, no, pl, ru, th, zh, zht)