Skip to content
randomness.hr
ToyEnglishWIP
  • Updated
  • rust
  • typescript
  • react
  • tauri
  • tmux
  • claude-code

Fleet

Supervise and steer every Claude Code session, on every machine, from one place — a Rust CLI, a phone-first web app and a macOS app over Tailscale.

Fleet web UI on a desktop: session list on the left, the selected session's chat on the right

Ten agents on two machines and one of me. Which one needs me right now? Where is it running? What is it actually doing? I got tired of cycling through tmux panes and iTerm tabs to find out, so I built Fleet.

Fleet finds every live Claude Code session — straight from Claude Code’s own registry in ~/.claude/sessions/, whether it runs in a tmux pane or an iTerm tab — and shows its status (busy · waiting · idle), context %, model, host and working directory. From there I can peek, steer, rename, spawn and hand work off. From a terminal, a browser, my phone or a Mac app.

One core, four front-ends

  • Rust core library — discovery, tmux and iTerm backends, naming, briefs, grouping, and dispatch to other hosts over ssh.
  • CLI and TUI — bare fleet is a live ratatui dashboard that notifies me when a session finishes or gets stuck; fleet list -a --json asks every host in parallel and returns one array.
  • Web server — zero-dependency Node, one per machine. It serves its own sessions and merges its peers’, so any URL shows the whole fleet.
  • React PWA — keyboard-first on the desktop, a home-screen app on the phone.
  • Fleet.app — a Tauri 2 shell around the same UI: system WebKit, ~10 MB, traffic lights sitting over the UI’s top bar. crates/fleet-desktop/bundle.sh --install builds it.
Fleet running as a native macOS window: session list on the left, a chat on the right
Fleet.app: the web UI in a native macOS window

The setup it’s built for

An always-on Mac — the workstation — runs Claude Code inside tmux, 24/7. The laptop and phone reach it over Tailscale, so closing the lid never interrupts an agent.

The CLI dispatches by re-running itself: ssh <host> fleet <same args>, with ControlMaster multiplexing so it stays fast. The web servers talk plain HTTP to each other and merge session lists. Each machine has one small JSON config written by fleet init; fleet install --host workstation copies everything over and fleet doctor checks both ends. There’s no authentication in the web app — it’s meant for the tailnet only.

Fleet web UI in a browser with sessions from the laptop and the workstation in one list
Every session, every host, one page

Board and smart grouping

An AI pass (claude -p with haiku, only for sessions it hasn’t placed yet) sorts sessions into work streams on a Kanban board. I can rename groups, drag sessions between them and reorder columns; clicking a card opens the session as a resizable flyout. Without the model it falls back to one group per repository.

Kanban board with columns per work stream and an open session flyout with its brief
Sessions from two hosts grouped into work streams

Session briefs

A handover note that writes itself: a summary, resources pulled from the transcript (branch, PRs, issues, files, links) and todos from TodoWrite. I can edit it by hand, and my edits win. “Continue in new session” seeds a fresh session with the brief (fleet spawn --from, fleet brief). It’s one haiku call, gated — only after a session is idle for 60 s, and at most 12 calls an hour.

Details panel with a summary, a todo list with three of five done, git branch, pull request, issue and links
Details panel with a session brief

Steering from anywhere

The chat view reads the transcript, with skills, shell commands and pasted text rendered as blocks. Messages go out with a 3-second undo window. Quick replies and keys (Continue, Yes, 1, Esc, Enter, ↑ ↓) are one tap away. Files attach by drag, paste or paperclip and upload to the session’s host. Paths Claude mentions become links with an in-app preview for markdown, code, images and PDFs. A Chat | Term toggle shows the live tmux pane. New sessions start on any host with a model picker, and every session keeps its own draft.

A reply to Claude's question with a "Sending in 2s" countdown and an Undo button
Send with a 3-second undo window
Raw terminal output of a Claude Code session running tests
The live tmux pane when you need the raw screen

Phone

Safari → Add to Home Screen. Swipe down for filters, up for quick replies, right to go back. On the phone the board becomes a grouped list.

Fleet on a phone: list of sessions with host badges and statusA session on a phone waiting on a question, with quick-reply buttons above the input
Session list and a session waiting on a question, on the phone

Desktop polish

⌘K opens a palette for any session on any host, plus actions. Every shortcut is ⌘/Ctrl + key: ⌘? lists them, ⌘⌫ closes a session (press twice), ⌘Enter starts a new one. There are three themes — Default, Earth and Dusk — and a UI-wide text size. Each session has one title: Claude’s /rename is the source of truth and the tmux name follows as a slug, with opt-in auto titles. And a notes explorer: point web.notes.root at a markdown folder to browse, search, follow [[wiki]] links and “Send to session”.

Command palette filtering sessions from both hosts and matching notes
⌘K: jump to any session on any host
Notes explorer with a file list and a rendered runbook
Markdown notes next to the sessions

Status

Actively developed. macOS only for now (iTerm support is macOS-only anyway). MIT licensed, with portions derived from productiveio/cli-toolbox. The repo has the details: setup, architecture, CLI and desktop app.