Background
The Windows desktop build now compiles (Wails v2.15, wails build -platform windows/amd64). Besides the known sandbox difference (Windows runs under
sandboxlocal with no OS-level isolation like seatbelt/bwrap), the current
code has the following platform differences between Windows and macOS.
Recording them here for future alignment.
Differences
1. Interactive terminal sessions (PTY) unavailable
- flowcraft's
sandbox/session_other.go (//go:build !unix) returns
NotAvailable directly: Windows has no pty, process groups, or signal
delivery.
- As a result, execd does not advertise the
pty capability
(internal/execd/server.go Capabilities); on Windows commands run through
pipes only, with no TTY interactive sessions.
- Expectation: define an explicit degradation path in the short term; evaluate
ConPTY later (suggested as a separate follow-up issue).
2. execd graceful shutdown degrades
stop() in internal/execd/fork.go first sends SIGTERM and waits for a
graceful exit; Windows os.Process.Signal only supports Kill, so SIGTERM is
ignored and the child is force-killed after 3 seconds.
- Result: in-process session cleanup does not run (the socket is removed by
the parent, so functionality is unaffected, but cleanup semantics differ
from Unix).
3. Parent-death watchdog never fires
watchParent in execd_main.go relies on Unix reparenting: after the parent
dies, os.Getppid() changes. On Windows, Getppid reads ParentProcessID
from the process entry, which does not change after the parent exits, so the
watchdog never triggers.
- Result: after a parent crash, the execd child can leak (on Unix it exits on
its own).
- Suggestion: use a Job Object on Windows, or poll for parent liveness, to
replace this mechanism.
4. Desktop window chrome
- macOS: hidden inset title bar + traffic-light alignment + disabled scroll
elasticity (mac_window_darwin.go).
- Windows: standard title bar (
mac_window_other.go no-op). Cosmetic only; no
functional impact.
5. Builtin plugin directory layout
- macOS:
.app/Contents/Resources/plugins; Windows/Linux: plugins/ next to
the executable (BuiltinPluginRoot in internal/plugins/runtime/runtime.go).
6. Plugin binary signing
- macOS ad-hoc codesigns plugin binaries (
signAdHoc in
internal/plugins/plugin.go); no-op on Windows.
7. Open file/directory command
open (macOS) vs cmd /c start (Windows) (openCommand in
internal/desktop/bindings.go).
8. Rendering engine
- macOS uses WKWebView (WebKit); Windows uses WebView2 (Chromium). Same React
frontend, but minor differences in fonts, scrolling, and compatibility
behavior.
9. Paths
- Data dir is
~/.opencraft on both (i.e. C:\Users\<user>\.opencraft on
Windows).
- The execd socket lives under the user cache dir:
~/Library/Caches on
macOS, %LocalAppData% on Windows.
10. Shell reported by execd
internal/execd/server.go hardcodes "Shell": "/bin/sh", which is
inaccurate on Windows. It is currently just an informational field (actual
execution is decided by the agent), so impact is low; suggest returning
cmd.exe / powershell.exe per platform.
Suggestions
- Add a Job Object or parent-liveness detection for execd on Windows to restore
graceful shutdown and crash cleanup.
- Return the Shell field per platform.
- Evaluate ConPTY support for interactive sessions (suggested as a separate
follow-up issue).
Background
The Windows desktop build now compiles (Wails v2.15,
wails build -platform windows/amd64). Besides the known sandbox difference (Windows runs undersandboxlocalwith no OS-level isolation like seatbelt/bwrap), the currentcode has the following platform differences between Windows and macOS.
Recording them here for future alignment.
Differences
1. Interactive terminal sessions (PTY) unavailable
sandbox/session_other.go(//go:build !unix) returnsNotAvailabledirectly: Windows has no pty, process groups, or signaldelivery.
ptycapability(
internal/execd/server.goCapabilities); on Windows commands run throughpipes only, with no TTY interactive sessions.
ConPTY later (suggested as a separate follow-up issue).
2. execd graceful shutdown degrades
stop()ininternal/execd/fork.gofirst sends SIGTERM and waits for agraceful exit; Windows
os.Process.Signalonly supports Kill, so SIGTERM isignored and the child is force-killed after 3 seconds.
the parent, so functionality is unaffected, but cleanup semantics differ
from Unix).
3. Parent-death watchdog never fires
watchParentinexecd_main.gorelies on Unix reparenting: after the parentdies,
os.Getppid()changes. On Windows,Getppidreads ParentProcessIDfrom the process entry, which does not change after the parent exits, so the
watchdog never triggers.
its own).
replace this mechanism.
4. Desktop window chrome
elasticity (
mac_window_darwin.go).mac_window_other.gono-op). Cosmetic only; nofunctional impact.
5. Builtin plugin directory layout
.app/Contents/Resources/plugins; Windows/Linux:plugins/next tothe executable (
BuiltinPluginRootininternal/plugins/runtime/runtime.go).6. Plugin binary signing
signAdHocininternal/plugins/plugin.go); no-op on Windows.7. Open file/directory command
open(macOS) vscmd /c start(Windows) (openCommandininternal/desktop/bindings.go).8. Rendering engine
frontend, but minor differences in fonts, scrolling, and compatibility
behavior.
9. Paths
~/.opencrafton both (i.e.C:\Users\<user>\.opencraftonWindows).
~/Library/CachesonmacOS,
%LocalAppData%on Windows.10. Shell reported by execd
internal/execd/server.gohardcodes"Shell": "/bin/sh", which isinaccurate on Windows. It is currently just an informational field (actual
execution is decided by the agent), so impact is low; suggest returning
cmd.exe/powershell.exeper platform.Suggestions
graceful shutdown and crash cleanup.
follow-up issue).