Skip to content

Cross-platform support: target macOS and Linux #32

Description

@AThraen

Goal

Ship CodeShellManager on Windows, macOS, and Linux from a single codebase while preserving the current feature set (multi-PTY tabbed/grid layout, FTS5 search, alert detection, git integration, session persistence, sleep/wake, SSH remote sessions).

Three Windows-only pillars to replace

  1. WPF → Avalonia 11 — the entire UI layer
  2. ConPTY P/Invoke → Pty.NetTerminal/PseudoTerminal.cs
  3. WebView2 → cross-platform terminal host — biggest unknown, needs a spike

The MVVM layer (MainViewModel, SessionViewModel) and most services (SessionManager, StateService, SearchService, ColorService, GitService, AlertDetector, OutputIndexer, AlertDetector) should port largely unchanged — they don't depend on WPF or Win32 types.

Strategy by layer

UI: WPF → Avalonia

  • Avalonia 11 uses similar XAML + MVVM, though its dialect differs (no WPF Triggers, Styles work differently, Border vs Border are mostly congruent).
  • Files to port: MainWindow.xaml/.cs, Views/NewSessionDialog.xaml/.cs, Views/SettingsWindow.xaml/.cs.
  • Heavy lift: MainWindow.xaml.cs has substantial imperative code-behind (sidebar building, layout switching, drag-reorder, search panel, dormant entries). Most of it is platform-agnostic logic that just calls into WPF visuals — port is largely mechanical.
  • Catppuccin hex literals carry over as-is (just SolidColorBrush declarations).
  • TrayIcon is built into Avalonia — replaces the current Windows tray helper.
  • INotifyPropertyChanged + ObservableCollection<T> work identically in Avalonia.

PTY: ConPTY → Pty.Net

  • Microsoft's Pty.Net wraps ConPTY on Windows and forkpty on Mac/Linux behind a single API.
  • Replace the body of Terminal/PseudoTerminal.cs; keep the public surface stable so TerminalBridge and OutputIndexer don't change.
  • SSH support already works cross-platform — system ssh is the PTY command, nothing else to change there.
  • Default shell selection needs platform branching: cmd/pwsh on Windows, $SHELL (fallback bash/zsh) on Unix.

Terminal host: WebView2 → ?

This is the riskiest part. Three candidate paths:

Option Pros Cons
Avalonia.WebView (per-platform native web views: WebView2 / WKWebView / WebKitGTK) Reuses existing Assets/terminal.html + xterm.js with minimal changes Per-platform behavior differs; transparency/font rendering may not match across all 3
Photino.NET Lighter, well-maintained, embedded native web runtime Less Avalonia integration; would need a custom host
Native terminal control (port/integrate a managed xterm equivalent) No web stack Major undertaking; loses existing xterm.js investment

Recommended: spike Avalonia.WebView first, fall back to Photino if blocking issues surface.

Smaller cross-platform concerns

  • Default shells: detect from $SHELL; sensible per-OS fallbacks.
  • State path: %AppData% / ~/Library/Application Support / ~/.config via Environment.SpecialFolder.ApplicationData — already works.
  • SQLite: Microsoft.Data.Sqlite is already cross-platform ✓.
  • Windows Terminal profile import: gate behind OperatingSystem.IsWindows() — feature is Windows-specific by nature.
  • Keyboard shortcuts: Avalonia's KeyGesture handles Ctrl ↔ Cmd mapping; revisit Ctrl+T/Ctrl+W/Ctrl+F to use Meta on macOS.
  • Font fallback chain: Cascadia Code → Menlo (macOS) → DejaVu Sans Mono (Linux) → generic monospace.
  • Crash log path: already uses SpecialFolder — should work unchanged.
  • Tray icon parity: Linux tray support varies by desktop environment (GNOME requires extensions). Treat as best-effort.

Packaging & distribution

  • Windows: keep existing signed MSI + winget pipeline (.github/workflows/winget.yml).
  • macOS: .app bundle → .dmg. Requires Apple Developer cert + notarization. Distribute via Homebrew Cask.
  • Linux: AppImage (universal) as default; consider Flathub for desktop integration; .deb / .rpm optional.

CI/CD changes

  • .github/workflows/build.yml: matrix over windows-latest / macos-latest / ubuntu-latest.
  • macOS notarization step (needs APPLE_ID, APPLE_APP_PASSWORD, APPLE_TEAM_ID secrets).
  • AppImage build step on Linux.
  • New Homebrew tap workflow on release: released event.
  • winget.yml unchanged (Windows-only path).

Suggested phases

  1. Spike (~1–2 weeks) — prove the three risky pieces in isolation: Avalonia + Pty.Net + Avalonia.WebView running xterm.js with a trivial PTY echo on all 3 OSes. No feature parity, just "does the stack work."
  2. Avalonia port on Windows (~3–4 weeks) — full feature parity, still Windows-only build target. Validates the rewrite doesn't lose anything before adding OS surface area.
  3. macOS (~1–2 weeks) — cross-build, manual smoke test, signing + notarization, tray icon, fonts, shortcuts.
  4. Linux (~1–2 weeks) — same, plus a distro test matrix (Ubuntu, Fedora, Arch).
  5. CI/CD + packaging (~1 week) — multi-OS matrix, installers, release automation.

Risks

  • WebView2 replacement — biggest unknown. If Avalonia.WebView falls short on perf/transparency/fonts, terminal UX may regress.
  • ConPTY ↔ forkpty behavior gaps — some edge cases (resize signals, mouse modes, signals like SIGWINCH) may behave subtly differently.
  • macOS notarization — first-time setup is tedious; can stall a release.
  • Linux tray — GNOME parity is poor without user-installed extensions.
  • MainWindow.xaml.cs volume — port is mostly mechanical but there's a lot of code; risk of subtle regressions in sidebar/layout/drag-reorder logic.

Out of scope (for this issue)

  • Mobile (iOS/Android).
  • Web/cloud deployment.
  • Rewriting search, alert, or persistence subsystems — they should port unchanged.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    on holdParked deliberately; not abandoned. See latest comment for resumption state.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions