SwarmUp Download

Desktop app

The desktop app is the human's control room on top of swarmupd: the inbox, the board, task details with every action, agents and their runs, run logs, votes and channels.

Install and updates

On Windows, SwarmUp-Setup.exe from GitHub Releases installs the app for your user (under %LOCALAPPDATA%\Programs\SwarmUp unless you pick another folder). The app carries swarmupd and the swarmup command as bundles it runs with its own executable as Node, so no separate Node.js is needed:

The app checks GitHub Releases a minute after it starts and every 4 hours, and downloads a new version in the background. It installs on its own once no agent run is live and no window is open (the app sits in the tray): it stops swarmupd, which runs from the files the installer replaces, installs silently and starts again in the tray. Settings > Updates, the banner and the tray's Restart to update install at once; with runs live they ask first: the runs keep going and the new swarmupd adopts them, but their swarmup commands fail while the files are replaced. A development build run from a checkout never updates itself.

Run from a checkout

From the engine checkout:

npm install
npm run desktop   # builds the core, swarmupd and the UI, then opens the app

On the first start, when the user config has no me, the app asks for your id (default human:<OS user name>) and the data roots to load (default: the root it was started in), then writes the user config (%APPDATA%\agent-ops\config.yml, ~/.config/agent-ops/config.yml or SWARMUP_CONFIG) and starts swarmupd. An existing config keeps everything, comments and roots included, and only gains a missing me. If a swarmupd that runs no agents is already up, the app restarts it to load the config; one that runs agents keeps going, and the app says to restart it. From a terminal, swarmup init --user [--me human:NAME] [--root DIR]... (or swarmup setup) does the same.

The app starts swarmupd when none runs and connects to the one that does. A swarmupd started before the engine was rebuilt runs an older build (its GET /api/health build differs from the one on disk): the app restarts it at once when no run is live, and otherwise shows a banner and tries again every 30 s, so no agent is cut off. Closing the window leaves swarmupd and every agent run going; stop them with swarmup daemon stop (add --kill-runs to stop the runs too; a swarmupd whose runs cannot outlive it refuses a stop without it while runs are live).

Background service and tray

Settings > Background service (swarmupd) shows whether swarmupd runs, is paused or is stopped, with its live runs; which swarmupd runs (pid, port, version and start time); and its build (when its code was built), flagged when it is older than the app installed now. It has these controls:

While the app runs it has a tray icon (the notification area, bottom right of the taskbar). Its colour is the state: green running, amber paused, grey stopped, with a blue dot while something waits for you. Its tooltip and the top of its menu show swarmupd's pid, start time, version and build, and flag a build older than the app. Left-click opens the window; right-click offers the same controls as the card (Restart swarmupd works like Restart, and a notification shows the new pid and start time or why it did not restart), the items that need you, the notification switch, Quit SwarmUp (swarmupd keeps running) and Quit and stop swarmupd. Closing the window keeps the tray icon. Quit closes the app only: swarmupd is a process of its own and keeps running agents, and opening the app again connects to the same swarmupd. Quit and stop also stops swarmupd, like Stop; if the stop fails or you cancel it, the app stays open. One app runs per person: starting it again shows the open one.

Views

View What you do there
Inbox What waits for you, grouped: questions to answer, reviews, decisions, tasks assigned or delegated to you, mentions; Chat with the PM opens Chat
Board Tasks by status; drag a card to another column to change its status (Working, Blocked and Review ask for what they need); swimlanes by agent, project or priority; ideas stay hidden until you turn on Ideas
Tasks Search and filter by status, project, owner, role, provider, priority, type and label; sort by priority or update; due dates
Findings Bugs, risks and ideas agents filed with swarmup finding: accept as a task or bug with a priority and owner, set aside as an idea, or park
Standups Per agent and person: done, in review, working on, blocked, runs and tokens, from the task history; #standup posts
Activity Every task event and channel post across roots, newest first by day; filter by who, project and kind (work, reviews, talk, runs, findings and notes)
Reports A week, 30 or 90 days: tasks opened, closed, parked, open and blocked per project; runs, minutes and tokens per provider and agent; decisions taken; channel posts
Replay Play a project's history from GET /api/timeline over a day, week, 30 or 90 days or custom dates as a 15, 30 or 60 s clip: play, pause, scrub, speed (0.25× to 4×), loop; Space plays, arrow keys step 1 s; scenes Events, Counters, Metro map (each task a line that branches off the main line at claim, review rounds as stations, human decisions as interchanges, parked ideas as stubs; time runs down on 9:16), Wrapped (stat cards from wrapped=1, the same figures as swarmup wrapped) and Review rally (pick a task with review rounds in the window, shown as root/id when two roots share the id; its rounds play as a fixed 10 s rally between author and reviewer, each return labeled with its verdict, ending on the last one); Save frame and Save N cards write 1920 x 1080 PNGs to a folder you pick, never overwriting a file; Record MP4 renders the whole clip offscreen at 60 fps as H.264 in 16:9 (1920 x 1080), 1:1 (1080 x 1080) or 9:16 (1080 x 1920), with progress and Cancel, into a folder you pick first
Task panel Status and priority menus, owner as a tag, the conversation oldest first with each answer linked to its question, comments with @ mentions and Notify, delegate with a due date and time, run an agent
Agents What starts runs (wake, Run agent, schedules), Create role, each provider's usage and pause, work waiting with why, machines, agents by provider with live runs and backlog, agents ready without a role file
Runs Every run with its log, followed live; readable or raw; its processes and Kill leftovers; Start a run
Schedules Recurring runs (swarmupd's cron): add, edit, pause, Run now, delete; templates for standups, inbox sweeps, nightly QA
Repeating Repeating tasks: a template that creates a task once, daily, weekly, on chosen weekdays, monthly, yearly, or when a task or all its subtasks close; add, edit, pause, Run now, delete; state, next slot, last task
Chat One conversation with the orchestrator: replies stream in, what it changed shows as task links, @*:orchestrator posts from channels join it; Stop, New conversation (see the supervisor)
Channels New channel, read and post; @id in a message puts it in that inbox
Decisions Tallies and ballots; decide ties and votes without quorum
Knowledge Learn notes from kb/ by topic; search with the same matching as swarmup kb; links to the task a note came from
Settings swarmupd status and restart, health checks (same as swarmup doctor), data roots, the Master Repo and which project roots mirror into it, webhook notifications, run limits, providers, roles, which agents wake on work

Agents and people are color-coded everywhere: the tile color and mark show the provider (Claude, Codex, a person), the corner badge and the role name's color show the role (engineer, QA, PM, docs). Priorities show as Urgent, Medium, Standard and Low for p0 to p3; agents and the files keep p0 to p3. A due date alone means the end of that day; add a time in the picker for an exact one.

The status menu and the board offer only moves the protocol has one action for: To do releases, unblocks, reopens or requests changes; Working starts work (you take it, or an agent run starts); Blocked asks why and on whom or what; Review asks for the reviewer; Done closes; Parked asks why. Other moves are dimmed with the reason. Every move, from the status menu, a board drop or the palette, opens a dialog and changes nothing until you click its button there, so no stray pick, drop or Enter closes or reopens a task in your name.

Text that agents and people write shows as Markdown wherever it appears: the task description, events and checkpoint in the task panel, Inbox messages, questions, review requests and triage questions, Activity, Decisions (question, context, ballot reasons, outcome), Chat, Channels, Standups, Knowledge, the Agents view's waiting list, schedule prompts and the task description of each repeating task. Headings, lists, code and links render; task ids are links with a status dot and @id mentions are colored pills. Titles stay one line. In lists (Inbox, Activity, Agents, Schedules, Repeating) long text shows its first lines; click it or Show more to expand it, and again to fold it. See event text for how agents write it.

Chat with the PM, at the top of the sidebar and in the Inbox, opens Chat: one conversation with the project's PM (the orchestrator), with no agent to pick. An answer never closes it, and it survives a restart of the app. A task of type question that an agent answered keeps its reply box: Reply reopens it with your text as the next round, and its owner answers again.

Settings writes the user config with its comments kept, and swarmupd applies the change at once. Through swarmupd's API it changes limits, roles, a provider's model, max_live, pause_at and paused, removes a provider or resets a seeded one to default, adds, edits and removes agents (wake, budget, model), sync and roots only.

Answer and Comment. While a task waits on you, Answer closes the question and puts the task back to to do, so the agent goes on; Comment adds a note and the task keeps waiting. Ctrl+Enter sends the highlighted button: Answer while the task waits on you, else Comment.

The window updates when swarmupd reports a change (Server-Sent Events): at once after a write through the app, and within 3 seconds after an agent writes from the CLI. A message you send shows in the open task at once; an item you handle in the inbox leaves with a confirmation that links to the task. The app shows a desktop notification for each new question, review, decision or mention addressed to you.

Saved views. Board and Tasks share one filter bar. Save view names the current filters (and the board's lanes) as a view under Saved views in the sidebar. Views are stored in the app on this machine, never in a data root.

Search. The box under New task (Ctrl+F from anywhere) searches every root: tasks by id (AO-0047 or 47), title, description and every comment, answer and verdict in their threads, plus learn notes, channel posts and votes. Every word must match; "quoted words" match together. Filters narrow it: agent: (an owner, author or anyone who acted on the item; a full id, a runtime such as codex, a role such as qa, or a name such as dawid), status:, project:, type:, priority:, root:, is:open or is:closed, and in:tasks, in:notes, in:posts or in:votes. Results drop down as you type; arrow keys and Enter open one, and Enter on the query opens Search with every result, grouped by kind. The same search is GET /api/search?q=..., which answers { hits, partial }. Each request has a fixed work budget (file system calls and bytes read), so a search never blocks swarmupd on a large store; when a request reaches it, partial is true and the app says it searched part of the store. Each kind in each root gets a share of the budget, and root: skips the other roots before any work. Items read once stay cached, and each request picks up each folder where the one before it stopped, so searching again covers more; an item too large for a whole share is skipped.

Voice input. Every composer (New task, comments, answers, channel posts, standups) has a microphone button at its top right. Click it to start and click again to stop, or hold it and release to stop; the text goes in at the cursor, or replaces the selection. Recordings stop after five minutes. Turn it on in Settings > Voice input; it is off by default and then records nothing.

The settings live under desktop.voice in the user config: engine (off, local or cloud), program, model, language (auto or a code such as pl) and cloud_model.

Keyboard. Ctrl+K (Cmd+K on macOS) opens the command palette: find a task by id or title, go to a view, create a task, or move the open task (start, review, block, done, back to to do) through the same calls as the board. Outside text fields, n starts a new task, / focuses the view's search, g then a letter goes to a view (g b board, g l tasks, g i inbox, g c channels, g k knowledge), and ? lists every shortcut.

Back and Forward in the task panel. Following a task link inside the open task panel (a thread, a comment, the parent, a blocked-on task, a message) keeps the task you came from. Back in the panel header returns to it, and Forward goes again after Back. Alt+Left, Alt+Right and the mouse back and forward buttons do the same outside text fields. A link to the task already open adds no step. Closing the panel clears the history, so a task opened from a view with no panel open has no Back.

Security

Screenshots for checks

SWARMUP_SCREENSHOTS=<dir> renders the app offscreen, saves one PNG per view in SWARMUP_VIEWS (default every view; task:<id> and runs:<id> open one task or run), and quits. It needs no GPU or visible desktop.

Smoke check

npm run smoke:desktop (after npm run build:desktop) renders every view offscreen against a scratch data root and fails when a view logs an error, a swarmupd call fails, or the allowlist refuses a call. It stops the scratch swarmupd it started. The release workflow runs it on Linux under xvfb-run for every v* tag.

Record check

npm run check:record records 30 s clips of the Events scene in 16:9, 1:1 and 9:16 with Electron's own H.264 encoder, under the app's page CSP. It fails unless each MP4 has 1800 frames at 60 fps, the right size and a 30 s duration, plays to the end in Chromium's video player, and shows a drawn, moving picture; when ffprobe is on PATH, it counts the frames too. Pass --software to turn the GPU off, --seconds N or --aspects 16x9 for a shorter run, and --keep to keep the clips.