docs/adr/0010-desktop-window.md

ADR 0010: Desktop Window Reuses the Mobile App

  • Status: Accepted (owner-decided)
  • Date: 2026-07-08

Context

VUH-644 asks what the desktop window is before implementation starts. There were three candidate shapes:

OptionShapeTrade-off
TUI is the desktop storyKeep clankie dev and the pi-tui face as the only desktop experience.Cheapest and already present, but it is a console on the host, not a window. It has no remote reach and none of the garden.
Thin shell mirrorPackage a Tauri-style desktop shell that speaks the same relay WebSocket contract as iOS, scoped to chat, roster, pane read/steer, and mirror.Reuses the relay and clankie-contract, but creates a third client surface if the UI is fresh and excludes the garden from v1.
Full RN reuse with gardenBuild a desktop shell around the existing React Native/Expo mobile app so desktop has the same layout and features as the iPad app, including the garden.Highest validation risk, but it keeps the product surface unified and avoids a reduced desktop client.

The actually-new desktop capability is remote reach from a window: the app can connect to a Herdr session on the same device or another device over the tailnet, using the same relay WebSocket and shared wire schemas that the iOS app uses today. A fresh desktop-only client would add a third maintenance surface for roster, chat, pane control, terminal mirror/native attach, session selection, garden actions, and future command surfaces.

Clanky-Hosted (M3) pushes in the same direction. A hosted brain makes a browser or desktop window the natural first client for non-Mac users, but it should not fork the product into "mobile app", "desktop app", and "hosted web app" feature sets. The desktop/web runtime should be another target for the same client surface, not a separate reduced experience.

Decision

The desktop window reuses the existing React Native/Expo mobile app (@clankie/mobile in the private Volpestyle/clankies repo) with full feature parity, including the garden. The owner direction is settled: desktop should present the "same layout and features as our iPad app" and connect to any Herdr session on the device or on other devices through local and tailnet reach.

Desktop does not get a fresh mirror-only UI. It uses the same relay WebSocket model and the same shared schemas in clankie-contract (@volpestyle/clankie-contract, the relay contract referred to as @clankie/contract in VUH-644) that the private iOS app already consumes.

flowchart LR
  shared["React Native / Expo app<br/>@clankie/mobile"]
  ios["iPhone + iPad target"]
  shell["Desktop shell target<br/>Tauri, Electron, or RN macOS"]
  relay["Clankie relay WS<br/>@volpestyle/clankie-contract"]
  sessions["Herdr sessions<br/>local device + tailnet devices"]
  garden["Garden<br/>@shopify/react-native-skia"]

  shared --> ios
  shared --> shell
  shared --> garden
  ios <-->|pairing + relay ops| relay
  shell <-->|pairing + relay ops| relay
  relay <-->|session-scoped ops| sessions

The shell choice remains an implementation question, not a product-scope question:

  • Tauri + React Native Web is the first candidate because it keeps a small desktop shell while preserving a web-shaped target that can also serve hosted browser use.
  • Electron + React Native Web remains a fallback if WebKit/runtime packaging, native module loading, or devtools needs make it materially cheaper.
  • React Native macOS remains a possible native target, but it is less useful for hosted/browser reach and may increase platform-specific code.

The first validation spike is @shopify/react-native-skia on web via CanvasKit. The garden is a first-class feature, so desktop scope is not accepted until that path proves that the garden can render and interact correctly in the selected web/desktop runtime. If CanvasKit is not viable, the decision remains full feature parity, but the shell/runtime choice must change before implementation continues.

Desktop implementation is deferred until the iOS BYO-onboarding lane (T4.1) proves the pairing, relay URL/token, session selection, and onboarding shape that desktop inherits.

Consequences

  • Desktop and iPad share one product surface. New roster, chat, pane, terminal, garden, stats, and command features land in the shared RN app instead of being reimplemented in a separate desktop UI.
  • Desktop reaches local and remote Herdr sessions through the relay contract, not by opening arbitrary Herdr sockets directly. The relay remains the auth, session-selection, and wire-compatibility boundary.
  • The garden remains in desktop v1. Implementation must budget for Skia/CanvasKit validation, performance profiling, asset loading, input handling, and packaging.
  • M3 hosted work can reuse the RN-web target rather than creating another hosted client surface, provided the selected runtime keeps browser deployment viable.
  • The desktop shell stays a host for the shared app. Shell code owns packaging, window lifecycle, native menus, notifications, deep links, secure storage, and OS integration; product behavior stays in the shared client and relay contract.

V1 Exclusions

  • Desktop v1 is not "the TUI plus docs." The TUI remains useful, but it is not the desktop window product.
  • Desktop v1 is not a mirror-only shell that omits the garden.
  • Desktop v1 does not introduce a new desktop-only control protocol or bypass the relay WebSocket / clankie-contract model.
  • Desktop v1 does not create a fresh desktop UI that must chase iOS/iPad feature parity by hand.
  • Desktop v1 does not ship before T4.1 proves the BYO onboarding and pairing shape it inherits.
  • Desktop v1 does not promise arbitrary public-internet reach; remote access follows the established local and tailnet relay model.

References