AgentDeck
by flashclub
README.md
# AgentDeck
**[English](README.md)** | [简体中文](README.zh-CN.md)
[](https://github.com/flashclub/agent-deck/actions/workflows/ci.yml)
[](LICENSE)
[](https://nodejs.org)
[](#quick-start)
[](https://github.com/flashclub/agent-deck/pulls)
[](#quick-start)
**One screen. Four terminals. Any AI coding agent.**
Stop juggling terminal tabs. AgentDeck gives you a 2×2 grid of real terminals in your browser — launch [pi](https://pi.dev), [Claude Code](https://claude.com/product/claude-code), [Codex](https://openai.com/codex), Gemini CLI, Aider, or a plain shell in any pane, and drive them all from one page.
<p align="center">
<img src="docs/img/demo.gif" width="880" alt="AgentDeck demo — broadcast to panes, switch theme & accent" />
</p>
<p align="center"><sub>From an empty page to four live agents — pick per pane, then maximize any of them</sub></p>
<p align="center">
<img src="docs/img/hero-dark.png" width="880" alt="AgentDeck — dark theme, four agents running side by side" />
</p>
<p align="center"><sub>Dark theme · pi + Claude Code + two shells · ⌨ caster dock at the bottom</sub></p>
<p align="center">
<img src="docs/img/hero-light.png" width="880" alt="AgentDeck — light theme with the caster dock expanded" />
</p>
<p align="center"><sub>Light theme · caster dock expanded — <code>Tab</code> cycles targets, <code>⌘/Ctrl+Enter</code> broadcasts to every pane</sub></p>
## Why
Running multiple coding agents in parallel means N terminal windows, N tabs, endless ⌘-Tab. AgentDeck keeps every agent visible at once, lets you talk to one or all of them from a single input, and keeps processes alive across page refreshes.
## Quick start
```bash
git clone https://github.com/flashclub/agent-deck.git
cd agent-deck
npm install
node server.mjs
# open http://127.0.0.1:7788
```
Requirements: Node ≥ 22, macOS / Linux. No build step, no config file.
Agents are **auto-detected** from your machine (`command -v`): pi, Claude Code, Codex, Gemini CLI, Aider, plus a login shell. Add your own in `detectAgents()` in `server.mjs`.
## Features
- **Real terminals** — node-pty + xterm.js. Full ANSI / 256-color / full-screen TUI rendering; every agent shortcut works exactly as locally.
- **Survives refresh & reconnect** — panes are server-side PTYs with ~160KB output replay per pane. Close the tab, come back, keep going.
- **Caster dock** — hover the ⌨ dock at the bottom:
- `Tab` / `Shift+Tab` cycle targets (All → pane 1..4, skips stopped panes)
- `Enter` sends to the selected pane
- `⌘/Ctrl+Enter` broadcasts to **all** running agents at once
- receiving panes flash; `Esc` collapses and returns focus to the terminal
- **English & Chinese UI** — defaults to English, one-click 中/EN switch in the toolbar, every string localized.
- **Editable pane titles** — click a pane's title to rename it; the full path slides in on hover. Titles and pane positions persist across refresh.
- **Collapsible toolbar** — hide the top bar for maximum terminal real estate; a small ⌃ button brings it back.
- **Light & dark themes + six accent colors** — tuned terminal palettes (cursor follows your accent), persisted; adjustable terminal font size (12–24px).
- **Per-pane controls** — click to focus, `⤢` maximize, `↻` restart, `✕` close; status dot pulses while output is flowing.
- **Isolated worktrees** — tick “Isolated worktree” in the launcher to run a pane in its own git worktree (`ad/wt*` branch, created outside your repo under `~/.agent-deck/worktrees`). When closing the pane you choose: **merge** the changes back, **discard** them, or **keep** the worktree for later. Restarts reuse the same worktree. Parallel agents on one repo never step on each other.
- **Browser bridge (experimental)** — pair the bundled Chrome extension (`extension/`) and any pane's agent can drive your real browser: navigate, click, eval JS, read pages, and screenshot (returned inline to multimodal agents, also saved to `~/.agent-deck/shots/`). Token-paired, localhost-only. Register `mcp.mjs` as an MCP server (`pi mcp add agentdeck-browser -- node …/mcp.mjs`) for native tool calls, or just `curl` the HTTP API — see `extension/README.md`.
- **Smart cwd picker** — optionally offers recent project directories read from pi's local session library (see Privacy).
- **Custom dialogs & toasts** — no native `alert()` anywhere.
<p align="center"><img src="docs/img/caster.gif" width="760" alt="caster demo: broadcast to all panes, then send to a single pane" /></p>
<p align="center"><sub>The caster in action — one message, every pane</sub></p>
## Keyboard map
| Key | Action |
|---|---|
| `Tab` (in caster) | cycle send target |
| `⌘/Ctrl+Enter` | broadcast to all panes |
| `Alt+1..4` | focus pane 1–4 |
| `Esc` | collapse caster / cancel dialog |
Everything else (including `Shift+Enter`, steering, aborts…) is handled by each agent's own TUI.
## How it works
```
Browser (xterm.js ×4, caster, theming, i18n)
│ WebSocket (JSON: spawn / input / resize / replay)
▼
Node server (server.mjs)
│ node-pty ── one PTY per pane
▼
pi / claude / codex / $SHELL — full TUI agents in their own cwd
```
- Static assets are served straight from `node_modules` (xterm.js) — no bundler.
- Each pane keeps a ring buffer so reconnects replay recent output.
- Broadcast = writing `text + \r` to every running PTY; agents receive it like typed input.
## Privacy
- Nothing leaves your machine. The server binds to `127.0.0.1` and makes no outbound requests.
- **No paths are baked into the repo.** The "recent directories" picker reads pi's local session library (`~/.pi/agent/sessions`) on *your* machine at runtime — everyone who clones sees only their own history.
- Don't want that? Run with `AG_RECENTS=0` to disable the scan entirely.
- Isolated worktrees live under `~/.agent-deck/worktrees/` and are cleaned up automatically on merge/discard. Kept worktrees can be reclaimed with `git worktree prune` or by deleting that folder.
## Security
No authentication, by design — a local tool. Do **not** expose it to a network (`AG_HOST=0.0.0.0` is a foot-gun: anyone on your LAN gets a shell).
## Test
```bash
node server.mjs & # start server first
npm run test:e2e # protocol-level E2E: shell echo round-trip + pi TUI boot
```
## License
[MIT](LICENSE)
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues