> fix the failing tests
● Read src/hooks/useAuth.ts
● Bash npm test -- useAuth
2 failed · 18 passed
● Edit src/hooks/useAuth.ts
✓ Fixed the race in useAuth. The effect cleanup ran after setState. 20 passed.
Mass-dispatch dashboard/Windows/v0.2.30
Run six at once and the two that have stopped look identical from across the room: a session that finished its turn prints nothing, and one blocked on a permission prompt prints nothing either. Claude Code sessions tell Dispatch which they are (the count is in the top bar of this page), and you answer them from one list instead of going to find them. What you get back is the gap between a session stopping and you noticing.
Dispatch is a Windows desktop app. Your project terminals in one grid, six agents running at once, and one place to answer them from.
A tile runs whatever you run: Claude Code, Codex, Gemini CLI, or a plain shell.
One command into four repos. Seconds later: one finished, one still working, and two waiting on an answer. The gold pulse is the product: a tile saying it has stopped spending tokens and started spending you. Claude Code in all four tiles here; a tile runs whatever command you point it at.
You have six workspaces open and one session in one of them is sitting on a permission prompt. It prints exactly as much as the one that finished four minutes ago, which is nothing, so finding it costs you six tab switches. Claude Code sessions report which they are. The top bar counts both, and Ctrl+Shift+A opens the list you answer them from.
Dispatch runs a small loopback endpoint and Claude Code posts to it when a turn starts, when it ends, when a permission prompt appears and when a session goes away. So a row that says finished means the turn ended, and one that says waiting on you means there is a dialog on your screen right now. The buttons under it come from reading that screen, and that reading fails closed: where Dispatch can't tell what is being asked you get the rows and no buttons, never a button for a question nobody asked.
Run Codex, Gemini CLI or a plain shell in a tile and you keep the rest of it: the tile goes gold when that command rings the terminal bell, marks itself done and says how long it has been quiet, strikes through when its shell exits, and marks its sidebar row and its workspace tab while you are elsewhere. What it does not do is reach the chip and this list. Those hold only what a session has reported for itself.
A session you are looking at is never in the count, and one drops out the moment you visit it. So the chip reads · all quiet whenever you are on top of things, rather than growing a permanent tally you learn to ignore.
The broadcast bar is one command into many terminals. This is the other half: many different jobs into many terminals. Keep one session as the lead, a tile you talk to rather than work in. Describe your morning to it and it opens the rest, each in the right repo, each with its own prompt already typed. Any agent that speaks MCP can be the lead, and each tile it opens runs the command that project is set to.
“I've got BUG-114 in vantage, BUG-118 in Aura-Tycoon, and two chores in meme-factory. Set them up.”
The command is typed into each shell and left sitting at the cursor. Not run. You read down the row, see exactly what each one is about to do, and press Enter on the ones you agree with. Ask for mode: "fired" when you'd rather they just go. Each tile uses that project's startup command unless the plan names a different one, so the row above is three CLIs because those three repos are set up that way.
You never get half a morning. Every project in a plan is resolved before a single terminal is created, so one it can't find means none of them open and you fix the name once. A name matching two projects comes back as an error listing both rather than a guess. A tile opened in the wrong repo is an agent working confidently on the wrong code.
Tiles land in a new workspace by default; pass workspace: "current" to add them to the one on screen. And when Dispatch isn't running, every tool says so rather than guessing.
dispatch_projectsdispatch_plandispatch_listdispatch_senddispatch_readdispatch_waitdispatch_docdispatch_studiodispatch_rojodispatch_workspacedispatch_closeType in the bar, press Enter, and the command goes to every targeted terminal, the ones whose checkbox is ticked. All and None target everything or nothing; when several groups are open, group chips let you target just one shelf of repos.
Ctrl-C sends an interrupt to every targeted terminal; Clear clears their screens.
Click any single terminal and use it normally. It was never a log pane. It's a full interactive shell.
Auto-discovery groups projects by category. Pin what you're on, hide the noise, and Ctrl+Shift+P fuzzy-opens any of them.
Each workspace remembers its own terminals, columns, tile heights and broadcast targeting, and switching keeps the other workspaces' processes running. Broadcasting only ever hits the active one.
Each workspace scans its own root folder, so one can be your Roblox games directory while the next is your JS/web directory. Pins, hidden projects and recents are shared across all of them, because they're stored by full path.
Right-click a project row or a group header and pick New workspace for this folder. You get a tab named after it with its root already pointed at it. Nothing is opened for you; the tab is just already aimed.
The ─ button drops a tile out of the grid and leaves a card in a bar underneath. The shell keeps running; the card still goes gold when that terminal rings, and strikes through when its process exits.
Two tiles on one repository used to share one checkout, so the session that switched branch moved the other one. Pin a tile to a branch and it gets its own git worktree instead, and a pin that has gone stale says so rather than quietly falling back. Branches and worktrees →
A markdown file opens as a tile beside the work, rendered rather than raw, and live in both directions. So a plan an agent just wrote gets read next to the session that produced it.
Plugins and integrations are in one place, the Marketplace, instead of a settings page per thing. Each one is a small sandboxed program, so installing one is not handing it your machine.
The manifest declares where its controls belong and what it is asking to touch, and Dispatch draws those controls itself. So a plugin reads as part of the app rather than as somebody else's website in a panel, and it gets the capabilities it named and nothing beside them. The ones that need an account get an OAuth flow instead of a box you paste a token into. Five ship with it, Spotify among them; the usage readout in the next row is another.
Run Claude Code and this totals it from the transcripts on disk, in the sidebar footer where you can see it without asking. Subagent transcripts are counted with the rest. A lead session that fans six of them out looks cheap on its own, and the six are where the tokens went. A total that leaves them out is wrong in the direction that flatters you.
This one is Claude Code only, and plainly so: it reads Claude Code's transcripts and prices Claude models. Another agent in a tile runs perfectly well and has nothing to say to this panel.
What the window, the bar and the cost figure are actually worth →
A Rojo workflow has two ends, and Dispatch only ever owned one: rojo serve runs in a tile, while the Connect that makes Studio listen lives in Rojo's own plugin. Forget that click and editing a project looks exactly like editing one that is synced. The files change, the place doesn't, and the first sign is a playtest behaving like the code from twenty minutes ago.
The chip is a switch: click it amber and it connects, click it green and it disconnects. Clicking Serve opens a terminal running it, in its own tile in that project, because rojo serve holds a terminal for as long as it runs.
Connect/Disconnect action. It reports the state it actually reached rather than the keystroke it sent, so a chip that stays amber tells you something real: nothing is bound to that chord, or Studio has a modal in front of the place.A tile can be pointed at a running Studio window, and its header carries a chip naming the place that window has open. Click to bring Studio to the front, shift-click to raise it without moving it, right-click for its home monitor. Which windows exist, what each has open, where they sit. Nothing reaches inside.
It names the place it is still pointed at, and clicking it opens that placerather than telling you it is shut. The plugin names itself on the way in, so every handshake carries the place's id.
$6/ month
or $60 / year2 months free
14 days of the same build, nothing withheld and nothing to cancel. One afternoon with six sessions running is enough to know whether that number is worth it.
Start the 14-day trial, no card