Files
orca/docs/reference/cross-platform-support.md
T

3.4 KiB

Cross-Platform Support

Orca targets macOS, Linux, and Windows. Keep all platform-dependent behavior behind runtime checks:

  • Keyboard shortcuts: Never hardcode e.metaKey. Use a platform check (navigator.userAgent.includes('Mac')) to pick metaKey on Mac and ctrlKey on Linux/Windows. Electron menu accelerators should use CmdOrCtrl.
  • Shortcut labels in UI: Display ⌘ / ⇧ on Mac and Ctrl+ / Shift+ on other platforms.
  • File paths: Use path.join or Electron/Node path utilities — never assume / or \.
  • Windows terminal shells: --shell picks the shell a terminal is; --command is typed into whatever shell the host spawned, so a shell choice routed through command silently becomes a child process.
  • Windows setup scripts: the setup/issue-command runner is a .cmd batch file unless the script starts with a #! line — never derive that from the user's terminal-shell preference, and never launch a .cmd runner with a bare cmd.exe /c from a Git Bash pane (MSYS rewrites the /c).
  • Windows child processes: start them through runProcess/spawnProcess from @orca/process-host — never child_process directly. It pins windowsHide, refuses shell: true, and encodes .cmd/.bat arguments so neither CommandLineToArgvW nor cmd.exe mangles them. Recognised npm/pnpm .cmd shims are resolved to their real target so the spawn skips cmd.exe entirely.
  • Ripgrep: Orca bundles rg for every platform, WSL, and SSH remotes. Spawn it through spawnBundledRipgrep (main) or resolveRelayRipgrepCommand (relay), never a bare 'rg' — Windows resolves a bare name in the spawn cwd before PATH. Don't add git/readdir fallbacks locally; the relay's chain exists only for hosts an upload never reached.
  • Windows process enumeration: read the table through src/main/windows/windows-process-table.ts, never by forking powershell.exe.
  • Windows MSYS/Git Bash panes: their children break away from the per-PTY job unless it is created without JOB_OBJECT_LIMIT_BREAKAWAY_OK, and a conpty.node built before that fix passes every existing gate.
  • Windows daemon-host relocation: the terminal daemon runs from a copy of the app runtime under %LOCALAPPDATA%, which is what survives an auto-update.
  • macOS daemon launch: packaged macOS runs the terminal daemon from a copy of the signed terminal host helper through launchd, so an update cannot sever its privacy grants. Before touching that copy, its cleanup, or the fork fallback, read macos-daemon-tcc-attribution.md.
  • Windows EDR signal: don't add -ExecutionPolicy Bypass, -EncodedCommand, cmd.exe /c with escaped free text, per-operation interpreter spawning, or runtime Add-Type compilation without reviewing the EDR impact first — behavioural EDR scores each of those, and being signed does not clear them.
  • WSL commands: build argv with buildWslExecArgs (always --exec — under --, wsl.exe expands $name in every argument and silently rewrites the script), and fence anything whose stdout you parse with buildWslCapturedLoginShellCommand, because the interactive login shell prints the distro banner to stdout.
  • Linux native modules: keep the glibc floor at Ubuntu 20.04 / glibc 2.31. A module compiled from source on a newer runner can reference symbol versions absent on the floor and crash the app on startup. Packaging fails if a bundled native binary needs newer glibc.