Skip to content

RFC: Optional remote backend mode (WSL2 daemon / native Windows UI) #54

@slkzgm

Description

@slkzgm

Summary

I'd like to propose an optional "remote backend" mode that would allow CodexMonitor to run a small daemon on a Linux environment (e.g. WSL2), while keeping the UI as a native desktop app on Windows.

The key constraint is: Codex must keep running in the exact same environment (WSL2) for the same performance, access, tooling, and filesystem semantics — but the UI should not depend on WSLg/gWSL.

This would be opt-in and must not change default behavior for existing users.

Motivation (Windows + WSL2)

In a Windows 11 + WSL2 setup:

  • Projects and tools live in WSL (/home/...), and codex is executed there.
  • Running a Tauri Linux build through WSLg or gWSL works, but the UI can be janky/clunky and GPU permissions can be problematic.
  • The best UX is a native Windows window (WebView2) while preserving a WSL-native codex runtime.

Additional use cases / benefits (beyond WSL)

Even without WSL, a remote backend mode could unlock:

  • Remote Linux dev machines (SSH into a workstation/VM): native UI on the laptop/desktop without X forwarding/VNC.
  • Devcontainers / sandboxes: run the backend inside a container/VM (where the repo, tools, and secrets live), while keeping the UI on the host.
  • Long-running sessions: a supervised daemon (systemd) + UI reconnects after restarts/crashes without losing in-progress work.
  • Future multi-client scenarios: groundwork for a read-only dashboard or a mobile companion UI later (still opt-in).
  • Cleaner privilege boundaries: keep repo access + keys on the backend side; UI talks over localhost + token (local-only by default).

Goals

  • Preserve the existing local backend mode (current behavior) as the default.
  • Allow running the backend in another process/environment (e.g. WSL2) while the UI stays native.
  • Keep the UI event stream and IPC surface stable.

Non-goals (initially)

  • Solving path translation for every edge case.
  • Supporting cross-machine networking by default.
  • Large UX redesign.

Proposed direction

Add an optional daemon that:

  • Runs locally (bind 127.0.0.1) and requires a token.
  • Exposes the same high-level operations as the current backend (list_workspaces, connect_workspace, send_user_message, approvals, terminal PTY, etc.).
  • Streams the same event payloads the UI already expects (e.g. app-server-event, terminal-output).

UI would gain a backend selector:

  • Local (current)
  • Remote (daemon) with URL + token

Incremental PR plan (no behavior change by default)

I'm proposing to split this into small PRs to reduce risk and improve acceptance.

PR1 (UI-only refactor, no-op)

  • Introduce a src/services/events.ts module to centralize event subscriptions.
  • Update hooks to use it (useAppServerEvents, useTerminalSession, etc.).
  • No change in event names/payloads.

PR2 (Rust refactor, no-op)

  • Separate backend "core" logic from Tauri glue to make it reusable.
  • Keep the same #[tauri::command] surface and emitted events.

PR3 (optional daemon)

  • Add a new binary (feature-gated if needed) that exposes a local-only API and event stream.

PR4 (remote backend mode)

  • Add settings + connection logic.
  • Keep default behavior unchanged.

PR5 (docs + CI)

  • Document Windows+WSL flow.
  • Ensure builds stay reasonable (feature flags, separate workflows).

Open questions / feedback wanted

  • Preferred transport: WebSocket JSON-RPC vs REST+WS events?
  • Where should the remote backend config live (app settings vs per-workspace)?
  • How to handle file picker + image attachments in remote mode (WSL paths vs upload bytes)?
  • Would maintainers accept the daemon as optional/feature-gated?

If this direction sounds acceptable, I'm happy to start with PR1 immediately (pure refactor) and keep everything else behind explicit opt-in settings.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions