Architecture
Band is composed of three main components: a desktop application, a web server, and a CLI. Each component has a distinct responsibility, and they communicate over HTTP and WebSocket.
System Overview
- Desktop App (Electron) — Hosts the dashboard webview, auto-starts the web server, and provides macOS-only shell helpers (folder picker, reveal in Finder, install the CLI with admin privileges). The desktop app spawns the web server using Electron's embedded Node runtime (
ELECTRON_RUN_AS_NODE=1), so end users do not need to install Node themselves. - Web Server (Node.js) — Data management, state, API, and background processes. Runs under whichever Node interpreter the host supplies — Electron's bundled Node 22.x in the packaged desktop app, or a system
nodebinary when run standalone. - CLI (Rust) — Command-line interface for scripting and automation.
Separation of Concerns
The web server handles data, state, and background processes exclusively. It never invokes macOS-only shell helpers — folder pickers, Finder reveal, opening apps, or installing the CLI symlink with administrator privileges all live in the desktop app.
Those bridges are exposed by the Electron desktop app
(apps/desktop/src/main/ipc/macos-shell.ts) and called from the React
webview via the IPC bridge in apps/web/src/lib/desktop-ipc.ts (which talks to the
preload script at apps/desktop/src/preload/index.cts). The split keeps the web
server runnable headlessly (e.g., on a remote machine for tunnel-based access) while the
desktop app handles the local-only OS bits.
Git Worktree-Based Workspace Isolation
Each workspace is backed by a Git worktree. When you create a workspace, Band runs
git worktree add to create an isolated working directory with its own branch. This
provides:
- File isolation — Each workspace has its own copy of the project files.
- Branch isolation — Each workspace works on its own Git branch.
- Concurrent work — Multiple agents can work on different tasks simultaneously without conflicts.
- Efficient storage — Git worktrees share the object database, so disk usage is minimal.
Worktrees are stored in the configured worktrees directory (default
~/.band/worktrees/<project>/<branch>).
SQLite for State
All application state is stored in a local SQLite database at ~/.band/band.db.
This includes projects, worktrees, chat panes, cronjobs, and panel layout state. The server
uses Node's built-in node:sqlite module via Drizzle ORM — no native module ships
in the bundle, and the binary always matches the runtime Node version.
tRPC API (HTTP + SSE + WebSocket)
The web server exposes a tRPC API used by:
- The web dashboard (browser client).
- The desktop app (Electron renderer).
- The CLI (via HTTP requests).
Most procedures are HTTP request/response. Long-lived streams use a few different transports depending on the data:
- Server-Sent Events — Chat task output streams over SSE
(
/api/tasks/<chatId>/stream). - WebSockets — Terminals (
/terminal) and language servers (/lsp) use raw WebSockets so the renderer can pipe them directly into xterm and the LSP client. - tRPC subscriptions — Lower-volume realtime events (workspace status, cronjob ticks, tunnel state) ride a tRPC WebSocket subscription.
tRPC provides end-to-end type safety between the server and TypeScript clients, ensuring the API contract is enforced at compile time. The same router is exposed as an OpenAPI spec (generated from the router definitions) for non-TypeScript consumers.
Agent Adapter Pattern
Band uses an adapter pattern to support different coding agents. Each agent implementation (Claude Code, Codex, OpenCode) is wrapped in an adapter that translates between Band's chat-pane model and the agent's specific interface. This allows Band to:
- Start and stop agent processes.
- Stream agent output to the dashboard in a uniform format
(
session-start,text-delta,tool-use,tool-result,session-result,error). - Support multiple agent backends without changing the core system.
See Coding Agents for the full feature matrix.
Agent Status
Agent status (working / waiting / completed / failed) is reported by the agent process itself
via the events listed above, plus — for Claude Code specifically — out-of-process hooks. On
first launch the server installs PreToolUse, PermissionRequest,
UserPromptSubmit, PostToolUse, and Stop hooks that pipe
JSON to band notify, which forwards it to the running server via the local tRPC
endpoint. See Agent Status for details.
Data Flow
- User sends a message to a chat pane via the dashboard, CLI, or cronjob.
- Server stores the message in SQLite and spawns / resumes the agent in the chat pane's workspace.
- Agent works in the Git worktree, making file changes and running commands.
- Agent events stream via SSE to the dashboard (and via stdout to
band chats watch). - Claude Code hooks publish status updates through
band notifyas the agent runs. - Desktop app handles window focus and positioning when the user switches workspaces.