One reliable control plane for every Claude Code session on your machine. Run more than two or three Claude Code sessions and you lose track of them: which terminal is which, which one is blocked on a permission prompt, and which two are editing the same file.
> /plugin marketplace add lacion/fleet-deck> /plugin install fleetdeck@fleetdeck
Repo: lacion/fleet-deck
What's inside
One reliable control plane for every Claude Code session on your machine.
Run more than two or three Claude Code sessions and you lose track of them: which terminal is which, which one is blocked on a permission prompt, and which two are editing the same file. Fleet Deck puts all of them on one local board at http://127.0.0.1:4711, with a callsign, a live status column, and a mailbox each.
Fleet Deck is deliberately an accessory, never a dependency of the developer loop. If its daemon, board, network, or hooks are unhealthy, Claude Code must remain usable from the terminal. That rule is the reliability boundary every feature below is built around.
queued → working → verifying → needs-you → idle → offline, computed from hook telemetry. The model badge is read from the session transcript, so it follows a mid-session /model switch instead of freezing on whatever the session launched with.⎿ Allowed by PermissionRequest hook and continues. Outlast the default 10-minute answer window and the question re-arms: a fresh card (badged RE-ARMED) whose answer is sent as a message, delivered at the next turn boundary — it cannot unblock an agent parked on its own prompt, and never pretends to. Ordinary terminal sessions use Claude's native prompts by default.assign auto: fix the flaky test picks a candidate — idle first, least buried, right repo — with a SQL query. The core makes zero model calls.+ Spawn starts a fresh interactive claude in a daemon-owned tmux window. Watch it on the board, attach to the pane, or kill it.tmux -C attach. No PTY, no native deps. Typing sends real keystrokes to the agent's pane. Shift+Enter inserts a newline rather than submitting — the board is the emulator, so it sends the ESC CR that Claude Code's keybinding expects, with nothing to configure. Ctrl+V pastes a screenshot: the board uploads the image, writes it server-side, and types the path into the composer; you press Enter yourself. (PNG/JPEG/GIF/WebP, ≤10 MB, written owner-only under FLEETDECK_HOME, pruned after 24 h or 50 files.)▦ Terminals opens every live agent at once. All tiles stream; exactly one accepts input — the focused tile wears an amber ring, and every other tile is stdin-disabled at the terminal itself, not filtered on the way out. The grid shares one tmux control client, so the tenth tile costs a WebSocket, not a tenth tmux process.⟲ click resumes a dead agent in its own worktree with full history — same callsign, same card. Whole columns at a time.claude plugin marketplace add lacion/fleet-deck # the repo is its own marketplace
claude plugin install fleetdeck@fleetdeck
Your next claude — any terminal, any repo, no wrapper — brings the fleet up and appears on the board. Type /fleet in any session for a live summary.
How updates actually reach you. Claude Code installs a marketplace plugin by copying it into a versioned local cache, and that cached copy is what runs at every SessionStart — not the repo. Auto-update is off by default for third-party marketplaces, and even with it on, Claude Code only recognizes an update when the plugin's version changes in the manifest. Fleet Deck bumps
versionin.claude-plugin/plugin.jsonand.claude-plugin/marketplace.jsonfor every distributable change for exactly this reason. To pull a new version, runclaude plugin marketplace update fleetdeckandclaude plugin update fleetdeck@fleetdeck(or manage it from/plugin), then start a new session. A push tomainwithout a version bump never reaches an installed copy. If you want releases only, use the npm channel —npm i -g fleetdeckfor standalone mode — or pin your marketplace clone to a tag.
Requirements. Bun 1.3.14+ — the CLI, hook shims, and daemon all run under Bun. A plugin install has no dependency-install step: the daemon ships as one bundled file and keeps state in Bun's built-in bun:sqlite. Add tmux 3.4+ to spawn workers or open their panes in the browser — Fleet Deck relies on 3.4's no-start probe to avoid attaching to a replacement server. Everything else works without tmux. Linux, WSL2 and macOS; Windows-native is untested.
Fleet Deck does not own your Claude Code version. Keep using Claude's normal latest, stable, or exact-version install flow, including upgrades and downgrades. This Fleet Deck release enables its hooks for stable Claude Code 2.1.206 and newer. An older, prerelease, or unidentifiable CLI makes every Fleet Deck hook a silent no-op: Claude starts and behaves normally, with no Fleet Deck warning or injected model context. Newer stable releases stay enabled; Fleet Deck's strict response validation and fail-open launcher prevent an incompatible hook result from interrupting or adding noise to Claude. For a decision hook, the neutral no-op is exactly {} on stdout, empty stderr, and exit code 0; Claude receives no override and continues to its native prompt or normal tool behavior. SessionStart and the background watcher use the equivalent empty-stream exit 0. The machine-readable minimum is compatibility.json.
claude plugin marketplace add /path/to/fleet-deck # a local clone
claude plugin marketplace add your-org/your-fork # or your fork
claude plugin install fleetdeck@fleetdeck
After changing daemon, CLI, hook, or board source, rebuild the matching distributable — the installed plugin and npm package run generated artifacts, not the TypeScript source. The complete command set is in Development. Then restart the daemon, or bump the version and let the verified upgrade handoff do it.
Two traps, both caused by the versioned plugin cache described above:
claude plugin marketplace update fleetdeck and claude plugin update fleetdeck@fleetdeck — and bump the version in both manifests first, or the update is a no-op and you will validate the stale cache.claude --plugin-dir /path/to/fleet-deck. That session's hooks come from your checkout, so what you test is what you just built.claude anywhere. A card appears in about a second.assign auto: add input validation to the signup form. The daemon picks a session and wakes it if idle.permission mode: plan), capture its plan, and execute it later with an unsupervised worker.Tick batch and the prompt box becomes a task list — one agent per line:
fix the flaky worktree test
update the README install section
3x find the race in the spawn path
That is five agents in one click. Each gets its own git worktree (<repo>--fd-<callsign>, or <repo>--fd-<TICKET>-<animal> when the source branch carries a Jira ticket) on its own branch (fd/<callsign> / fd/<TICKET>-<animal>), so they share a repo without standing on each other's edits — isolation is forced for a batch, not offered. The 3x prefix runs a line several times, which is how you race independent attempts at one bug.
Before anything launches the form shows the exact list and count. That preview is the guardrail: there is deliberately no cap on how many agents may be live. It is your machine and your token budget.
terminal 1..n : plain `claude` + this plugin's hooks
│ events (http hooks, fail-open) ▲ whispers, blocks, decisions
▼ │ (hook responses)
fleetd — one Bun daemon, loopback by default, SQLite state
▲ │ WebSocket push
└────────── the board (React) ─────────┘
claude fleet-aware. The first session's SessionStart hook elects and launches the daemon; the port bind is the election. Standalone/Coder installs supervise the same daemon independently of any Claude session.FAQ
fleetdeck is a Claude Code plugin with 1 hand-picked skill for development work, indexed on Flowy. Install it with the command on its page. It includes fleet-doctrine. Its skills do not fire on their own yet. Request auto-invocation to have Flowy route them as you prompt. Free and open source.
Is this plugin yours?
Claim it with GitHubSubmit a pluginPromote it