Skip to content

feat(desktop): Windows build with PowerShell and Git Bash terminal integration - #8696

Open
Thewookie-Eng wants to merge 6 commits into
simstudioai:stagingfrom
Thewookie-Eng:feat/desktop-windows
Open

Thewookie-Eng wants to merge 6 commits into
simstudioai:stagingfrom
Thewookie-Eng:feat/desktop-windows

Conversation

@Thewookie-Eng

@Thewookie-Eng Thewookie-Eng commented Oct 6, 2026 •

Copy link
Copy Markdown

Summary

Builds and runs the desktop shell on Windows alongside macOS, with a working agent terminal.

The shell was already a thin Electron wrapper with most platform-specific code behind process.platform guards, so the port is small. Three commits, each reviewable on its own:

  1. feat(desktop): add Windows packaging and runtime support
    • Per-arch @lydell/node-pty-* packages move to optionalDependencies (plus win32-x64/win32-arm64). electron-builder's bun dependency walk fails on a missing regular dependency but skips a missing optional one, so this is what lets one package.json package both platforms.
    • scripts/ensure-pty-prebuilds.ts picks the arch list from the host platform; the Windows addon is conpty.node, not pty.node.
    • electron-builder.yml gains win (nsis + zip, x64 + arm64) and nsis sections; scripts/build.ts emits build/generated-icon.png from the same 1024px logo the macOS .icon bundle uses.
    • The terminal launches pwsh → powershell.exe → COMSPEC on Windows instead of $SHELL, without the POSIX -l flag. macOS-only hide menu roles are gated (they render as blank rows on Windows); setAppUserModelId is set per channel.
  2. feat(desktop): shell integration for PowerShell and Git Bash on Windows
    • PowerShell gets the same OSC 633 markers as zsh/bash: prompt reports cwd, previous exit code and prompt start; PSConsoleHostReadLine reports the command line and its start. This is the arrangement Windows Terminal and VS Code use. Without it the agent was refused with NO_SHELL_INTEGRATION.
    • The hooks travel as -EncodedCommand: dot-sourcing a file is blocked by the default execution policy on Windows clients, and lowering it for the shell would loosen it for everything the user runs there.
    • ReadLine is called with two arguments only. In PSReadLine 2.0 (Windows PowerShell 5.1) the third parameter is a CancellationToken; a bool coerces to a cancelled one and the prompt loops.
    • Git for Windows' bash is offered through a Windows-only Terminal Shell app-menu submenu when Git is installed (Git's install paths only — System32\bash.exe is the WSL launcher). The existing bash hooks work there; cygpath -w translates the reported cwd. Persisted as terminalShell.
    • The marker parser now unescapes \\ so Windows paths survive the hooks' escaping; tmux probing is skipped on Windows; detectShell recognises .exe names on any host.
  3. test(desktop): make the unit suite pass on a Windows host — 15 tests skipped on win32 (11 build fixtures with symlink(), which needs Developer Mode or elevation; 4 assert POSIX mode bits), 3 path expectations go through path.join/basename, and the microphone-settings ipc test now expects the Windows ms-settings: URL the handler has always had. No change on macOS.

Not in scope, documented in the README as Windows parity gaps: auto-update (initUpdater stays a no-op off macOS), Help-menu docs search, Chrome cookie/password import, Terminal.app/iTerm2 theme import, and code signing (unsigned builds trigger SmartScreen; CSC_LINK/CSC_KEY_PASSWORD work as on macOS). CI is unchanged — desktop-release.yml still builds macOS only; a Windows job can follow if this is wanted.

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation
  • Other: ___________

Testing

On Windows 11 (10.0.26300), Bun 1.4.2, Node 24, no C++ toolchain:

  • bun run package:win:dir and bun run package:win produce release/win-unpacked/Sim.exe and Sim-<version>-x64.exe (NSIS). The packaged app launches, loads the hosted origin, and completes the system-browser sign-in handoff (handoff_redeem_ok in the event log).

  • Shell integration was exercised under a real ConPTY with the production launch args and parser, for both shells:

    Windows PowerShell 5.1 (PSReadLine 2.0) Git Bash
    integration live 549 ms 608 ms
    E command-line markers all commands, verbatim ✓
    D exit codes 0, 0, 3, 3 ✓
    P cwd after cd C:\Windows C:\Windows (via cygpath)
    OSC leaking to display none none
  • apps/desktop: type-check, lint:check clean; bun run test 72/72 files, 860 passed, 16 skipped on this host.

  • macOS: not re-verified by me — the mac packaging config is untouched apart from the optionalDependencies move, and ensure-pty-prebuilds.ts keeps the same two darwin arches. A maintainer running bun run package:dir on a Mac once would be the one thing worth confirming.

Reviewers may want to focus on: the optionalDependencies move (any effect on the universal build's x64ArchFiles handling), the PowerShell script in shell-integration.ts, and whether a native app-menu submenu is the right surface for the shell choice versus a web-app setting through desktop-bridge.

Known limitation: when a PowerShell cmdlet fails (as opposed to a native program), the reported exit code can be a stale $LASTEXITCODE. VS Code has the same behaviour.

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

Screenshots/Videos

n/a — no UI changes to the web app; the only new UI is a native Windows app-menu submenu (Terminal Shell → PowerShell / Git Bash).

🤖 Generated with Claude Code

Thewookie-Eng and others added 3 commits October 6, 2026 14:34
Build the Electron shell on Windows alongside macOS:

- Per-arch @lydell/node-pty packages become optionalDependencies, with
  win32-x64 and win32-arm64 added. electron-builder's bun dependency walk
  fails on a missing regular dependency but skips a missing optional one.
- scripts/ensure-pty-prebuilds.ts picks the arch list from the host
  platform and checks for conpty.node on Windows.
- electron-builder.yml gains win (nsis + zip, x64 + arm64) and nsis
  sections; scripts/build.ts emits build/generated-icon.png for the .ico.
- The agent terminal launches pwsh, then powershell, then COMSPEC on
  Windows instead of $SHELL, without the POSIX -l flag.
- macOS-only hide menu roles are gated; setAppUserModelId is set per
  channel on Windows.
- README documents the Windows build and its parity gaps (no
  auto-update, no Help search, no Chrome import, uninstrumented
  PowerShell).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The agent terminal was refused with NO_SHELL_INTEGRATION on Windows
because prompt hooks existed only for zsh and bash. PowerShell now gets
the same OSC 633 markers: `prompt` reports the directory, previous exit
code and prompt start, and `PSConsoleHostReadLine` reports each command
line and its start, as Windows Terminal and VS Code do. The hooks travel
as -EncodedCommand because dot-sourcing a file is blocked by the default
execution policy on Windows clients, and ReadLine is called with two
arguments only: PSReadLine 2.0's third parameter is a CancellationToken,
and a bool coerces to a cancelled one, which made the prompt loop.

Git for Windows' bash is offered through a Windows-only Terminal Shell
submenu when Git is installed; the existing bash hooks work there, with
cygpath translating the reported directory to a Windows path. The choice
persists as `terminalShell` in settings.

Also: the marker parser unescapes `\\` so Windows paths survive the
hooks' escaping, tab titles split on either separator, tmux probing is
skipped on Windows, and detectShell recognises `.exe` names on any host.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The desktop suite is run by CI on macOS, where it passes; on Windows 19
tests failed for reasons in the host rather than the code under test.

- 15 tests are skipped on win32: eleven build their fixture with
  symlink(), which Windows refuses without Developer Mode or elevation,
  and four assert POSIX mode bits (0o600/0o700) that Windows does not
  have.
- Three path expectations were hard-coded with `/`; they now go through
  path.join or basename, matching the implementation.
- The microphone-settings ipc test expected a settings pane only on
  macOS, but the handler has carried a Windows ms-settings URL since it
  was written.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@Thewookie-Eng
Thewookie-Eng requested a review from a team as a code owner October 6, 2026 21:35
@vercel

vercel Bot commented Oct 6, 2026

Copy link
Copy Markdown

@Thewookie-Eng is attempting to deploy a commit to the Sim Team on Vercel.

A member of the Team first needs to authorize it.

@greptile-apps

greptile-apps Bot commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 4/5

[High risk] Adds Windows build and terminal support to desktop app.

The PR appears safe to merge, with a non-blocking concern about overly broad Windows test skips.

Findings

  1. P2 Windows skips portable checks ▶

Summary

Adds Windows desktop packaging, PowerShell shell integration, and a saved Git Bash choice in the native menu.

  • Prepares Windows PTY binaries and adds NSIS and ZIP targets.
  • Decodes escaped Windows paths and skips tmux probes on Windows.
  • One non-blocking concern: several Windows test skips also remove portable checks.

Acknowledged limitations from Thewookie-Eng: stale $LASTEXITCODE after failed PowerShell cmdlets; Windows auto-update, Help-menu search, browser import, terminal-theme import, signing, and release CI are intentionally outside scope. Windows cross-builds from macOS/Linux are unsupported.

Diagram
%%{init: {'theme': 'neutral'}}%%
flowchart TD
  Settings[Saved shell choice] --> Choice{Windows shell}
  Choice -->|Default| PowerShell[PowerShell]
  Choice -->|Git installed| Bash[Git Bash]
  PowerShell --> Hooks[Command and directory markers]
  Bash --> Hooks
  Hooks --> Parser[ShellIntegrationParser]
  Parser --> Session[TerminalSession state and results]
Loading

Reviews (1) · Last reviewed commit: "test(desktop): make the unit suite pass ..."

Comment thread apps/desktop/src/main/desktop-chat-session-store.test.ts Outdated
Thewookie-Eng and others added 3 commits October 6, 2026 14:44
Three of the win32 skips covered more than the platform-specific check.
The encryption assertions, the unknown-mount, directory, size-limit and
missing-path checks are now their own tests that run everywhere; only
the symlink fixtures and the POSIX mode-bit assertion stay skipped.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant