Windows Tauri desktop client for the qq agent server, with worktree sessions and goals
Discovered from README cross-links · today
Built a native Windows desktop app that shares sessions with the qq TUI and CLI.
What they did
The author built a Windows desktop app for qq in `apps/desktop/`, stacked on an engine-prerequisites branch (#313) and documented in ADR-0065. The app is a Tauri v2 shell with a native Rust client core and a React + TypeScript + Tailwind UI. Rather than reimplementing protocol logic, it is a client of the same user-scoped server the TUI and CLI use, so sessions, configuration and credentials are shared across surfaces. Engine supervision attaches to a server found by `qq_server::discover`, or starts `qq serve --exit-on-stdin-close` and holds its stdin; a stale discovery record no longer blocks startup because the instance lock decides. The client core runs one actor per open project around `qq_client::TuiClient` and the `qq-client::state` reducer (the TUI's own code paths), pushing coalesced view models to the webview at most every 33 ms, with bounded command queues and drafts kept until the server acknowledges them. View-model types are generated from `view.rs` with ts-rs, and a test fails when `src/lib/generated.ts` drifts. On top of that they built the agent-facing UI: sessions grouped Needs you / Working / Recent with search, rename/archive/delete, child sessions and opt-in Windows notifications; a virtualized transcript with streamed markdown, reasoning, folded tool-call summaries, diffs and run summaries with Retry; inline approval cards for shell, edit, fetch and `ask_user`; a composer with `@` file picking backed by the TUI's `complete_paths`, `/` command and skill completion, queue/steer/interrupt, model and approval pickers and a context ring; `/btw` side questions that never enter the run; a Changes panel; a git strip showing branch, ahead/behind and PR via `gh`, with commit/push/PR actions behind confirmations; worktree sessions giving each task its own `git worktree` and branch; open-in-editor for VS Code, Cursor, Windsurf and Zed; and durable goals matching the TUI's `/goal`, with revision-checked `SetGoal`/`GoalControl`, command-exact check consent and budget presets. They also handled window chrome and settings (custom title bar, command palette, themed dropdowns, theme/text size/notifications, connection and MCP diagnostics, remembered geometry, reduced-motion-aware entrance), sign-in (API keys for Anthropic, OpenAI, Google and xAI, browser sign-in for ChatGPT and xAI, stored as `qq auth login` stores them, with providers read from the engine's table per ADR-0064), the ADR-0042 project-trust prompt calling `grant_pending_trust`, and packaging via `pnpm bundle` into a Tauri sidecar plus a per-user NSIS installer. `apps/desktop/src-tauri` is its own Cargo workspace with its own lockfile so engine CI never builds Tauri/WebKitGTK, and a separate `Desktop` GitHub Actions workflow on `windows-latest` runs the app's checks.
How it went
Verified on Windows 11: `pnpm typecheck`, 32 frontend tests, `pnpm check:version` and `pnpm build` pass; `cargo fmt --check`, clippy with `-D warnings` and 31 Rust tests pass, covering goal budgets, stale-revision refusal, git status/commit, worktree create/remove against throwaway repos, editor path containment and the generated-types contract. Live checks against throwaway projects covered engine start/exit, sign-in, trust prompts, streaming, approvals, pickers, side questions, git status, worktree create/open/remove, open-in-editor, and a release build whose NSIS installer carries `qq.exe`. The goal panel was exercised in a browser render fixture but not yet against a live goal run.
Worth knowing
Windows only so far, and the installer is unsigned (signing needs a certificate; the procedure is documented). Single host: no multi-server view or pairing. No image input, since protocol input parts reject images today. Undo of a run waits on proposed run snapshots rather than a desktop-only `git reset`. MCP servers are shown but not editable; config changes still go through `config.ron` and trust. Session rename/archive is local to the desktop because there is no server-side rename yet, and shell edits are not tracked in the Changes panel. The PR is stacked on #313 and retargets to `main` once that merges.
Wiring
Order: engine prerequisites (#313) first, then the desktop app on top. `apps/desktop/src-tauri` is a standalone Cargo workspace with its own lockfile; the root `Cargo.toml`/`Cargo.lock` stay untouched so engine CI never builds Tauri/WebKitGTK. The Rust core depends on `qq_server::discover`, `qq serve --exit-on-stdin-close` (stdin held for lifetime), `qq_client::TuiClient` and `qq-client::state`; it exposes view models to the React webview over Tauri IPC, with types generated from `view.rs` by ts-rs (test-only dependency) and a drift test on `src/lib/generated.ts`. Git and `gh` are invoked without a shell, prompts disabled, with deadlines and one mutating action at a time; worktrees live in `<repo>.worktrees/<branch>`. Editors are resolved from `PATH` with paths contained to the project. Sign-in writes credentials the same way `qq auth login` does, with providers from the engine's built-in table (ADR-0064); trust calls `grant_pending_trust` like `qq trust`. `pnpm bundle` builds the release engine as a Tauri sidecar and a per-user NSIS installer. CI: `.github/workflows/desktop.yml` on `windows-latest` runs `pnpm typecheck`, `pnpm test`, `pnpm check:version`, `pnpm build`, `cargo fmt --check`, `cargo clippy --locked --all-targets -- -D warnings` and `cargo test --locked`.
Try it yourself
Read ADR-0065 and `docs/plans/desktop-production-readiness.md` in this repo, then scaffold `apps/desktop/` as a Tauri v2 app with a Rust client core and a React + TypeScript + Tailwind UI. Make it a client of the existing user-scoped server: attach to the instance `qq_server::discover` finds, or start `qq serve --exit-on-stdin-close` and hold its stdin, letting the instance lock decide when a discovery record is stale. Run one actor per open project around `qq_client::TuiClient` and the `qq-client::state` reducer, push coalesced view models to the webview at most every 33 ms, and keep all protocol logic out of TypeScript. Generate the view-model types from `view.rs` with ts-rs and add a test that fails when `src/lib/generated.ts` drifts. Keep `apps/desktop/src-tauri` as its own Cargo workspace with its own lockfile so the root engine CI never builds Tauri, and add a separate `Desktop` workflow on `windows-latest`. Then build the session list, virtualized transcript, inline approval cards, `@`/`/` composer, `/btw` side questions, Changes panel, git strip with `gh`, worktree sessions, open-in-editor, goals panel with revision-checked controls, sign-in, project trust and the NSIS installer via `pnpm bundle`.