Skip to content

feat: add WSL/Linux terminal window launching support#649

Open
rexsilex wants to merge 1 commit intoiloom-ai:mainfrom
rexsilex:feat/wsl-linux-terminal-support
Open

feat: add WSL/Linux terminal window launching support#649
rexsilex wants to merge 1 commit intoiloom-ai:mainfrom
rexsilex:feat/wsl-linux-terminal-support

Conversation

@rexsilex
Copy link
Copy Markdown

Add platform-specific terminal backends for WSL (Windows Terminal) and native Linux (gnome-terminal, konsole, xterm) alongside the existing macOS backend. Extract terminal logic into backend modules while keeping the public API unchanged.

Key changes:

  • Add platform-detect.ts for WSL/Linux environment detection
  • Add terminal-backends/ with darwin, wsl, linux backends and factory
  • Refactor terminal.ts to delegate to platform-specific backends
  • Fix E2BIG on Linux by externalising large CLI args to temp files
  • Fix race condition: write loom metadata before opening terminal tabs
  • Fix empty error messages in Claude CLI error handling
  • Update TerminalColorManager with WSL-aware messaging

WIP: Terminal tabs open and Claude launches, but behavior still being refined for full end-to-end WSL support.

Add platform-specific terminal backends for WSL (Windows Terminal) and
native Linux (gnome-terminal, konsole, xterm) alongside the existing
macOS backend. Extract terminal logic into backend modules while keeping
the public API unchanged.

Key changes:
- Add platform-detect.ts for WSL/Linux environment detection
- Add terminal-backends/ with darwin, wsl, linux backends and factory
- Refactor terminal.ts to delegate to platform-specific backends
- Fix E2BIG on Linux by externalising large CLI args to temp files
- Fix race condition: write loom metadata before opening terminal tabs
- Fix empty error messages in Claude CLI error handling
- Update TerminalColorManager with WSL-aware messaging

WIP: Terminal tabs open and Claude launches, but behavior still being
refined for full end-to-end WSL support.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@acreeger
Copy link
Copy Markdown
Collaborator

Thanks for this PR, @rexsilex! Great work on the terminal backend architecture — the strategy pattern with platform-specific backends is clean and well-tested. The E2BIG fix and race condition fix are solid additions too.

I ran a code review and found a few issues, which I've gone ahead and fixed in follow-up commits on this branch:

Issues Found & Fixed

Bug (High): Empty command produces shell syntax error on Linux

In linux.ts, when buildCommandSequence({}) returns a single space " ", the keep-alive construction produces " ; exec bash", which is a bash syntax error:

$ bash -lic ' ; exec bash'
bash: syntax error near unexpected token `;'

Fix: Trimmed the buildCommandSequence result and added an empty-string guard in both openSingle and openGnomeTerminalMultiTab, so an empty command produces just exec bash.

Bug (Medium): bash -c vs bash -lic inconsistency in gnome-terminal multi-tab

The single-tab path in execTerminal correctly uses bash -lic (login/interactive shell, loads profile scripts), but openGnomeTerminalMultiTab used bash -c. This means multi-tab launches on gnome-terminal wouldn't load .bashrc/.bash_profile, so tools like nvm, asdf, rvm etc. wouldn't be available.

Fix: Changed to bash -lic for consistency.

Security (Medium): Temp files written with default permissions

The externalizeIfNeeded function in claude.ts writes sensitive data (system prompts, MCP configs, agent configs) to temp files with default permissions. On Linux/WSL with a common umask of 022, these files would be world-readable (644). On shared multi-user systems (common in WSL enterprise setups), other local users could read these files.

Fix: Added mode: 0o700 for temp directories and mode: 0o600 for temp files.

Additional Notes (not fixed, low priority)

  • escapeForBashC in wsl.ts is exported and tested but never called — consider removing or adding a comment about intended future use
  • buildTerminalAppScript in darwin.ts duplicates command-building logic instead of using shared buildCommandSequence — potential refactor opportunity
  • Duplicate detectITerm2 functions exist (async in terminal.ts vs sync in darwin backend)

acreeger added a commit that referenced this pull request Mar 1, 2026
* feat: add Linux, WSL, and tmux terminal backends

Refactor terminal launching into pluggable backends using a strategy
pattern, enabling cross-platform support. The public API (openTerminalWindow,
openMultipleTerminalWindows) is unchanged — backends are selected
automatically based on the detected platform.

Backends:
- darwin: Refactored existing macOS code (Terminal.app + iTerm2)
- linux: GUI terminals (gnome-terminal, konsole, xterm)
- wsl: Windows Terminal via wt.exe
- tmux: Headless fallback for SSH, Docker, Code Server, CI

On Linux, the factory tries GUI terminals first, then falls back to
tmux automatically when no GUI is available. This unblocks `il start`
on headless Linux environments where the previous "not yet supported"
error made iloom unusable.

Fixes gnome-terminal multi-tab by using sequential openSingle calls
(gnome-terminal --tab adds to the focused window) instead of a single
invocation where `--` terminates all option parsing.

Based on the architecture from #649 by @rexsilex. Resolves #795.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: check DISPLAY before GUI terminals and keep tmux sessions alive

Skip GUI terminal detection on Linux when no display server (X11/Wayland)
is available — prevents crashes like konsole SIGABRT in headless
environments (SSH, Docker, Code Server).

Add `; exec bash` keep-alive to tmux backend so sessions persist after
the command exits, matching the Linux GUI backend pattern.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: deduplicate darwin command-building and platform detection

Address code review feedback (PR #796):

1. darwin.ts buildTerminalAppScript now delegates to the shared
   buildCommandSequence instead of reimplementing the same logic.
   Removes unused escapeSingleQuotes and buildEnvSourceCommands imports.

2. terminal.ts detectITerm2 now delegates to darwin.ts's canonical
   implementation instead of duplicating the existsSync check.

3. terminal.ts detectPlatform now delegates to detectTerminalEnvironment
   from platform-detect.ts, eliminating the duplicate platform detection
   logic. Maps 'wsl' → 'linux' to preserve the Platform return type.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address review feedback — session naming, WSL keep-alive, catch blocks, N+1 detection

1. [Critical] Tmux openSingle() sessions now use iloom- prefix so
   findIloomSession() can discover them, matching openMultiple() behavior.

2. [Critical] WSL backend appends '; exec bash' keep-alive to prevent
   terminal tabs from closing when the command exits.

3. [Medium] Narrowed bare catch blocks in isTmuxAvailable, sessionExists,
   findIloomSession, and detectLinuxTerminal to check for exitCode before
   swallowing — unexpected errors now propagate instead of being silently
   ignored. Test mocks updated to include exitCode matching real execa
   behavior.

4. [Medium] LinuxBackend.openMultiple() now calls execTerminal() directly
   with the pre-detected terminal instead of delegating to openSingle(),
   eliminating redundant detectLinuxTerminal() calls per window.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: ENOENT-specific catch in WSL detection, DRY linux backend, update README platform support

- platform-detect: check for ENOENT specifically instead of bare catch
- linux backend: extract resolveTerminal() and openSingleWithTerminal() to
  eliminate duplicated detection/command-building between openSingle/openMultiple
- README: update OS support line to reflect Linux/WSL/tmux support, credit
  @TickTockBent and @rexsilex in Acknowledgments

* docs: add Windows/WSL setup guide and update README platform support

- New docs/windows-wsl-guide.md with full WSL setup, VS Code integration,
  Windows Terminal usage, and troubleshooting
- Link from README system requirements to the WSL guide

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Adam Creeger <adamcreeger@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

2 participants