Skip to main content
Glama
README.md
# AgentDeck

**[English](README.md)** | [简体中文](README.zh-CN.md)

[![CI](https://github.com/flashclub/agent-deck/actions/workflows/ci.yml/badge.svg)](https://github.com/flashclub/agent-deck/actions/workflows/ci.yml)
[![License: MIT](https://img.shields.io/badge/License-MIT-6d4bf0.svg)](LICENSE)
[![Node >= 22](https://img.shields.io/badge/node-%3E%3D22-339633?logo=nodedotjs&logoColor=white)](https://nodejs.org)
[![Platforms](https://img.shields.io/badge/platforms-macOS%20%7C%20Linux-555555)](#quick-start)
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-3ddc97)](https://github.com/flashclub/agent-deck/pulls)
[![Zero build](https://img.shields.io/badge/zero_build-no_config-ffcc66)](#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)

Maintenance

ActivityMaintained
ResponsivenessNo issues