Parallel multi-agent TUI — run many AI coding sessions simultaneously, each in its own git worktree.
BeamAgents launches N parallel AI agent sessions (opencode, codex, or any CLI agent), each isolated in its own git worktree under /tmp. A React-based terminal UI lets you monitor all sessions live, inspect diffs, and apply any session's changes back to your working directory — all without leaving the terminal.
┌─────────────────────────────────────────────────────────────────┐
│ BeamAgents TUI [repo: myproject] │
├──────────────────────┬──────────────────────────────────────────┤
│ Sessions │ Terminal / Diff │
│ ──────────────── │ │
│ [1] ● running │ $ opencode run │
│ [2] ● running │ > Analyzing auth.ts... │
│ [3] ✓ done │ > Applying fix to line 42 │
│ [4] ✓ done │ │
│ [5] ● running │ [Enter to toggle diff view] │
│ [6] ✗ error │ │
│ [7] ● running │ + const token = jwt.sign(payload, │
│ [8] ✓ done │ + process.env.JWT_SECRET!); │
│ │ - const token = jwt.sign(payload, ""); │
├──────────────────────┴──────────────────────────────────────────┤
│ F:filter A:apply U:unapply R:restart ?:help Q:quit │
└─────────────────────────────────────────────────────────────────┘
- True parallelism — up to 64 concurrent sessions; configurable
--parallellimit prevents resource exhaustion - Git worktree isolation — each session gets its own branch and working tree; your main workdir is never touched until you explicitly apply
- Smart dirty-workdir handling — auto-stash your uncommitted changes before applying a session's patch; auto-restore on unapply
- Live diff view — press
Enterto toggle between terminal output and a colored unified diff (git diff <baseSha>) - Agent-agnostic — works with
opencode run,codex exec, or any shell command that reads a prompt and writes code - Hook support — run a custom script before each session's agent spawns (environment injection, per-session config, etc.)
| Requirement | Version |
|---|---|
| Bun | ≥ 1.1 |
| Git | ≥ 2.20 (worktree support) |
| opencode or codex | any recent version |
Important: Bun is required.
node/tsxwill not work because the process spawning layer usesBun.spawndirectly.
git clone https://github.com/your-org/BeamAgents
cd BeamAgents
bun install
bun run dev -- -n 4 -p "Fix the bug in auth.ts"bun run build # outputs dist/index.js
# Then run from any directory:
bun dist/index.js -n 8 --agent "opencode run"bun run dev -- -n 4 -p "Refactor error handling in src/api/"# 16 sessions, max 4 running concurrently
bun run dev -- -n 16 --parallel 4 -p "Add JSDoc to all exported functions"bun run dev -- -n 8 --agent "codex exec --sandbox workspace-write" \
--dirty-policy stash -p "Migrate fetch calls to async/await"echo "Identify and fix all TODO comments in the codebase." > prompt.txt
bun run dev -- -n 6 -p prompt.txt --parallel 3bun run dev -- -n 4 --no-cleanup -p "Experiment: add caching layer"Testing tip: Run BeamAgents from a separate project directory, not from the
/workspacesource root. Usebun /path/to/BeamAgents/src/index.tsxrather thanbun run devwhen the current directory matters.
| Key | Action |
|---|---|
↑ / k |
Select previous session |
↓ / j |
Select next session |
Ctrl+W |
Toggle focus: session list ↔ terminal panel |
Enter |
Toggle right panel: terminal output ↔ worktree diff |
F |
Cycle filter: all → running → done → error |
A |
Apply selected session's patch to main workdir (auto-stashes dirty files) |
U |
Unapply patch (Normal or Force; Force = git reset --hard HEAD && git clean -fd) |
X |
Discard ALL workdir changes; does not affect patch tracking state |
R |
Restart an errored session |
? |
Toggle help overlay |
Q |
Quit with full cleanup |
The diff panel (toggled with Enter) and the focus target (toggled with Ctrl+W) are independent — you can browse the diff while the session list retains focus.
pending ──► starting ──► running ──► done
│
├──► needs_input
│
└──► error
applied is an overlay status on top of any terminal state (preserved in _underlyingStatus).
When you press A to apply a session's changes:
- If another patch is currently applied, it is reversed first.
- If the workdir is still dirty (your own changes), they are auto-stashed with
git stash -u. - The session's diff is applied as a patch to the main workdir.
When you press U to unapply:
- Normal: reverses the patch, then pops the auto-stash if one was created.
- Force: runs
git reset --hard HEAD && git clean -fdto remove all changes including new files.
CLI → Agent → Git → TUI → Utils
| Layer | Path | Responsibility |
|---|---|---|
| CLI | src/cli/args.ts |
Arg parsing via commander; produces CliOptions |
| Agent | src/agent/ |
Session lifecycle, PTY management, prompt dispatch |
| Git | src/git/ |
Worktree creation (/tmp/BeamAgents-XXXXXX/) and patch apply/unapply |
| TUI | src/tui/ |
React + @opentui/react renderer, keyboard dispatch, overlays |
| Utils | src/utils/ |
Logger, shell helpers, resource checks, async utilities |
The TUI layer never imports from Agent or Git directly — all backend communication goes through the IAppBus interface (src/events/), keeping the UI fully testable in isolation.
bun run dev -- [options]
| Option | Default | Description |
|---|---|---|
-n, --count <n> |
4 |
Number of agent sessions to create (max 64) |
--parallel <n> |
4 |
Max sessions running concurrently |
-p, --prompt <file|string> |
— | Prompt text or path to a prompt file |
-a, --agent <cmd> |
opencode run |
Agent command to run in each session |
-t, --tmp-dir <path> |
/tmp |
Base directory for worktree temp folders |
--dirty-policy <policy> |
stash |
What to do if workdir is dirty on start: stash, continue, or abort |
--hook <script> |
— | Shell script to run before each session spawns |
--no-cleanup |
— | Keep worktrees and branches when BeamAgents exits |
--no-force-cleanup |
— | Skip auto-removal of existing ma-* branches/worktrees on startup |
| Value | Behavior |
|---|---|
stash |
Auto-stash uncommitted changes before creating worktrees (recommended) |
continue |
Proceed with dirty workdir; worktrees branch from the current index |
abort |
Exit immediately if any uncommitted changes are detected |
bun run dev # Run from source (src/index.tsx)
bun run build # Bundle to dist/ (Bun target)
bun run watch # Dev with file-watching
bun run test # Run all tests (vitest --run)
bun run test:watch # Interactive test mode
bun tsc --noEmit # Type-check only (no emit)Run a single test file:
bun vitest run src/agent/SessionManager.test.tsFor developer internals (design decisions, session state machine details, TUI architecture), see CLAUDE.md.
MIT © BeamAgents contributors