-
Notifications
You must be signed in to change notification settings - Fork 775
Description
Related: #192
Summary
T3 Code should support running its backend outside the local desktop environment through a first-class BackendTarget model, instead of treating WSL or other remote environments as shell/path special cases.
The most immediate use case is Windows + WSL, but the same architecture would also make future remote targets possible (for example SSH or other Linux hosts).
The core idea is:
- keep the desktop UI local
- run the backend natively in the selected target environment
- let the desktop process resolve, start, supervise, and reconnect that backend
- keep the renderer connected through one stable desktop-provided endpoint
- expose target capabilities to the UI instead of scattering target-specific checks everywhere
Why this matters
WSL support is deceptively hard to get right if it is approached as a subprocess or path-conversion problem.
A naive implementation usually turns into some combination of:
- spawning
wsl.exead hoc - translating paths back and forth in multiple places
- letting the renderer infer execution context indirectly
- mixing Windows desktop concerns with Linux runtime concerns
That tends to become brittle around:
- terminal behavior
- Git/toolchain behavior
- cwd semantics
- Linux-native workspace paths
- reconnect/restart handling
- version compatibility
- network transport differences
- desktop integrations like folder selection or opening files in an editor
If T3 Code wants WSL to feel reliable and native, WSL should be modeled as a real backend target, not as a compatibility mode.
Why this is also a general remote-backend issue
After looking at T3 Code’s current structure, VS Code’s remote architecture, the public Remote - WSL package, code-server, devcontainers/cli, and WSL docs, the pattern is pretty consistent:
- the client UI stays local
- the backend runs natively in the target environment
- transport is a separate concern
- startup is deterministic
- auth and version compatibility are explicit
- target capabilities are modeled directly
That is useful for WSL, but it also sets up a clean path for future remote targets.
So this issue is intentionally broader than “add WSL support”: it is proposing the abstraction that would make WSL the first clean implementation.
Current T3 Code shape
T3 Code already seems close to supporting this architecture:
- the desktop app starts the backend process in
apps/desktop/src/main.ts - the renderer already depends on a desktop-provided WebSocket URL through the desktop bridge
- the backend is already separated enough from the UI boundary that target-aware startup could live mostly on the desktop side
That suggests this can be introduced as a lifecycle/target refactor, not as a frontend rewrite.
Proposal
1. Introduce an explicit backend target model
Something like:
localwsl:autowsl:<distro>
Longer term this could also support:
ssh:<host>- other remote Linux targets
2. Move backend lifecycle behind a desktop-side controller
Instead of assuming one local child process forever, the desktop app should own a target-aware controller responsible for:
- resolving the target
- selecting the distro/host
- bootstrapping the backend
- readiness detection
- reconnect/restart policy
- surfacing errors and diagnostics
- exposing target metadata/capabilities to the renderer
3. Run the backend natively in the target
In WSL mode, the backend should run inside the selected distro, not on Windows.
That preserves the right semantics for:
- Linux paths
- shell/cwd behavior
- Git
- package managers
- local toolchains
- terminal sessions
4. Keep one stable renderer-facing connection contract
The renderer should not need to know if the backend is local, in WSL, or elsewhere.
It should keep consuming:
- one desktop-provided connection endpoint
- one set of target metadata/capabilities
5. Expose capabilities instead of adding isWsl checks
For example:
requiresLinuxWorkspacePathssupportsNativeFolderPickersupportsDesktopEditorBridgesupportsTargetBootstrapsupportsReconnect
This keeps UI logic from becoming target-specific over time.
6. Keep desktop-only integrations on the desktop side
Especially in WSL mode:
- folder picking should not blindly inject Windows paths into a Linux backend
- opening files in an external editor should remain desktop-owned
- path translation should happen only at explicit boundaries, not throughout core runtime logic
7. Keep backend startup deterministic
Startup should not depend on interactive shell init files or user shell customization.
That is one of the clearest lessons from the mature remote tooling already out there.
Why WSL should be the first target
WSL is the most practical first implementation because it exercises the exact boundaries that a general remote architecture needs:
- different runtime OS from the desktop app
- different filesystem semantics
- different path formats
- different shell/toolchain environment
- target-local backend process
- desktop-local UI integrations
- transport/reconnect concerns
If the abstraction works for WSL, it is much more likely to scale to future remote targets cleanly.
Sources that support this direction
VS Code / Remote WSL
VS Code’s public OSS and distributed Remote - WSL package strongly suggest the following model:
- WSL is treated as a real remote authority / target identity
- the client resolves that target on the desktop side
- a Linux-native server is started in WSL
- the client connects through a stable resolved endpoint
- startup is kept deterministic
Relevant references:
- VS Code remote authority infrastructure:
src/vs/platform/remote/common/remoteAuthorityResolver.tssrc/vs/platform/remote/electron-browser/remoteAuthorityResolverService.ts
- WSL detection in core:
src/vs/platform/remote/node/wsl.ts
- Windows shell handoff:
resources/win32/bin/code.sh
- WSL sanity tests:
test/sanity/src/wsl.test.ts
Public docs / package-level references:
- https://code.visualstudio.com/api/advanced-topics/remote-extensions
- https://code.visualstudio.com/docs/remote/troubleshooting
- https://github.com/microsoft/vscode-remote-release
WSL platform docs
WSL networking and behavior vary depending on configuration, which is a strong argument for an explicit target/transport layer rather than assumptions baked into the renderer:
- https://learn.microsoft.com/en-us/windows/wsl/networking
- https://learn.microsoft.com/en-us/windows/wsl/wsl-config
Other relevant open-source references
code-server is useful as a reference for remote server concerns such as auth, transport, and reverse-proxy assumptions:
devcontainers/cli is useful as a reference for separating target bootstrap, environment resolution, and runtime lifecycle:
WezTerm is a useful reference for modeling WSL as a first-class domain/target rather than a subprocess trick:
- https://wezterm.org/config/lua/config/default_domain.html
- https://wezterm.org/config/lua/config/wsl_domains.html
Suggested implementation order
- Introduce
BackendTarget - Introduce a desktop
BackendController - Wrap current behavior as
LocalBackendTarget - Add
WslBackendTarget - Expose target metadata/capabilities through the desktop bridge
- Make renderer behavior capability-driven
- Add WSL-aware workspace selection and editor-open flows
- Add Windows + WSL integration tests
Expected outcome
This would give T3 Code:
- a clean way to support WSL on Windows
- a better separation between UI, transport, and backend runtime
- a path toward future remote backends without redoing the architecture later
I’m opening this as an architecture proposal rather than a PR because the main value here is agreeing on the model before implementation.