English · 한국어
Run a fleet of AI coding agents from anywhere — even your phone.
AgentBoard is a browser-based command center for running many AI coding agents in parallel — across as many machines as you like. Spawn Claude Code, Codex, Aider, or any shell-based agent in its own tmux session, switch between them with a tap, and pick up exactly where you left off — from your laptop, your tablet, or your phone. Sessions running on several PCs (even behind NAT) aggregate into one dashboard.
Designed for the moment your agents outgrow a single terminal tab — and then a single machine.
A real, unedited Claude Code session driven through AgentBoard — it adds rate limiting, verifies with a test client, and reports back:
Modern coding agents are most useful when they run for minutes or hours, not seconds. Soon you're juggling three, five, ten of them — and tmux alone gets old fast on mobile. AgentBoard wraps tmux in a clean dashboard that:
- Just works on mobile. Real touch scroll with momentum, no broken gestures, no pinch traps. Built and tuned on actual devices, not emulators.
- Knows what each agent is doing. Each session shows an
idle/working/waitingbadge derived from its terminal output. - Refuses to lose state. Sessions live in
tmux— they survive page reloads, server restarts, and flaky networks. - Is honestly fast. 80 ms screen refresh on the session you're looking at, 2 s on the rest. Adaptive, never wasteful.
- Long-running refactors — kick off an agent at your desk, check its progress from your phone over coffee, tap once to send
ywhen it asks for confirmation. - Parallel coding — three agents on three branches, one dashboard, zero context-switching tax.
- Pair-programming with yourself — the same
tmuxstate, viewed live from any device on the network. - Tablet-first development — file browser, code editor, PDF viewer, and a live terminal — all in one tab.
| Multi-session terminal | Spawn, kill, rename, and switch between unlimited tmux sessions |
| Multi-machine | Aggregate sessions from several PCs in one dashboard; remote agents dial out, so NAT/firewalls are no obstacle |
| Mobile-first UI | Custom touch handlers — momentum scroll, scroll-to-bottom, on-screen keys (PgUp/PgDn, ⌫), keyboard-friendly input |
| Live state detection | Per-session badges: idle, working, waiting-for-input |
| Push notifications | Web Push fires an OS notification when a session goes waiting or completed — even on iOS (installed PWA) |
| Adaptive polling | 80 ms on the active session, 2 s on background sessions |
| File browser & editor | CodeMirror 6 with syntax highlighting for 13+ languages, plus a git-diff view |
| Markdown + KaTeX | Notion-style rendered view, clickable task-list checkboxes, sanitized HTML, math rendered server-free |
| Jupyter notebooks | Read-only .ipynb viewer — rendered cells, syntax-highlighted code, images/tables/errors |
| PDF & image viewer | PDF zoom (50–300%), fit-to-width; images pan/zoom; all lazy-loaded for instant boot |
| Cookie auth | Single password, HMAC-SHA256 signed, per-IP login throttling |
| Optional Cloudflare tunnel | Expose the dashboard publicly with one env var |
| Survives everything | tmux-backed sessions persist across reloads, restarts, and disconnects |
git clone https://github.com/ralbu85/AgentBoard.git
cd AgentBoard
DASHBOARD_PASSWORD=pick-a-password docker compose up -d --buildOpen http://localhost:3002 and log in. Sessions run bash by default — the
image ships no AI CLIs, so install what you need (e.g.
docker compose exec agentboard npm install -g @anthropic-ai/claude-code) or
extend the image. Mount your projects by setting AGENTBOARD_WORKSPACE=/path/to/projects.
Prerequisites: tmux, Python 3.12, Node 20+.
git clone https://github.com/ralbu85/AgentBoard.git
cd AgentBoard
python3.12 -m venv backend/.venv
backend/.venv/bin/pip install -r backend/requirements.txt
(cd frontend && npm install)
echo "DASHBOARD_PASSWORD=pick-a-password" > .env
./deploy.sh # builds the frontend, starts the server, waits for /api/healthOpen http://localhost:3002, log in, hit + New — and you're spawning agents.
The server binds to loopback by default; set AGENTBOARD_HOST=0.0.0.0 in .env
for LAN access, or put a reverse proxy (nginx/Caddy) in front for HTTPS.
Every extra PC runs a lightweight agent that dials outbound to your hub — so machines behind NAT or a firewall just work, no SSH or port-forwarding. On each remote PC:
git clone https://github.com/ralbu85/AgentBoard.git && cd AgentBoard
python3.12 -m venv backend/.venv
backend/.venv/bin/pip install -r backend/requirements.txt # tmux required too
export AGENT_HUB_URL=wss://your-hub-host/agent-ws # ws:// needs AGENT_INSECURE=1
export AGENT_TOKEN=<the hub's AGENT_TOKEN> # defaults to its auth token
export AGENT_HOST_LABEL="Office PC" # display name (optional)
agent/start-agent.shThe machine appears in the dashboard within seconds; its sessions show up as
office:1, office:2, … and everything (spawn, kill, input, push
notifications) works exactly like local sessions. Use wss:// in production —
the token grants shell access, so don't send it in plaintext.
Browser (xterm.js + React)
│
│ HTTPS / WSS
▼
nginx :12019
│
▼
uvicorn :3002 ──── pipe-pane FIFO
│ capture-pane polling
▼
tmux sessions
| Layer | Stack |
|---|---|
| Frontend | React 19, xterm.js 5.5, Zustand, Vite, CodeMirror 6 |
| Backend | FastAPI, asyncio, tmux via async subprocess |
| Auth | HMAC-SHA256 signed cookie |
| Proxy | nginx (optional, recommended for HTTPS) |
| Method | Path | Body |
|---|---|---|
POST |
/api/login |
{pw} |
GET |
/api/workers |
— |
POST |
/api/spawn |
{cwd, cmd} |
POST |
/api/kill |
{id} |
POST |
/api/remove |
{id} |
POST |
/api/input |
{id, text} |
POST |
/api/key |
{id, key} |
GET |
/api/browse?path= |
directory listing |
GET |
/api/files?path= |
file metadata |
GET |
/api/file?path= |
read file |
POST |
/api/file |
{path, content} |
GET |
/api/health |
readiness probe |
- Client → server:
resize,active,resync,title,key,terminal-input,input - Server → client:
spawned,snapshot,screen,stream,status,cwd,aiState,info,title,titles
backend/
main.py FastAPI app, lifespan, static serving
config.py .env loading, auth token, project root
auth.py HMAC-SHA256 cookie auth
sessions.py SessionStore: spawn / kill / recover tmux
streamer.py pipe-pane FIFO + capture-pane polling
state_detector.py idle / working / waiting heuristics
tmux.py async tmux wrappers
ws.py WebSocket routing + broadcast
routes_session.py REST: login, workers, spawn, kill, input
routes_file.py REST: browse, files, read / write
tunnel.py optional Cloudflare tunnel
frontend/
src/
App.tsx root + login flow
store.ts Zustand state
ws.ts WebSocket singleton
api.ts REST wrappers
components/Terminal/ xterm.js lifecycle, mobile scroll
components/Sidebar/ session list, mobile overlay
components/Viewer/ split layout, code editor, file content
components/SpawnModal/ new-session dialog
components/FilePanel.tsx file browser
components/PdfViewer.tsx PDF rendering
components/Header.tsx status bar, + New
components/Login.tsx password login
components/Toaster.tsx toast notifications
A few non-obvious decisions that have already burned someone:
- Static assets are served
no-cache. Build outputs use fixed names (app.js,index.css); cache busting is via a?v=<timestamp>query injected bydeploy.sh. Never add a client-sidesetTimeoutauto-reload — it loops on slow mobile. - xterm.js native touch is disabled (
pointer-events: noneon.xterm*). A custom handler on.xterm-wrapdrives mobile scroll. Playwright's CDP touch direction is the opposite of real devices — trust real-device feedback over emulator output. - Raw stream is not applied to the client. Pipe-pane output contains escape sequences that destroy the scrollback. The client receives
writeScreen(in-place capture-pane) and a one-timewriteSnapshoton session switch. - Always launch from the project root.
start.shanddeploy.shhandle this — theycdfirst sobackend.mainresolves correctly.
GNU AGPL-3.0 © 2026 Jihwan (James) Lee.
Free to use, modify, and self-host. The AGPL's network clause means that if you run a modified version as a service over a network, you must offer your users the modified source. For a commercial license without the AGPL obligations, contact the author.





