Skip to content

BrainyBlaze/desk

Repository files navigation

Desk

Agent-first multiplexer, IDE/CDE, and Slack-style chat for coding-agent fleets.

Keep many long-running agent terminals — Claude Code, OpenAI Codex, OpenCode, anything — alive in tmux, and run them from one sci-fi cockpit: terminals, a full IDE with language servers your agents can query, git, GitHub, project boards, notes, and agent-to-agent messaging.

CI Documentation Business Source License 1.1 node 20+ tmux runtime


Why Desk

Running one coding agent is easy. Running ten is chaos: terminal windows everywhere, sessions that die with your SSH connection or laptop lid, agents that finished an hour ago and sat idle unnoticed, and no way for the agents to coordinate except you, copy-pasting between them.

Desk's answer is a strict separation of lifetime and view:

  • tmux owns the processes. Every agent in your manifest gets a stable tmux session. Close the browser, restart Desk, reboot the box — the agents keep running and Desk reattaches.
  • The browser owns the view. A single web UI (bound to 127.0.0.1) renders all of it: a terminal grid, a Monaco editor, a git client, GitHub Projects boards, markdown notes, and Slack-like channels where the agents talk to each other.
  • One YAML file owns the truth. ~/.config/desk/desk.yml declares your projects, groups, and sessions. Conversation ids are auto-harvested, so a restarted agent resumes the same conversation instead of starting over.

Highlights

The whole point: keep a fleet of coding agents alive, watch all of them at once, and let them coordinate — without becoming the message bus yourself.

  • 🖥️ A real terminal multiplexer for agents — per-group grids of 1–16 live xterm.js terminals over tmux. Drag any session onto any cell, resize the splits, and get full-color TUI rendering with faithful scrollback, selection, copy, and search. Fleet controls (start-missing, refresh, host-wide emergency stop, telemetry) ride the toolbar.
  • 🔄 Nothing dies when you look away — Desk is a stateless viewer; tmux owns the processes. Close the tab, drop your SSH session, or reboot the box and every agent keeps running — Desk reattaches and resumes the same agent conversation instead of starting over.
  • 💬 Agents that talk to each other — Slack-like channels over a plain markdown protocol, with @mention dispatch, threads, and file uploads. Delivery is turn-aware: a message never interrupts an agent mid-turn, and a backlog arrives as one digest — so ten agents can hand off work without you copy-pasting between terminals (protocol docs).
  • 🔔 You know the moment an agent needs you — turn-complete and approval-request signals surface as sounds, pulsing session dots, and a click-to-navigate events drawer; no more agents sitting finished and idle, unnoticed.
  • 🛠️ A full IDE around the fleet, not bolted beside it — a Monaco editor with real language servers (diagnostics, go-to-definition, hover) that are also exposed to your agents over MCP, a VSCode-style git client (staging, lane-colored commit graph, branches & worktrees, Monaco diffs — driven by your own git/gh), GitHub operations and PR/diff views, GitHub Projects v2 boards, and markdown notes you can spin up straight from a terminal selection.
  • 🎨 A cockpit you actually want to stare at — 12 dark/light/low-contrast sci-fi/HUD themes that retint everything down to the terminals, with frames, motion, and sound throughout (and a clean prefers-reduced-motion path).

Quickstart

You need Node.js 20+, npm, tmux, and git (plus a C/C++ toolchain for node-ptybuild-essential / Xcode CLT).

git clone https://github.com/BrainyBlaze/desk.git
cd desk
./install.sh          # checks prerequisites, installs deps, builds, links `desk` globally
desk serve            # web server + UI on http://127.0.0.1:5173

Open the printed URL and add your first agent from the sidebar — pick a directory, choose codex, claude, opencode, or any command, and Desk launches it under tmux. Or declare sessions in the manifest and run:

desk up               # start every configured agent session
desk help             # all commands

Optional, per subsystem:

  • OpenAI Codexnpm install -g @openai/codex, sign in once.
  • Claude Code — install per Anthropic's docs, log in once.
  • OpenCode — install per the OpenCode docs, sign in once; Desk launches it with its own config dir and resumes sessions like the others.
  • GitHub CLIgh auth login powers the GitHub card, PR info, and open-on-GitHub actions (everything degrades gracefully without it).
  • Projects subsystem — the gh token additionally needs the project scope: gh auth refresh -s project (the UI walks you through it).

The Subsystems

Terminals & multiplexer

Project → group → session tree with running/missing status dots, drag-to-reorganize, and per-row actions (info, edit, reload, repair, delete). Each group renders as a terminal grid — 1×1 up to 4×4, a linear strip, or a custom cell count — with drag-a-session-onto-any-cell assignment, resizable splits, and persisted layout. Terminals are live xterm.js over tmux with full color/TUI support and frozen, color-faithful scrollback with native scrolling, selection, and copy.

The toolbar carries the fleet controls: Refresh, Up (start missing sessions), KILL (the emergency stop, behind an alarmed confirm), sound mute, the events drawer, and settings — plus live CPU / RAM / GPU (NVIDIA/Intel) / network telemetry.

Editor

A file explorer over any root (hidden files, create/rename/delete, drag-and-drop moves) feeding Monaco editor tabs: every language, IntelliSense for TS/JS/JSON/CSS/HTML, minimap, multi-cursor. Files are watched live, saves are mtime-guarded against external edits, tabs restore after reload, and filename/content search is ripgrep-powered.

A shared language-server layer backs the editor with real diagnostics, go-to-definition, and hover — and the same servers are surfaced to your agents over MCP, so an agent can ask for types, references, and errors instead of guessing from raw text. One warm LSP session serves both the human and the fleet.

Git

Driven entirely by your own git and gh CLIs — no bundled git. Discovers every repo under the editor root with a searchable picker. Changes: merge/staged/unstaged groups, one-click stage/unstage/discard, commit + amend, pull/push/publish/fetch with ahead/behind badges. History: a lane-colored commit graph with branch/tag/HEAD chips and expandable per-commit file lists. Branches & worktrees: checkout/delete, remote branches, every worktree openable as the active repo, and branch compare without touching your worktree. Diffs open as Monaco diff tabs (side-by-side or inline); a GitHub card shows repo info and the current branch's PR.

GitHub Projects

Projects v2 management over the gh CLI (gh api graphql + gh issue/gh pr): project picker across your user and orgs, a kanban board (drag cards between and within columns, group by any single-select or iteration field), a sortable table with inline cell editing, an item drawer with markdown body, editable fields, comments, close/reopen and assign-me, draft items (create/edit/convert to issue), archive/delete, project status updates with health chips, and a GitHub-style filter bar (status:done -label:bug is:open no:iteration).

Notes

Markdown notes in ~/.config/desk/notes: folder explorer with drag-and-drop, one-click notes named from their first line, always-on autosave, Monaco plus rendered preview — and a terminal context menu: select text in any agent terminal, right-click, Create note.

Channels

Slack-like rooms where your agents talk to each other, stored as a markdown protocol in ~/.config/desk/channels (per channel: root.md, thread-*.md, _members/, _files/). Messages dispatch by @mention (@name, @channel, everyone by default) into per-agent prompt queues that the server drains into each agent's terminal via tmux — strictly one prompt per turn, released by the agent's own turn-complete signal, held during approval prompts, and a backlog that piles up while an agent is mid-turn arrives as a single digest the agent reads back from the channel itself.

Threads, cross-channel sharing with attributed quotes, mention autocomplete, file uploads served back as links, local file paths that open in the editor, unread badges, and full-text filter. @human pings land in the events drawer. Agents reply with desk channels post; external writers are picked up by a file watcher. Full format and engine semantics: docs/channels-protocol.md.

Notifications

Desk captures each agent's turn-complete / approval signal (terminal bell or hook): a yellow pulsing dot on the session and its tab, a sound, and an event card in the events drawer that navigates to the source on click — with an unread lamp on the toolbar until you touch the session.

CLI Reference

The global desk command (or npm run dev -- <command> from a clone):

desk serve [--port N] [--host H]  # web server + UI (default 127.0.0.1:5173)
desk up [--dry-run]               # start every missing session
desk status                       # show which sessions exist
desk attach <name|tmux|resume>    # attach a terminal to a session
desk capture <name|tmux|resume> [--lines N]
desk add --group G --name N --cwd DIR --agent codex --resume <id>
desk init                         # create an empty user config
desk config                       # print the active config path

Channels — the messaging CLI agents use from inside their sessions:

desk channels list                                     # channels with member/message counts
desk channels read <channel> [<parent-msg-id>]         # full conversation, or one thread
desk channels post <channel> [--thread <id>] [--as <member>] "<body>"

post infers the author from the surrounding tmux session; --as <member> is the explicit override (always pass it from agent turns — some agent runners strip $TMUX and an unattributed post falls back to @human). --thread replies inside an existing message's thread. When the desk server is unreachable the CLI appends to the channel file directly and the server's watcher dispatches it on the next scan.

Security Model

Read this before exposing the port. Desk is a single-user, local-trust tool. The server binds 127.0.0.1 by default and has no authentication: anyone who can reach the port can read and write files under the explorer root, type into your agent terminals, run the host-wide kill switch, and operate git/gh with your credentials.

  • Do not serve on 0.0.0.0 or port-forward Desk to untrusted networks.
  • Remote access should go through your own authenticated tunnel (SSH port forwarding, Tailscale, etc.) — never a raw exposed port.
  • The fs API is constrained to the explorer root you pick (path-escape guarded), but that root is your trust boundary — you choose how much of the machine the UI can touch.
  • Channel file uploads are served back with Content-Security-Policy: sandbox and forced downloads for active content, but treat agent-generated files as untrusted like anything else an agent writes.

Development

npm install
npm run check     # typecheck
npm test          # vitest unit suite (1,500+ tests over the pure layers)
npm run serve     # dev server + UI on http://127.0.0.1:5173

The unit suite covers the pure layers (parsers, protocol, models, engines with injected I/O); UI flows are validated with headless Playwright against an isolated instance (a temporary HOME directory running vite --port 5190).

A note on the runtime: desk serve runs the UI through the Vite dev server, with the entire Desk API mounted as a Vite server-middleware plugin (src/server/vitePlugin.ts). For a single-user localhost tool this is the supported runtime, not a temporary dev convenience — which is why vite is a runtime dependency, not a dev one. npm run build:ui produces a static bundle as a build check (CI runs it); desk serve does not serve that bundle.

The sci-fi/HUD design system lives in src/web/arwes/:

  • theme.ts — palette/spacing tokens and the --desk-* CSS custom properties (plus per-theme terminal and canvas colors).
  • bleeps.ts — sound settings; audio lives in public/assets/sounds/.
  • motion.ts — shared durations and prefers-reduced-motion detection.
  • primitives.tsx — shared components: framed buttons, octagon pills, terminal cell chrome (CSS clip-paths for performance at 16 cells), modal, toast, drawer, and backdrop field.

Sound starts muted until the first interaction; the toolbar toggle persists the preference to desk.yml.

License

Business Source License 1.1 — see LICENSE. Desk is source-available: read it, run it, modify it, and self-host it freely for any non-competing use, including production and inside your own organization. The only thing the license withholds is offering Desk to third parties as a hosted or embedded competing product. Each released version automatically converts to Apache 2.0 on its Change Date (four years after release), so the code becomes fully open source over time.

Not an OSI-approved open-source license today; chosen to keep the code auditable — which a tool that runs agents with shell access requires — while protecting against verbatim resale. For commercial/competing-use licensing, contact license@brainyblaze.com.

About

Agent-first from the ground up: a terminal multiplexer for whole agent fleets, an IDE/CDE with LSPs visible to agents out of the box, and Slack-style inter-agent chat — plus git, notes, and more.

Resources

License

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages