Skip to Content
PlatformsWindows

Windows support

FrankenTUI treats Windows as a first-class CI target but not yet as a first-class native runtime target. Today that means every test in the workspace is expected to pass on windows-latest, color and input work on Windows Terminal, and a dedicated native backend is on the roadmap behind the Unix v1 milestone. The canonical status document is docs/WINDOWS.md; this page summarizes it and points to the governing ADRs.

The short version: it runs, it tests green in CI, and the native backend crate (ftui-win32, tentative) is deliberately deferred until the Unix backend API is frozen. See ADR-008 for why.

CI validation status

Last validated: 2026-02-03 (bead bd-31go).

PlatformRunnerToolchainStatus
Linuxubuntu-lateststable, nightlyValidated
macOSmacos-lateststable, nightlyValidated
Windowswindows-lateststableValidated

The matrix lives in .github/workflows/ci.yml. Every PR runs:

  • cargo fmt --check, cargo clippy -- -D warnings, cargo build on all three.
  • Full unit-test sweep on all three.
  • #[cfg(target_os = "windows")] capability-detection tests (notably Windows-Terminal detection via WT_SESSION).
  • Platform-independent golden snapshot tests.
  • PTY-based E2E tests on Linux/macOS only (see scripts/cross_platform_e2e.sh). A Windows-native PTY path is part of the deferred work below.

What works on Windows today (v1 target)

  • Raw-mode enter/exit with best-effort cleanup on panic.
  • Basic key input (letters, arrows, modifiers).
  • Resize events where the backend surfaces them.
  • Mouse input via SGR encoding where the terminal supports it.
  • Color:
    • 16-color baseline everywhere.
    • 256-color on Windows Terminal and modern ConHost.
    • TrueColor on Windows Terminal.

Known limitations on Windows (v1)

  • DEC synchronized output (mode 2026): not widely supported. Flicker-free mode falls back to scroll-region batching.
  • OSC 8 hyperlinks: Windows Terminal only; cmd.exe and legacy ConHost skip them silently.
  • Bracketed paste: varies by emulator.
  • Focus events: unreliable in some terminals; treat them as advisory.
  • Kitty keyboard protocol: limited/absent.
  • DECSTBM scroll region: behavior varies by emulator; the renderer sniffs and downgrades.
  • Mouse SGR: may fall back to legacy encoding on older paths.

Terminal compatibility matrix

FeatureWindows Terminalcmd.exeConHostPowerShell
TrueColorYesNoPartialDepends
OSC 8 LinksYesNoNoPartial
Mouse (SGR)YesNoPartialPartial
Sync Output (DEC 2026)NoNoNoNo

The recommendation is simple: prefer Windows Terminal, use a Unicode-capable font (Cascadia Mono, JetBrains Mono, Fira Code), and let the capability detector do the downgrades.

The v1 scope decision — ADR-004

ADR-004 fixes two things:

  1. Windows stays in CI. No feature lands that cannot compile and test green on windows-latest.
  2. No Windows-specific runtime code ships in v1. That means no ftui-win32 crate yet, no Windows-only dependencies in core, and no feature flags gated on #[cfg(windows)] in widget or runtime code.

This is deliberately conservative. The alternative — sprinkling crossterm and Win32 API calls throughout core — made the TTY backend seam much harder to reason about and meant every Unix-side refactor had to dual-verify on Windows. Keeping a hard line at “everything in core is portable” has kept the codebase honest.

The terminal backend strategy — ADR-008

ADR-008 generalizes the lesson: platform specifics go behind ftui-backend, not inside the crates that consume it. That is already how ftui-tty and ftui-web coexist; a future Windows-native crate slots into the same seam.

Deferred: the native backend plan

docs/WINDOWS.md Section “Deferred Native Backend Strategy” (bead bd-lff4p.4.9) lays out the staged plan for a native Windows backend. It starts after the Unix backend API is frozen.

PhaseGoalPrimary dependenciesNotes
0 (current)Keep Windows CI green while Unix evolvesExisting workspace depsNo new Windows-only runtime dep
1Backend crate skeleton + RAII lifecyclewindows-sys / windows for console mode + handlesMirrors TerminalSession cleanup
2Input parity (key/mouse/resize/focus)Win32 console input records + ConPTY probesNormalize into ftui_core::event::Event
3Output + capability parityVT-enablement APIs, mode toggles, synchronized flushingPreserves the one-writer rule
4Validation + hardeningWindows CI + deterministic E2E fixturesTerminal-specific paths (WT + ConHost)

Scope boundaries, restated from the doc:

  • Windows work must not block the web renderer/input path, the WASM showcase, or the remote PTY bridge.
  • Unix-first milestones stay priority. The Windows crate work starts only when:
    1. Unix backend API stabilizes,
    2. parity tests for core lifecycle pass consistently,
    3. existing CI is green.

The practical implication: if you are reading this and wondering why there is no ftui-win32 source yet, that is the reason. The seam is ready; the crate waits its turn.

Risk register (Windows-specific)

  • Capability fragmentation — Windows Terminal vs ConHost vs cmd.exe. Mitigation: capability-driven branches, strict downgrade paths, no assuming Windows means any one of the three.
  • Input encoding — modifiers, IME, surrogate pairs all behave differently across console APIs. Mitigation: explicit normalization tests on each.
  • Cleanup on abrupt exit — RAII is load-bearing. Mitigation: Windows cleanup tests that mirror the Unix panic-path tests.

The broader FrankenTerm architecture document (docs/spec/frankenterm-architecture.md) has a Windows section that outlines how a future browser-backed terminal experience also satisfies the “Windows works” promise without needing a native backend at all. Users on Windows today who run the WASM showcase are effectively using that path already.

Pitfalls

  • Do not import windows-sys from core. Every such import is a reviewer “no.” Platform deps live in the backend crate, full stop.
  • Do not assume cmd.exe behavior represents “Windows”. Windows Terminal is the target emulator for v1.
  • Do not disable tests on Windows “because they flake.” File the issue, tag it windows, and keep the test green. Silent disabling has bitten us before.
  • Do not gate features on #[cfg(windows)] in portable crates. Gate them on a BackendFeatures bit instead and let the backend answer.

See also