A cross-platform terminal aggregator with multi-workspace support and built-in AI agent integration
Manage multiple project terminals in one window, with a built-in Claude Code agent panel, file browser, git viewer, snippet manager, and remote access — all in a single Electron app.
Claude Code Agent Panel — Built-in AI agent with permission controls, status line, and streaming output

Terminal — Run persistent terminals alongside your agent for long-running commands and monitoring

File Browser — Browse and preview project files without leaving the app

- Multi-Workspace — Organize terminals by project folders; each workspace binds to a directory
- Drag & Drop — Reorder workspaces freely in the sidebar
- Groups — Categorize workspaces into named groups with a filter dropdown
- Profiles — Save and switch between multiple workspace configurations (local or remote)
- Detachable Windows — Pop out individual workspaces to separate windows; auto-reattach on restart
- Per-Workspace Env Vars — Configure custom environment variables per workspace
- Activity Indicators — Visual dots showing which workspaces have active terminal processes
- Double-click to rename, right-click context menu for all workspace actions
- Split-panel layout — 70% main panel + 30% scrollable thumbnail bar showing all terminals
- Multiple terminals per workspace — Powered by xterm.js with full Unicode/CJK support
- Agent presets — Pre-configured terminal roles: Claude Code, Claude Code (worktree), Codex Agent, or plain terminal
- Git worktree isolation — Spawn Claude agents in an isolated worktree to prevent destructive changes to your main working tree
- Tab navigation — Switch between Terminal, Files, and Git views per workspace
- File browser — Search, navigate, and preview files with syntax highlighting (highlight.js)
- Git integration — Commit log, diff viewer, branch display, untracked file list, GitHub link detection
- GitHub panel — Browse PRs and issues directly from the Git tab
- Snippet manager — Save, organize, search, and paste code snippets (SQLite-backed with categories and favorites)
- Markdown preview — Preview
.mdfiles in a dedicated right sidebar panel with live file watching and right-click context menu - Worker panel (Procfile) — Run multiple processes from a Procfile in a single tab with combined log view and per-process start/stop/restart controls, inspired by Overmind
- Per-terminal prompt history — Access previous commands per terminal session
- Built-in Claude Code via SDK — Runs the agent directly inside the app; no separate terminal needed
- Message streaming with extended thinking blocks (collapsible)
- Permission modes — Multiple levels of tool execution control:
- Default — Approve each tool call individually
- Accept Edits — Auto-approve file edits, prompt for other tools
- Plan mode — Agent proposes a plan file first; approve the plan to auto-execute
- Bypass — Full auto-approval (use with caution)
- Subagent tracking — See spawned subagent tasks with progress indicators, elapsed time, and stall detection
- Session resume — Persist conversations and resume them across app restarts
- Session fork — Branch off from any point in a conversation with pending prompt auto-send
- Rest/Wake sessions — Pause and resume agent sessions from the context menu to save resources
- Effort level — Configure default effort level (high/medium/low) for new agent sessions
- Auto-compact — Automatically compact context when token count exceeds a configurable threshold
A configurable status bar at the bottom of the agent panel, with 15 items across three zones (left / center / right):
| Item | Description |
|---|---|
| Session ID | First 8 chars of SDK session ID (click to resume a past session) |
| Git Branch | Current git branch name |
| Tokens | Total input + output token count (click for context breakdown) |
| Turns | Number of conversation turns |
| Duration | Session duration |
| Context % | Percentage of context window used (color-coded) |
| Cost | Total session cost in USD |
| Workspace | Current workspace name |
| 5h Usage / Reset | 5-hour API rate limit usage and reset countdown |
| 7d Usage / Reset | 7-day API rate limit usage and reset countdown |
| Max Output | Maximum output tokens for current model |
| Cache Eff. | Cache read efficiency percentage (click for cache history with per-turn cost breakdown) |
| Prompts | Link to view prompt history |
Items can be reordered, colored, and toggled on/off via a drag-and-drop template editor in Settings.
- Cache history — Per-turn cache read/write breakdown with cost calculations per model (Opus, Sonnet, Haiku)
- Cache TTL countdown — Optional floating badge in the top-right corner showing remaining time for 5-minute and 1-hour cache TTLs; updates every 30 seconds, only appears after 1 minute of idle
- Cache expiry warning — Pre-send confirmation dialog when >150k cached tokens have expired (>1 hour), preventing accidental full-price reprocessing
- Multi-account switching —
/switchto manage and switch between multiple Claude accounts - Usage monitoring — Track API rate limits (5-hour and 7-day windows) via Anthropic OAuth or Chrome session key
- Context usage panel — Visualize token usage breakdown by category (code, conversation, tools, memory, MCP, etc.)
- Image attachment — Drag-drop or use the attach button (up to 5 images per message)
- Clickable URLs — Markdown links and bare URLs open in the default browser
- Clickable file paths — Click any file path in agent output to preview it with syntax highlighting and search (Ctrl+F)
- Ctrl+P file picker — Fuzzy-search project files and attach them to the conversation context
- Skills & Agents panels — Browse available slash commands and agent configurations in the right sidebar
- Notifications — Dock badge, sound, and system notifications on agent completion (configurable)
- Update notifications — Automatic check for new releases on GitHub
- English, Traditional Chinese (繁體中文), Simplified Chinese (简体中文)
| Shortcut | Action |
|---|---|
Ctrl+`` / `Cmd+ ` `` |
Toggle between Agent terminal and first regular terminal |
Ctrl+←/→ / Cmd+←/→ |
Cycle workspace tabs (Terminal / Files / Git) |
Ctrl+↑/↓ / Cmd+↑/↓ |
Switch to previous / next workspace |
Ctrl+P / Cmd+P |
File picker (search & attach files to agent context) |
Ctrl+N / Cmd+N |
Open new window |
Shift+Tab |
Switch between Terminal and Agent mode |
Enter |
Send message |
Shift+Enter |
Insert newline (multiline input) |
Escape |
Stop streaming / close modal |
Ctrl+Shift+C |
Copy selected text |
Ctrl+Shift+V |
Paste from clipboard |
Right-click |
Copy (if text selected) or Paste |
| Command | Description |
|---|---|
/resume |
Resume a previous Claude session from history |
/model |
Switch between available Claude models |
/new / /clear |
Reset session (clear conversation, fresh start) |
/abort |
Stop the current agent session immediately |
/snippet |
Show snippets to Claude for management |
/switch |
Switch between Claude accounts |
/login |
Sign in to Claude (switch account) |
/logout |
Sign out of Claude |
/whoami |
Show current account info and usage |
brew install --cask tonyq-org/tap/better-agent-terminalchoco install better-agent-terminalPackage is currently pending review on Chocolatey.org.
Download from Releases for your platform:
| Platform | Format |
|---|---|
| Windows | NSIS installer, .zip |
| macOS | .dmg (universal binary) |
| Linux | .AppImage |
macOS DMG installation:
- Download the
.dmgfile from Releases - Double-click the
.dmgto mount it - Drag Better Agent Terminal into the Applications folder
- On first launch, macOS may block the app — go to System Settings > Privacy & Security, scroll down and click Open Anyway
- Make sure Claude Code CLI is installed (
npm install -g @anthropic-ai/claude-code)
Prerequisites:
- Node.js 18+
- Claude Code CLI installed and authenticated
git clone https://github.com/tony1223/better-agent-terminal.git
cd better-agent-terminal
npm installDevelopment mode:
npm run devBuild for production:
npm run buildRun the following command in your terminal (macOS, Linux, or Windows with Git Bash/MSYS2):
curl -fsSL https://raw.githubusercontent.com/tony1223/better-agent-terminal/main/install.sh | bashThis script will detect your OS and install the application to the standard location.
Native dependencies (node-pty, better-sqlite3) require Xcode Command Line Tools:
xcode-select --installThen:
npm install
npm run dev # Development
npm run build # Build .dmgbetter-agent-terminal/
├── electron/ # Main process (Node.js)
│ ├── main.ts # App entry, IPC handlers, window management
│ ├── preload.ts # Context bridge (window.electronAPI)
│ ├── pty-manager.ts # PTY process lifecycle, multi-window broadcast
│ ├── claude-agent-manager.ts # Claude SDK session management
│ ├── codex-agent-manager.ts # Codex/OpenAI agent integration
│ ├── worktree-manager.ts # Git worktree lifecycle (create, remove, rehydrate)
│ ├── account-manager.ts # Multi-account switching infrastructure
│ ├── window-registry.ts # Multi-window management
│ ├── logger.ts # Disk-based logger (enable with BAT_DEBUG=1)
│ ├── snippet-db.ts # SQLite snippet storage
│ ├── profile-manager.ts # Profile CRUD and persistence
│ ├── node-resolver.ts # Node.js dependency resolution
│ ├── update-checker.ts # GitHub release update check
│ └── remote/
│ ├── protocol.ts # Proxied channel/event definitions
│ ├── handler-registry.ts # Unified IPC + remote handler registry
│ ├── broadcast-hub.ts # Event broadcasting to remote clients
│ ├── remote-server.ts # WebSocket server (host mode)
│ ├── remote-client.ts # WebSocket client (connect mode)
│ └── tunnel-manager.ts # IP detection, Tailscale, QR code info
├── src/ # Renderer process (React)
│ ├── App.tsx # Root component, layout, profile orchestration
│ ├── components/
│ │ ├── Sidebar.tsx # Workspace list, groups, drag-drop, context menu
│ │ ├── WorkspaceView.tsx # Per-workspace container
│ │ ├── ClaudeAgentPanel.tsx # Claude agent chat UI, streaming, cache tracking
│ │ ├── TerminalPanel.tsx # xterm.js terminal wrapper
│ │ ├── ThumbnailBar.tsx # Scrollable terminal thumbnail strip
│ │ ├── MainPanel.tsx # Tab container (Terminal / Files / Git)
│ │ ├── GitPanel.tsx # Git log, diff, status viewer
│ │ ├── GitHubPanel.tsx # GitHub PR/Issue browser
│ │ ├── FileTree.tsx # In-app file browser with markdown preview
│ │ ├── PathLinker.tsx # Clickable file paths & URLs, preview modal
│ │ ├── MarkdownPreviewPanel.tsx # Markdown preview sidebar with live reload
│ │ ├── SnippetPanel.tsx # Snippet manager sidebar
│ │ ├── SkillsPanel.tsx # Skills/commands reference panel
│ │ ├── AgentsPanel.tsx # Agent configurations panel
│ │ ├── WorkerPanel.tsx # Procfile multi-process runner
│ │ ├── PromptBox.tsx # Agent message input with image attach
│ │ ├── SettingsPanel.tsx # App settings UI
│ │ ├── ProfilePanel.tsx # Profile switcher
│ │ ├── AboutPanel.tsx # About dialog
│ │ ├── EnvVarEditor.tsx # Per-workspace env var editor
│ │ ├── WorkspaceEnvDialog.tsx # Workspace env var dialog
│ │ ├── CloseConfirmDialog.tsx # Worktree cleanup confirmation
│ │ ├── ResizeHandle.tsx # Resizable panel divider
│ │ └── UpdateNotification.tsx # Update banner
│ ├── stores/
│ │ ├── workspace-store.ts # Workspace + terminal state (pub/sub)
│ │ └── settings-store.ts # App settings persistence
│ ├── locales/
│ │ ├── en.json # English
│ │ ├── zh-TW.json # Traditional Chinese
│ │ └── zh-CN.json # Simplified Chinese
│ ├── types/
│ │ ├── index.ts # Core types (Workspace, AppSettings, Statusline, etc.)
│ │ ├── claude-agent.ts # Claude message, tool call, and thinking types
│ │ ├── agent-presets.ts # Agent preset definitions
│ │ └── electron.d.ts # window.electronAPI type declarations
│ └── styles/
│ ├── main.css
│ ├── claude-agent.css
│ ├── path-linker.css
│ ├── context-menu.css
│ └── ... # Component-specific styles
├── assets/ # App icons and screenshots
├── scripts/
│ └── build-version.js # Version string generator
└── package.json
- Frontend: React 18 + TypeScript + i18next (EN / zh-TW / zh-CN)
- Terminal: xterm.js + node-pty
- Framework: Electron 28
- AI: @anthropic-ai/claude-agent-sdk
- Build: Vite 5 + electron-builder
- Storage: better-sqlite3 (snippets, session data)
- Remote: ws (WebSocket) + qrcode
- Syntax Highlighting: highlight.js
BAT includes a built-in WebSocket server that allows other BAT instances or mobile devices to connect and control it remotely. This feature is currently experimental.
- The Host enables the WebSocket server in Settings → Remote Access (default port: 9876)
- On startup, the server generates a Connection Token (32-character hex string) used to authenticate connections
- The Client connects by entering the host IP, port, and token via a Remote Profile
- Once connected, the client can operate all terminals, Claude Agent sessions, workspaces, and other features on the host
On the client BAT instance:
- Open Settings → Profiles
- Create a new profile and set the type to Remote
- Enter the host IP, port (9876), and token
- Load the profile to connect to the remote host
On the host BAT instance:
- Open Settings → Remote Access → Generate QR Code
- If the server is not yet running, it will start automatically
- Scan the QR code with a mobile device to retrieve the connection info
- The QR code contains the WebSocket URL and token (in JSON format)
If the host and client are not on the same local network (e.g., connecting from home to an office machine), we recommend using Tailscale to establish a secure peer-to-peer VPN:
- Free plan supports up to 100 devices
- No port forwarding or additional server setup required
- Each device gets a stable
100.x.x.xIP address - BAT automatically detects Tailscale IPs and uses them preferentially
Installation:
| Platform | Install |
|---|---|
| macOS | Download or brew install tailscale |
| Windows | Download |
| iOS | App Store |
| Android | Google Play |
| Linux | Install Guide |
After installation, sign in with the same account on all devices and they will be able to communicate. BAT's QR code will automatically use the Tailscale IP.
Warning: Enabling the Remote Server opens a WebSocket connection. Any device with the token can fully control BAT on the host machine, including executing terminal commands, accessing the file system, and controlling Claude Agent sessions.
- Do not start the server on untrusted networks
- Do not share the token with untrusted parties
- Shut down the server when not in use
- Strongly recommended to use Tailscale to avoid direct exposure to the public internet
You can also run the same WebSocket server without launching the GUI — useful for VPS, containers, or background services. The headless entry uses BAT's bundled Node runtime, so no separate node.exe install is required.
The installer drops bat-server.cmd next to BetterAgentTerminal.exe (typically %LOCALAPPDATA%\Programs\BetterAgentTerminal\):
"%LOCALAPPDATA%\Programs\BetterAgentTerminal\bat-server.cmd" --bind=all --port=9876Add the install directory to PATH to call it as just bat-server. Stdout prints the connection URL, token, and certificate fingerprint on startup.
The app bundle ships a bat-server shell wrapper inside Contents/Resources/:
/Applications/BetterAgentTerminal.app/Contents/Resources/bat-server --bind=tailscale --port=9876For convenience, symlink it onto your PATH:
sudo ln -sf /Applications/BetterAgentTerminal.app/Contents/Resources/bat-server /usr/local/bin/bat-server
bat-server --bind=all --port=9876If the shell wrapper isn't executable (rare, depends on the installer), invoke it via bash:
bash /Applications/BetterAgentTerminal.app/Contents/Resources/bat-server --bind=allAppImages mount themselves read-only at runtime, so the simplest path is to extract once and call the wrapper inside:
chmod +x BetterAgentTerminal-*.AppImage
./BetterAgentTerminal-*.AppImage --appimage-extract
./squashfs-root/resources/bat-server --bind=all --port=9876You can move squashfs-root/ anywhere stable (e.g. /opt/better-agent-terminal/) and symlink the wrapper onto your PATH:
sudo mv squashfs-root /opt/better-agent-terminal
sudo ln -sf /opt/better-agent-terminal/resources/bat-server /usr/local/bin/bat-serverClone the repo and run the bundled npm script — handy for development or when you don't want to install the GUI build:
git clone https://github.com/tony1223/better-agent-terminal.git
cd better-agent-terminal
npm install
npm run compile
npm run start:server -- --bind=all --port=9876--port=N TCP port to listen on (default: 9876)
--bind=IFACE localhost | tailscale | all (default: localhost)
--data-dir=PATH persistent state directory (default: same as the GUI)
--token=HEX pin a known token (default: persisted or random)
--debug write debug.log inside data-dir
-h, --help show this help
Environment variable equivalents: BAT_PORT, BAT_BIND, BAT_DATA_DIR, BAT_TOKEN, BAT_DEBUG.
Note: Headless mode runs without the OS keychain, so persisted tokens are stored in plaintext under
--data-dir. Treat that directory like any other secret.
Workspaces, settings, and session data are saved to:
| Platform | Path |
|---|---|
| Windows | %APPDATA%/better-agent-terminal/ |
| macOS | ~/Library/Application Support/better-agent-terminal/ |
| Linux | ~/.config/better-agent-terminal/ |
Set the BAT_DEBUG=1 environment variable to enable disk-based debug logging. Logs are written to debug.log in the configuration directory.
Follows semantic versioning: vMAJOR.MINOR.PATCH (e.g., v2.1.41)
Pre-release versions use the -pre.N suffix (e.g., v2.1.42-pre.1). Tags containing -pre are automatically marked as pre-release on GitHub and do not update the Homebrew tap.
Push a tag to trigger builds for all platforms:
git tag v2.1.42
git push origin v2.1.42MIT License - see LICENSE for details.
TonyQ - @tony1223
- lmanchu - @lmanchu - macOS/Linux support, workspace roles
- bluewings1211 - @bluewings1211 - Shift+Enter newline, preserve workspace state, resizable panels
- Henry Hu - @ninedter - Key API discovery and valuable architectural feedback
- craze429 - @craze429 - Windows/Linux credential reading, permission fix, git parsing fix, async dialog
- Owen - @Owen0857 - Windows zombie process fix, terminal resize black screen fix, debug log cleanup
- MikeThai - @mikethai - macOS .dmg spawn ENOENT fix
- Luke Chang - @lukeme117 - Snippet sidebar and UI improvements
- Overmind — Inspired our Worker panel and Procfile-based multi-process management integration
Built with Claude Code
