Feedback widget — visitor reports become fleet work
One script tag puts a feedback button on any site you run. Visitors point at the exact element that's broken; reports land in a per-project inbox.
One click dispatches an agent to fix a report — with an optional instruction of yours prepended to the prompt.
Remote control without deploys: pause, resume, rotate, or revoke the widget from FleetCrown and the customer site follows within seconds. Live status comes from a real heartbeat, not install intent.
Install and uninstall are one click too: an agent adds or removes the embed in your repo and ships it through your normal review flow.
At volume, Synthesize clusters new reports into structured briefs, and a daily digest files themes as draft actions on Approvals — nothing executes without your approval.
The loop closes itself: when a dispatched fix deploys, the report auto-resolves and the visitor who left an email hears their feedback shipped.
P3 terminal interactive parity. A non-durable rawkey/resize event rides the existing bridge NOTIFY → SSE channel (no per-keystroke DB rows, no command-claim); the runner dispatches it to writeRawKey/resizePty, writing bytes verbatim into the agent's owned PTY. Strictly additive and independent of the autopilot command-drain path. Verified end-to-end: typed in the browser terminal, echoed from a runner-owned PTY with no zellij dependency; killing an agent leaves the runner green (PTY isolation confirmed). Linux (AppImage + .deb).
The "My machine" terminal is now fully interactive — char-level keystrokes, Ctrl-C / Tab / arrows, and live resize — at parity with the server terminal.
Reliability: the wait=0 command poll had no request timeout, so a connection left half-open by a backend restart could hang the poll forever — the poller went silent, the process stayed alive (so nothing restarted it), and the autopilot loop stalled. Bounded the poll with AbortSignal.timeout(20s); on timeout it backs off and retries instead of hanging. Pairs with the supervised systemd service (Restart=always) for end-to-end 'never silently offline'.
The runner no longer goes silently offline after the dashboard restarts (e.g. during a deploy). The command poll now has a hard timeout, so a half-open connection can't wedge the loop with the app still running.
Injection fix. Claude's TUI treats a big multi-line write as a bracketed paste and absorbs a trailing carriage return into the paste buffer instead of submitting — so the prompt sat in the input unsent and every dispatch reported “the agent didn't pick up the prompt within the window.” Fixed by sending the submit Enter as a separate keystroke after the paste settles (two nudged CRs at 250ms/800ms). Found by driving kivvi end-to-end and reading the live PTY.
Dispatched and next-best prompts now actually submit. Large multi-line prompts were being pasted into the agent's input but never sent (stuck as “[Pasted text +N lines]”), so the agent looked launched but never started working.
Reliability release for the autopilot loop. Three root causes of the 'nothing works' freeze: (1) the live-terminal peek ran a synchronous zellij dump-screen that blocked the runner's single event loop and starved command acks → every command was re-served forever; fixed by streaming only owned PTYs (async, in-memory). (2) the status push had no request timeout → one hung request killed the heartbeat. (3) runtime state was only pushed every 5 min → launched agents took minutes to appear; now pushed immediately after each command.
Autopilot is reliable now: the runner no longer freezes after a terminal peek, so dispatched and next-best prompts keep flowing instead of silently queueing forever.
Newly launched agents appear in the dashboard and the live terminal within a second, instead of after a 5-minute heartbeat.
The status heartbeat can no longer get stuck on a slow request, so the dashboard stops showing stale state.
Makes the owned-PTY execution from 0.8.2 the default (set FLEETCROWN_RUNNER_PTY=false to force Zellij). This removes the structural cause of the launch timeouts: launching no longer depends on an attached Zellij client.
Agents now run in a terminal Fleet Runner owns by default — no more dispatch/launch timeouts when your Zellij session isn't attached (the recurring "spawnSync /bin/sh ETIMEDOUT").
If an owned-terminal launch ever fails, it falls back to Zellij automatically, so launching can't dead-end.
Watch any agent live from the web app in full color with scrollback.
First step of moving agent execution off Zellij name-puppeting onto FleetCrown-owned PTYs (docs/architecture/agent-execution-platform.md). Ships node-pty in the runner (load-verified in the packaged build) but stays behind a flag so this release behaves exactly like 0.8.1 until you opt a project in.
Fleet Runner can now run each agent in a terminal it owns directly, instead of driving your Zellij by name — which is what made dispatch into some projects time out when the session wasn't attached.
Watch any owned-terminal agent live from the web app, in full color with scrollback (a true byte stream, not a once-a-second screenshot).
Opt-in for now: set FLEETCROWN_RUNNER_PTY=true to switch a project's agents to owned terminals; everything else keeps using Zellij until you flip it.
The reliability release for the dispatch loop (Control → your local Zellij). Pairs with the web app's new Terminal tab, real Activity timeline, sidebar Light/Dark/Auto switch, and the dark-first Geist redesign deployed on fleetcrown.orangecat.ch.
Reliable dispatch: a single verified command ensures the project's Zellij tab, launches the agent if none is running, injects the prompt, and confirms the agent picked it up — instead of silently typing into a closed or wrong tab.
Fuzzy tab matching: project keys now resolve to the tab names you actually use, so "revampit" finds your "revamp-it" tab (case + hyphens + spaces no longer matter).
Detached-session launches now fail with a clear "zellij attach <session>" instruction instead of a cryptic spawn timeout; stale commands queued while the runner was offline are purged instead of failing noisily on reconnect.
Self-healing bridge connection so the runner stops getting stuck "offline", and an honest offline state when a dispatch can't reach your machine.
Auto-update enabled: future Fleet Runner fixes download in place — no more manual reinstalls.
Mostly a web UI + API release — deploys immediately on fleetcrown.orangecat.ch. Fleet Runner v0.8.0 picks up the improved remote switch_agent poller when you next update the desktop app; until then, cloud-queued switches still work on the existing runner.
One-click agent switching from the project card chip or Cmd+K — quits the live CLI and launches the new agent without typing /quit in the terminal.
Rate-limit and quota banners on project cards offer a single "Switch to …" button with automatic fallback order (Claude → Cursor → Codex → Gemini → Grok).
Agent label mismatch warnings when the UI preference disagrees with the live process scan, so "Claude" no longer silently shows while Codex is running.
Switch-agent commands now scan /proc and quit every running agent in the project directory before launching the replacement.
Closes the last dogfood gap found while testing production Control against the local Zellij workspace: queued focus commands were claimed but could appear to land on the wrong tab without useful logs.
Remote focus-tab commands now use the same Zellij adapter path as Peek/injection, including focus confirmation.
Desktop command handling now logs handled/rejected command IDs, making remote-control failures debuggable from systemd logs.
Completes the v0.7.7 Control-state fix by making the desktop app report the same installed tools the user's terminal can actually run.
Agent availability detection now searches common user CLI install locations, including nvm Node bins and `~/.local/bin`, instead of trusting Electron's reduced PATH.
Fixes false 'Missing local tools' banners when Claude, Gemini, Codex, Cursor, or Grok are installed and work in the terminal.
Fixes the UI drift where Fleet Runner showed open workspaces but each project still said 'No live observation'. The pusher now sends the same rich runtime snapshot the server route already knew how to store.
Runtime heartbeats now push per-project session and process state, not just the list of open Zellij tabs.
The Control UI can show last done, next step, session health, current prompt, and active agent state after a refresh even if no new handoff event fired.
Project-to-tab matching now tolerates punctuation and case differences such as `revampit` versus `revamp-it`.
Fixes the dogfood gap where the cloud UI looked connected but only `truthseeker` appeared and most remote actions were rejected by the desktop poller. This release makes the web app and phone UI a real controller for the local Zellij workspace.
Fleet Runner now drains the full remote-control command set from the hosted web app: launch agent, focus tab, close tab, switch agent, install CLI, auto-continue, and prompt injection.
Local project import now writes and repairs the canonical `dirPath`, so imported repositories actually appear in /control and can launch agents.
The desktop command boundary has regression coverage for every supported queued command type.
Permanent fix for the .deb auto-update problem the user surfaced on 2026-06-07: they installed v0.7.0, received zero update notifications across 4 shipped releases (v0.7.1-v0.7.4), and didn't know they were stale. The auto-updater was downloading the new .debs but couldn't apply them — Linux dpkg requires sudo and Electron can't escalate. Now even when auto-apply fails, the user always sees what to do.
In-app update banner — when a newer version is detected, /control shows the exact upgrade path with a one-click Copy button.
On .deb installs (Linux), the banner shows the `sudo dpkg -i <path>` command since electron-updater can't escalate sudo. No more silent update failures.
On AppImage/dmg/exe, the banner has a 'Restart to install' button that triggers electron-updater's quitAndInstall directly.
Banner is dismissable per-version (sessionStorage) so it doesn't nag, but re-appears on the next release.
Architectural cleanup. The bundled renderer was an aspirational 'local-first' surface that never reached parity with /control. Deleting it (2,135 lines) puts Fleet Runner in the same category as Slack / Linear / Notion desktop: web UI + native integrations (tray, deep-link auth, IPC for Peek + auto-mint + local-dev-scan, auto-update).
Removed the bundled local renderer entirely — Fleet Runner is now a clean Electron wrapper around the cloud /control UI.
Fixes the v0.7.0 boot disaster where users saw a half-working stub with 'YOUR MACHINES. YOUR AGENTS.' and zero projects.
Smaller binary, no dependency on `agent-projects.conf` local file, no parallel-UI drift risk.
Splash → web shell transition is the only boot path; clean offline page if cloud is unreachable.
Fixes a real bug where a revoked token would lock the user permanently offline — auto-mint's 'if existing token, bail' guard kept reusing the dead one. Now the runner deletes bad tokens on 401, and the next /control load mints a fresh one from the signed-in browser session.
Clear stale auth tokens automatically when the server rejects them (401/403).
Renamed window title from 'Cockpit Fleet Runner' (legacy pre-rename) to 'Fleet Runner'.
Pusher and poller now signal token-invalid back to the auto-mint flow, so a dead token recovers without user intervention.
Closes the biggest visibility gap in /control: you could see tab names and state chips but had to alt-tab into Zellij to see what an agent was actually saying. Peek brings the agent's view into FleetCrown itself.
Peek tab feature — eye-icon button on /control's workspaces table opens a drawer showing the live screen contents of any Zellij tab.
Sub-200ms round-trip per peek; auto-refresh toggle re-snapshots every 3s for watching long-running agents.
Emergency revert. v0.7.0 shipped the bundled renderer as the default boot target before it had parity with /control, which produced the 'YOUR MACHINES. YOUR AGENTS. / 0 projects / Sync error: Failed to fetch' screen. v0.7.4 later deletes the bundled renderer entirely; v0.7.1 was the safe rollback to v0.6 behavior in the meantime.
Reverted the v0.7.0 'bundled-renderer-as-primary' boot flip.
Fleet Runner opens fleetcrown.orangecat.ch inside Electron again — the same UI you know from the browser.
Updated download CTA on the marketing site to point at the latest release dynamically.
Major v0.6 → v0.7 cut. Several real features landed (autopilot, typed boundary, scheduler) but the Phase C 'make the bundled renderer the primary' change went out before parity work was done. v0.7.1 reverted that part; v0.7.4 deleted the bundled renderer for good.
Per-project autopilot mode override (UI toggle on each ProjectCard).
Typed command boundary at the desktop runtime (zod-validated commands from cloud).
Autonomous scheduler that nudges idle projects when no human dispatch happens.
Beacon /tmp/*.json migrated to the cloud DB for cross-device visibility.
Breaking
Bundled renderer became the default boot target — produced a broken UX, reverted in v0.7.1, removed entirely in v0.7.4.
The architectural foundation for everything that came after. Pre-v0.6, /control polled /api/control every 30s and the daemon-offline indicator was always lying about staleness. v0.6 inverts the dataflow: clients subscribe to an SSE stream, the bridge LISTENs on Postgres NOTIFY events, every row change fans out to connected clients within milliseconds.
Real-time updates via Postgres LISTEN/NOTIFY + SSE bridge — replaces the v0.5 30-second polling.
Sub-second latency from DB row change → browser UI update.
Bridge server runs on bridge.orangecat.ch (Hetzner CX22), reachable from desktop + web + mobile.
Runner pusher is event-driven (worker.idle from session.md changes) instead of pure heartbeat.