Agent of Empires
A terminal session manager for AI coding agents on Linux and macOS, built on tmux and written in Rust.
AoE lets you run multiple AI agents in parallel -- each in its own tmux session, optionally on its own git branch, optionally inside a Docker container. A TUI dashboard shows you what every agent is doing at a glance.

Why AoE?
The problem: You're working with AI coding agents (Claude Code, OpenCode, Codex, etc.) and want to run several in parallel across different tasks or branches. Managing multiple terminal windows, git branches, and container lifecycles by hand gets tedious fast.
AoE handles it for you:
- One dashboard for all agents. See status (running, waiting, idle, error) at a glance. Toggle to paired shell terminals with
t. - Git worktrees built in. Create a session and AoE creates a branch + worktree automatically. Delete the session and AoE cleans up.
- Docker sandboxing. Run agents in isolated containers with your project mounted and auth credentials shared across containers.
- Per-repo configuration. Drop a
.aoe/config.tomlin your repo for project-specific settings and hooks that run on session creation or launch. - Sessions survive everything. AoE wraps tmux, so agents keep running when you close the TUI, disconnect SSH, or your terminal crashes.
Supported Agents
Claude Code, OpenCode, Mistral Vibe, Codex CLI, and Gemini CLI. AoE auto-detects which are installed.
Documentation
Getting Started
- Installation -- prerequisites and install methods
- Quick Start -- create your first session in under a minute
Guides
- Workflow Guide -- recommended setup with bare repos and worktrees
- Docker Sandbox -- container isolation, images, and volume mounts
- Repo Config & Hooks -- per-project settings and automation
- Git Worktrees -- branch management and worktree templates
- Diff View -- review and edit git changes in the TUI
- tmux Status Bar -- session info in your tmux status line
Reference
- CLI Reference -- every command and flag
- Configuration Reference -- all config options (global, profile, repo-level)
Contributing
- Development -- building, testing, and generating demo assets
Installation
Prerequisites
Install Agent of Empires
Quick Install (Recommended)
Run the install script:
curl -fsSL \
https://raw.githubusercontent.com/njbrake/agent-of-empires/main/scripts/install.sh \
| bash
Homebrew
brew install njbrake/aoe/aoe
Update via brew update && brew upgrade aoe.
Build from Source
git clone https://github.com/njbrake/agent-of-empires
cd agent-of-empires
cargo build --release
The binary will be at target/release/aoe.
Verify Installation
aoe --version
Uninstall
To remove Agent of Empires:
aoe uninstall
This will guide you through removing the binary, configuration, and tmux settings.
Quick Start
Launch the TUI
aoe
This opens the dashboard. You'll see an empty session list on first run.
Create Your First Session
From the TUI: Press n to open the new session dialog. Fill in the path to your project (or leave it as . for the current directory) and press Enter.
From the CLI:
aoe add /path/to/project
The session appears in the dashboard with status Idle.
Attach to a Session
Select a session and press Enter to attach. You're now inside a tmux session running your AI agent (Claude Code by default).
To return to the TUI, press Ctrl+b d (the standard tmux detach shortcut).
Use the Terminal View
Press t to toggle between Agent View and Terminal View. Each agent session has a paired shell terminal where you can run builds, tests, and git commands without interrupting the agent.
Review Changes with Diff View
Press D to open the diff view. This shows changes between your working directory and the base branch. Navigate files with j/k, press e to edit, and Esc to close.
Create a Worktree Session
To work on a new branch with its own directory:
# CLI
aoe add . -w feat/my-feature -b
# TUI: press n, fill in the worktree branch field
This creates a new git branch, a worktree directory, and a session pointing at it. When you delete the session, AoE offers to clean up the worktree too.
Create a Sandboxed Session
To run an agent inside a Docker container:
aoe add --sandbox .
In the TUI, toggle the sandbox checkbox when creating a session. The agent runs in an isolated container with your project mounted at /workspace and authentication credentials shared via persistent Docker volumes.
Requires Docker to be installed.
Choose a Different Agent
By default, AoE uses Claude Code. To use a different tool:
aoe add -c opencode .
aoe add -c vibe .
aoe add -c codex .
aoe add -c gemini .
In the TUI, select the tool from the dropdown in the new session dialog.
TUI Keyboard Reference
| Key | Action |
|---|---|
n | New session |
Enter | Attach to session |
d | Delete session |
t | Toggle Agent/Terminal view |
D | Open diff view |
/ | Search sessions |
? | Show help |
q | Quit |
Ctrl+b d | Detach from tmux session |
Next Steps
- Workflow Guide -- recommended setup with bare repos and parallel agents
- Docker Sandbox -- container configuration and custom images
- Repo Config & Hooks -- per-project settings
- CLI Reference -- every command and flag
Workflow Guide
This guide covers the recommended setup and daily workflow for using aoe with git worktrees.
Project Setup: Bare Git Repos
The recommended way to set up a project is using a "bare repo" structure. This keeps your main repository and all worktrees organized under a single directory:
my-project/
.bare/ # Bare git repository
.git # File pointing to .bare
main/ # Worktree for main branch
feat-api/ # Worktree for feature branch
fix-bug/ # Another worktree
Initial Setup
# Clone as bare repo
git clone --bare git@github.com:user/repo.git my-project/.bare
cd my-project
# Create .git file pointing to bare repo
echo "gitdir: ./.bare" > .git
# Configure fetch to get all branches
git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
git fetch origin
# Create your main worktree
git worktree add main main
Now when you run aoe from my-project/, new worktrees are created as siblings (e.g., my-project/feat-api/) rather than in a separate directory.
Why Bare Repos?
- Clean organization: Everything lives under one project directory
- Sandbox-friendly: All paths stay within the project root (important for Docker sandboxing)
- Easy navigation: Switch between branches by switching directories
Single-Window Workflow
Run aoe in a single terminal and toggle between views:
| Key | View | Purpose |
|---|---|---|
| (default) | Agent View | Manage and interact with AI coding agents |
t | Terminal View | Access paired terminals for git, builds, tests |
Daily Workflow
1. Start your day
cd ~/scm/my-project
aoe
You'll see your sessions in Agent View. Keep one session on main for general questions and pulling updates.
2. Update main (Terminal View)
- Press
tto switch to Terminal View - Select your main session, press
Enterto attach to its terminal - Run
git pull origin main - Detach with
Ctrl+b d - Press
tto return to Agent View
3. Create a new session
- Press
nto open the new session dialog - Fill in the worktree field with your branch name (e.g.,
feat/auth-refactor) - Press
Enter
This creates:
- A new branch from your current HEAD
- A new worktree at
./feat-auth-refactor/ - A new session with an agent working in that worktree
4. Work on your feature (Agent View)
- Select your session and press
Enterto attach - Interact with the agent
- Detach with
Ctrl+b dwhen done
5. Run builds/tests (Terminal View)
- Press
tto switch to Terminal View - Select the same session, press
Enter - Run your build commands, tests, git operations
- Detach with
Ctrl+b d
6. Clean up when done
- In Agent View, select the session and press
dto delete - Answer
Yto also remove the worktree
Tips
- Keep one session on main: Use it for codebase questions and its terminal for
git pull - One task, one session: Each worktree maps to one aoe session. Keeps context isolated.
- Pull before creating: Always update main before creating new sessions so branches start fresh
- Let agents stay focused: Git operations happen in the paired terminal, not in agent sessions
Keyboard Reference
| Key | Action |
|---|---|
t | Toggle between Agent View and Terminal View |
D | Open Diff View to review git changes |
Enter | Attach to agent (Agent View) or terminal (Terminal View) |
n | Create new session |
d | Delete session (Agent View only) |
? | Show help |
Ctrl+b d | Detach from tmux (return to aoe) |
Non-Bare Repos
If you're not using a bare repo setup, aoe defaults to creating worktrees in a sibling directory:
~/scm/
my-project/ # Your repo (stays on main)
my-project-worktrees/ # Worktrees created here
feat-auth-refactor/
fix-bug/
You can customize this with path_template in your config. See the Worktrees Reference for details.
Docker Sandbox: Quick Reference
Overview
Docker sandboxing runs your AI coding agents (Claude Code, OpenCode, Mistral Vibe, Codex CLI, Gemini CLI) inside isolated Docker containers while maintaining access to your project files and credentials.
Key Features:
- One container per session
- Shared authentication across containers (no re-auth needed)
- Automatic container lifecycle management
- Full project access via volume mounts
CLI vs TUI Behavior
| Feature | CLI | TUI |
|---|---|---|
| Enable sandbox | --sandbox flag | Checkbox toggle |
| Custom image | --sandbox-image <image> | Not supported |
| Container cleanup | Automatic on remove | Automatic on remove |
| Keep container | --keep-container flag | Not supported |
One-Liner Commands
# Create sandboxed session
aoe add --sandbox .
# Create sandboxed session with custom image
aoe add --sandbox-image myregistry/custom:v1 .
# Create and launch sandboxed session
aoe add --sandbox -l .
# Remove session (auto-cleans container)
aoe remove <session>
# Remove session but keep container
aoe remove <session> --keep-container
Note: In the TUI, the sandbox checkbox only appears when Docker is available on your system.
Default Configuration
[sandbox]
enabled_by_default = false
yolo_mode_default = false
default_image = "ghcr.io/njbrake/aoe-sandbox:latest"
auto_cleanup = true
cpu_limit = "4"
memory_limit = "8g"
environment = ["ANTHROPIC_API_KEY"]
Configuration Options
| Option | Default | Description |
|---|---|---|
enabled_by_default | false | Auto-enable sandbox for new sessions |
yolo_mode_default | false | Skip agent permission prompts in sandboxed sessions |
default_image | ghcr.io/njbrake/aoe-sandbox:latest | Docker image to use |
auto_cleanup | true | Remove containers when sessions are deleted |
cpu_limit | (none) | CPU limit (e.g., "4") |
memory_limit | (none) | Memory limit (e.g., "8g") |
environment | [] | Env var names to pass through from host |
environment_values | {} | Env vars with explicit values to inject (see below) |
volume_ignores | [] | Directories to exclude from the project mount via anonymous volumes |
extra_volumes | [] | Additional volume mounts |
default_terminal_mode | "host" | Paired terminal location: "host" (on host machine) or "container" (inside Docker) |
Volume Mounts
Automatic Mounts
| Host Path | Container Path | Mode | Purpose |
|---|---|---|---|
| Project directory | /workspace | RW | Your code |
~/.gitconfig | /root/.gitconfig | RO | Git config |
~/.ssh/ | /root/.ssh/ | RO | SSH keys |
~/.config/opencode/ | /root/.config/opencode/ | RO | OpenCode config |
~/.vibe/ | /root/.vibe/ | RW | Vibe config (if exists) |
Persistent Auth Volumes
| Volume Name | Container Path | Purpose |
|---|---|---|
aoe-claude-auth | /root/.claude/ | Claude Code credentials |
aoe-opencode-auth | /root/.local/share/opencode/ | OpenCode credentials |
aoe-vibe-auth | /root/.vibe/ | Mistral Vibe credentials |
aoe-codex-auth | /root/.codex/ | Codex CLI credentials |
aoe-gemini-auth | /root/.gemini/ | Gemini CLI credentials |
Note: Auth persists across containers. First session requires authentication, subsequent sessions reuse it.
Container Naming
Containers are named: aoe-sandbox-{session_id_first_8_chars}
Example: aoe-sandbox-a1b2c3d4
How It Works
- Session Creation: When you add a sandboxed session, aoe records the sandbox configuration
- Container Start: When you start the session, aoe creates/starts the Docker container with appropriate volume mounts
- tmux + docker exec: Host tmux runs
docker exec -it <container> <tool>(claude, opencode, vibe, codex, or gemini) - Cleanup: When you remove the session, the container is automatically deleted
Environment Variables
These terminal-related variables are always passed through for proper UI/theming:
TERM,COLORTERM,FORCE_COLOR,NO_COLOR
Pass additional variables (like API keys) through containers by adding them to config:
[sandbox]
environment = ["ANTHROPIC_API_KEY", "OPENAI_API_KEY", "GEMINI_API_KEY"]
These variables are read from your host environment and passed to containers (in addition to the terminal defaults above).
Sandbox-Specific Values (environment_values)
Use environment_values to inject env vars with values that AOE manages directly, independent of your host environment. This is useful for giving sandboxes credentials that differ from (or don't exist on) the host:
[sandbox.environment_values]
GH_TOKEN = "ghp_sandbox_scoped_token"
CUSTOM_API_KEY = "sk-sandbox-only-key"
Values starting with $ are read from a host env var instead of being used literally. This lets you store the actual secret in your shell profile rather than in the AOE config file:
[sandbox.environment_values]
GH_TOKEN = "$AOE_GH_TOKEN" # reads AOE_GH_TOKEN from host, injects as GH_TOKEN
# In your .bashrc / .zshrc
export AOE_GH_TOKEN="ghp_sandbox_scoped_token"
If the referenced host env var is not set, the entry is silently skipped.
To use a literal value starting with $, double it: $$LITERAL is injected as $LITERAL.
Available Images
AOE provides two official sandbox images:
| Image | Description |
|---|---|
ghcr.io/njbrake/aoe-sandbox:latest | Base image with Claude Code, OpenCode, Mistral Vibe, Codex CLI, Gemini CLI, git, ripgrep, fzf |
ghcr.io/njbrake/aoe-dev-sandbox:latest | Extended image with additional dev tools |
Dev Sandbox Tools
The dev sandbox (aoe-dev-sandbox) includes everything in the base image plus:
- Rust (rustup, cargo, rustc)
- uv (fast Python package manager)
- Node.js LTS (via nvm, with npm and npx)
- GitHub CLI (gh)
To use the dev sandbox:
# Per-session
aoe add --sandbox-image ghcr.io/njbrake/aoe-dev-sandbox:latest .
# Or set as default in ~/.agent-of-empires/config.toml
[sandbox]
default_image = "ghcr.io/njbrake/aoe-dev-sandbox:latest"
Custom Docker Images
The default sandbox image includes Claude Code, OpenCode, Mistral Vibe, Codex CLI, Gemini CLI, git, and basic development tools. For projects requiring additional dependencies beyond what the dev sandbox provides, you can extend either base image.
Step 1: Create a Dockerfile
Create a Dockerfile in your project (or a shared location):
FROM ghcr.io/njbrake/aoe-sandbox:latest
# Example: Add Python for a data science project
RUN apt-get update && apt-get install -y \
python3 \
python3-pip \
python3-venv \
&& rm -rf /var/lib/apt/lists/*
# Install Python packages
RUN pip3 install --break-system-packages \
pandas \
numpy \
requests
Step 2: Build Your Image
# Build locally
docker build -t my-sandbox:latest .
# Or build and push to a registry
docker build -t ghcr.io/yourusername/my-sandbox:latest .
docker push ghcr.io/yourusername/my-sandbox:latest
Step 3: Configure AOE to Use Your Image
Option A: Set as default for all sessions
Add to ~/.agent-of-empires/config.toml:
[sandbox]
default_image = "my-sandbox:latest"
# Or with registry:
# default_image = "ghcr.io/yourusername/my-sandbox:latest"
Option B: Use per-session via CLI
aoe add --sandbox-image my-sandbox:latest .
Worktrees and Sandboxing
When using git worktrees with sandboxing, there's an important consideration: worktrees have a .git file that points back to the main repository's git directory. If this reference points outside the sandboxed directory, git operations inside the container may fail.
The Problem
With the default worktree template (../{repo-name}-worktrees/{branch}):
/projects/
my-repo/
.git/ # Main repo's git directory
src/
my-repo-worktrees/
feature-branch/
.git # FILE pointing to /projects/my-repo/.git/...
src/
When sandboxing feature-branch/, the container can't access /projects/my-repo/.git/.
The Solution: Bare Repo Pattern
Use the linked worktree bare repo pattern to keep everything in one directory:
/projects/my-repo/
.bare/ # Bare git repository
.git # FILE: "gitdir: ./.bare"
main/ # Worktree (main branch)
feature/ # Worktree (feature branch)
Now when sandboxing feature/, the container has access to the sibling .bare/ directory.
AOE automatically detects bare repo setups and uses ./{branch} as the default worktree path template, keeping new worktrees as siblings.
Quick Setup
# Convert existing repo to bare repo pattern
cd my-project
mv .git .bare
echo "gitdir: ./.bare" > .git
# Or clone fresh as bare
git clone --bare git@github.com:user/repo.git my-project/.bare
cd my-project
echo "gitdir: ./.bare" > .git
git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
git fetch origin
git worktree add main main
See the Workflow Guide for detailed bare repo setup instructions.
Repository Configuration & Hooks
AoE supports per-repo configuration via a .aoe/config.toml file in your project root. This lets you define project-specific defaults and hooks that apply to every team member using AoE on that repo.
Getting Started
Generate a template config:
aoe init
This creates .aoe/config.toml with commented-out examples. Edit the file to enable the settings you need.
Configuration Sections
Hooks
Hooks run shell commands at specific points in the session lifecycle.
[hooks]
# Run once when a session is first created (failures abort creation)
on_create = ["npm install", "cp .env.example .env"]
# Run every time a session starts (failures are logged but non-fatal)
on_launch = ["npm install"]
on_create runs only once, when the session is first created. If any command fails, session creation is aborted. Use this for one-time setup like installing dependencies or generating config files.
on_launch runs every time a session starts (including the first time, and every restart). Failures are logged as warnings but don't prevent the session from starting. Use this for things like ensuring dependencies are up to date.
For sandboxed sessions, hooks run inside the Docker container.
Session
[session]
default_tool = "opencode" # Override the default agent for this repo
Available tools: claude, opencode, vibe, codex, gemini.
Sandbox
Override sandbox settings for this repo:
[sandbox]
enabled_by_default = true
default_image = "ghcr.io/njbrake/aoe-dev-sandbox:latest"
environment = ["NODE_ENV", "DATABASE_URL"]
environment_values = { CUSTOM_KEY = "value" }
volume_ignores = ["node_modules", ".next", "target"]
extra_volumes = ["/data:/data:ro"]
cpu_limit = "8"
memory_limit = "16g"
auto_cleanup = true
default_terminal_mode = "host" # "host" or "container"
Worktree
Override worktree settings for this repo:
[worktree]
enabled = true
path_template = "../{repo-name}-worktrees/{branch}"
bare_repo_path_template = "./{branch}"
auto_cleanup = true
show_branch_in_tui = true
delete_branch_on_cleanup = false
Hook Trust System
When AoE encounters hooks in a repo for the first time, it prompts you to review and approve them before execution. This prevents untrusted repos from running arbitrary commands.
- Trust decisions are stored globally (shared across all profiles)
- If hook commands change (e.g., someone updates
.aoe/config.toml), AoE prompts for re-approval - Use
--trust-hookswithaoe addto skip the trust prompt (useful for CI or repos you control)
# Trust hooks automatically
aoe add --trust-hooks .
Config Precedence
Settings are resolved in this order (later overrides earlier):
- Global config (
~/.agent-of-empires/config.toml) - Profile config (
~/.agent-of-empires/profiles/<name>/config.toml) - Repo config (
.aoe/config.toml)
Only settings that are explicitly set in the repo config override the global/profile values. Unset fields inherit from the higher-level config.
Example: Full Repo Config
[hooks]
on_create = ["npm install", "npx prisma generate"]
on_launch = ["npm install"]
[session]
default_tool = "claude"
[sandbox]
enabled_by_default = true
default_image = "ghcr.io/njbrake/aoe-dev-sandbox:latest"
environment = ["DATABASE_URL", "REDIS_URL"]
environment_values = { NODE_ENV = "development" }
volume_ignores = ["node_modules", ".next"]
[worktree]
enabled = true
Checking Into Version Control
The .aoe/config.toml file is meant to be committed to your repo so the entire team shares the same configuration. The hook trust system ensures that each developer explicitly approves hook commands before they run.
Worktrees Reference
Reference documentation for git worktree commands and configuration in aoe.
For workflow guidance, see the Workflow Guide.
CLI vs TUI Behavior
| Feature | CLI | TUI |
|---|---|---|
| Create new branch | Use -b flag | Always creates new branch |
| Use existing branch | Omit -b flag | Not supported |
| Branch validation | Checks if branch exists | None (always creates) |
CLI Commands
# Create worktree session (new branch)
aoe add . -w feat/my-feature -b
# Create worktree session (existing branch)
aoe add . -w feat/my-feature
# List all worktrees
aoe worktree list
# Show session info
aoe worktree info <session>
# Find orphaned worktrees
aoe worktree cleanup
# Remove session (prompts for worktree cleanup)
aoe remove <session>
# Remove session (keep worktree)
aoe remove <session> --keep-worktree
TUI Keyboard Shortcuts
| Key | Action |
|---|---|
n | New session dialog |
Tab | Next field |
Shift+Tab | Previous field |
Enter | Submit and create session |
Esc | Cancel |
When creating a session with a worktree branch name in the TUI, it automatically creates a new branch and worktree.
Configuration
[worktree]
enabled = false
path_template = "../{repo-name}-worktrees/{branch}"
bare_repo_path_template = "./{branch}"
auto_cleanup = true
show_branch_in_tui = true
delete_branch_on_cleanup = false
Template Variables
| Variable | Description |
|---|---|
{repo-name} | Repository folder name |
{branch} | Branch name (slashes converted to hyphens) |
{session-id} | First 8 characters of session UUID |
Path Template Examples
# Default (sibling directory) - used for non-bare repos
path_template = "../{repo-name}-worktrees/{branch}"
# Bare repo default (worktrees as siblings)
bare_repo_path_template = "./{branch}"
# Nested in repo
path_template = "./worktrees/{branch}"
# Absolute path
path_template = "/absolute/path/to/worktrees/{repo-name}/{branch}"
# With session ID for uniqueness
path_template = "../wt/{branch}-{session-id}"
Cleanup Behavior
| Scenario | Cleanup Prompt? |
|---|---|
| aoe-managed worktree | Yes |
| Manual worktree | No |
--keep-worktree flag | No (skips prompt) |
| Non-worktree session | No |
Auto-Detection
AOE automatically detects bare repos and uses bare_repo_path_template instead of path_template, creating worktrees as siblings within the project directory.
File Locations
| Item | Path |
|---|---|
| Config | ~/.agent-of-empires/config.toml |
| Sessions | ~/.agent-of-empires/profiles/<profile>/sessions.json |
Error Messages
| Error | Solution |
|---|---|
| "Not in a git repository" | Navigate to a git repo first |
| "Worktree already exists" | Use different branch name or add {session-id} to template |
| "Failed to remove worktree" | May need manual cleanup with git worktree remove |
| "Branch already exists" (CLI) | Branch exists; remove -b flag to use existing branch |
Diff View
The diff view lets you review changes between your working directory and a base branch (like main), then edit files directly.
Opening Diff View
From the main screen, press D to open the diff view. It shows:
- Left panel: List of changed files with status indicators (M=modified, A=added, D=deleted)
- Right panel: Diff content for the selected file
The diff is computed against the base branch (defaults to main or your repo's default branch).
Navigation
| Key | Action |
|---|---|
j / k or ↑ / ↓ | Navigate between files |
| Scroll wheel | Scroll through diff content |
PgUp / PgDn | Page through diff |
g / G | Jump to top / bottom of diff |
Editing Files
Press e or Enter to open the selected file in your editor ($EDITOR, or vim/nano if not set).
After saving and exiting, the diff view refreshes automatically to show your changes.
Other Commands
| Key | Action |
|---|---|
b | Change base branch |
r | Refresh the diff |
? | Show help |
Esc | Close diff view |
Configuration
In your config file (~/.config/agent-of-empires/config.toml on Linux, ~/.agent-of-empires/config.toml on macOS):
[diff]
# Default branch to compare against (auto-detected if not set)
default_branch = "main"
# Lines of context around changes (default: 3)
context_lines = 3
Tips: See Changes While Editing
The diff view shows you where changes are before you edit. For an even better experience, you can install editor plugins that show git diff markers in the gutter while you edit:
Vim
Install vim-gitgutter or vim-signify. These show +, -, and ~ markers in the sign column for added, removed, and modified lines.
With vim-plug:
Plug 'airblade/vim-gitgutter'
Nano
Nano doesn't have a plugin system, so there's no equivalent. Use the diff view to note line numbers before editing, or consider switching to vim for this workflow.
Other Editors
- Emacs: git-gutter
- VS Code: Built-in git gutter support
- Sublime Text: GitGutter
Workflow Example
- Press
Dto open diff view - Use
j/kto browse changed files - Scroll to review each file's changes
- Press
eto edit a file that needs work - Save and exit the editor
- Continue reviewing (diff auto-refreshes)
- Press
Escwhen done
tmux Status Bar
Agent of Empires can display session information in your tmux status bar, showing:
- Session title: The name of your aoe session
- Git branch: For worktree sessions
- Container name: For sandboxed (Docker) sessions
How It Works
When you start a session, aoe sets tmux user options (@aoe_title, @aoe_branch, @aoe_sandbox) and configures the status bar to display this information with aoe's phosphor green theme.
Example status bars:
aoe: My Session | 14:30 # Basic session
aoe: My Session | feature-branch | 14:30 # Worktree session
aoe: My Session ⬡ aoe_my_container | 14:30 # Sandboxed session
aoe: My Session | main ⬡ aoe_container | 14:30 # Worktree + sandbox
Auto Mode (Default)
By default, aoe uses "auto" mode for the status bar:
- If you don't have a
~/.tmux.conf: aoe automatically styles the status bar for aoe sessions - If you have a
~/.tmux.conf: aoe assumes you prefer your own configuration and does not modify the status bar
This ensures beginners get a helpful status bar out of the box, while experienced tmux users retain full control.
Configuration
Configure the status bar behavior in ~/.agent-of-empires/config.toml:
[tmux]
# "auto" (default) - Apply only if no ~/.tmux.conf exists
# "enabled" - Always apply aoe status bar styling
# "disabled" - Never apply, use your own tmux config
status_bar = "auto"
mouse = "auto" # Same modes: auto, enabled, disabled
Values
| Value | Description |
|---|---|
auto | Apply status bar if user has no tmux config (default) |
enabled | Always apply aoe status bar to aoe sessions |
disabled | Never modify tmux status bar |
Custom Integration
If you have your own tmux configuration but want to display aoe session info, use the aoe tmux status command.
Basic Integration
Add this to your ~/.tmux.conf:
set -g status-right "#(aoe tmux status) | %H:%M"
This will show the aoe session title and branch when attached to an aoe session, and nothing when in other tmux sessions.
JSON Output
For more advanced scripting:
aoe tmux status --format json
Output:
{"title": "My Session", "branch": "feature-branch", "sandbox": null}
For a sandboxed session:
{"title": "My Session", "branch": null, "sandbox": "aoe_my_container"}
Returns null if not in an aoe session.
Example: Conditional Display
# Only show aoe info if in an aoe session
set -g status-right "#{?#{==:#(aoe tmux status),},,%#(aoe tmux status) | }%H:%M"
tmux User Options
When aoe starts a session with status bar enabled, it sets these tmux options:
| Option | Description |
|---|---|
@aoe_title | Session title |
@aoe_branch | Git branch (worktree sessions only) |
@aoe_sandbox | Container name (sandboxed sessions only) |
You can reference these in your own tmux config:
set -g status-right "#{@aoe_title} #{@aoe_branch} #{@aoe_sandbox} | %H:%M"
Troubleshooting
Status bar not showing
- Check if you have a
~/.tmux.confor~/.config/tmux/tmux.conf - If so, either:
- Set
status_bar = "enabled"in your aoe config - Or add
aoe tmux statusto your tmux.conf manually
- Set
Status bar shows old info
The tmux user options are set when the session starts. If you rename a session in aoe, the status bar will show the old name until you restart the session.
Branch not showing
Branch is only displayed for worktree sessions (sessions created with aoe add --worktree). Regular sessions don't have a fixed branch.
Container not showing
Container name is only displayed for sandboxed sessions (sessions created with aoe add --sandbox). The container name follows the pattern aoe_<session_id>.
Sound Effects
Agent of Empires can play sound effects when agent sessions change state, providing audio feedback for transitions like starting, running, waiting, idle, and error states.
Features
- 🔊 State transition sounds (start, running, waiting, idle, error)
- 🎵 Multiple installation options (bundled, AoE II extraction, custom)
- 🎨 Fully customizable - use any .wav/.ogg files
- ⚙️ Configurable via Settings TUI
- 🎯 Per-transition sound overrides
- 🎲 Random or specific sound modes
Quick Start
-
Install sounds:
aoe sounds installThis downloads and installs CC0 fantasy/RPG sounds from GitHub to your config directory.
-
Enable sounds in settings:
- Launch
aoe(TUI mode) - Press
sto open Settings - Navigate to the Sound category
- Enable sounds
- Launch
-
Test it: Start an agent session and listen for the transition sounds!
Available Sounds
Agent of Empires can download 10 CC0 (public domain) fantasy/RPG sound effects from GitHub:
Default State Transition Sounds
start.wav- Spell fire sound (session starting)running.wav- Blade sound (agent actively working)waiting.wav- Misc sound (agent waiting for input)idle.wav- Book sound (agent idle)error.wav- Roar sound (error occurred)
Additional Variety Sounds
spell.wav- Alternative spell/magic effectcoins.wav- Coin/reward soundmetal.wav- Metal impact soundchain.wav- Chain/lock soundgem.wav- Gem/crystal sound
All sounds are from the 80 CC0 RPG SFX pack by SubspaceAudio.
Installation
Install Sounds from GitHub
aoe sounds install
This downloads and installs 10 CC0 (public domain) fantasy/RPG sounds from the GitHub repository to:
- Linux:
~/.config/agent-of-empires/sounds/ - macOS:
~/.agent-of-empires/sounds/
Note: Requires an internet connection for the initial download. Sounds are downloaded from:
https://github.com/njbrake/agent-of-empires/tree/main/bundled_sounds
Useful Commands
Check installed sounds:
aoe sounds list
Test a sound:
aoe sounds test start
Sound Modes
Random Mode (default)
Picks a random sound from your sounds directory for each transition.
Specific Mode
Always plays the same sound file. Useful if you want one signature sound for all transitions.
Configuration
Global Settings
Configure sounds for all profiles:
- Launch
aoeTUI - Press
sfor Settings - Select "Sound" category
- Configure:
- Enabled: Turn sounds on/off
- Mode: Random or Specific
- Per-transition overrides: Set specific sounds for each state
Profile Settings
Override sound settings per profile:
- In Settings, toggle to "Profile" scope (top-right)
- Configure sound overrides for this profile only
TOML Configuration
You can also edit configuration files directly:
Global: ~/.config/agent-of-empires/config.toml (Linux) or ~/.agent-of-empires/config.toml (macOS)
[sound]
enabled = true
mode = "random"
on_error = "error" # Use specific sound for errors
Profile: ~/.config/agent-of-empires/profiles/<profile>/config.toml
[sound]
enabled = true
on_start = "spell"
on_running = "metal"
on_error = "error"
Custom Sounds
Add your own sounds to ~/.config/agent-of-empires/sounds/:
- Supported formats:
.wav,.ogg - File naming: Use descriptive names (e.g.,
wololo.wav,rogan.ogg) - Reference in config: Use the filename without extension
Example:
# Linux
cp ~/Downloads/wololo.wav ~/.config/agent-of-empires/sounds/
# Then in settings, set "On Start" to "wololo"
Audio Playback
Sounds are played using platform-native audio players:
- macOS:
afplay - Linux:
aplay(ALSA) orpaplay(PulseAudio)
If sounds don't play, ensure you have audio tools installed:
# Debian/Ubuntu
sudo apt install alsa-utils pulseaudio-utils
# Arch Linux
sudo pacman -S alsa-utils pulseaudio
Troubleshooting
Sounds not playing?
- SSH Session: Audio doesn't work over SSH - you need a local terminal with speakers/headphones
- Check that sound files exist in
~/.config/agent-of-empires/sounds/ - Verify sounds are enabled in Settings
- Test audio with:
aplay ~/.config/agent-of-empires/sounds/start.wav(Linux) - Check logs:
AGENT_OF_EMPIRES_DEBUG=1 aoe
Want Age of Empires II sounds? If you own AoE II, manually copy the taunt files to your sounds directory.
Custom sounds aren't listed?
- Ensure files have
.wavor.oggextension - Check file permissions are readable
- Restart the TUI to refresh the sound list
License
Bundled sounds are CC0 1.0 Universal (Public Domain) - no attribution required. You are free to use, modify, and distribute them for any purpose, including commercial use.
Source: OpenGameArt.org - 80 CC0 RPG SFX by SubspaceAudio
Command-Line Help for aoe
This document contains the help content for the aoe command-line program.
Command Overview:
aoe↴aoe add↴aoe init↴aoe list↴aoe remove↴aoe status↴aoe session↴aoe session start↴aoe session stop↴aoe session restart↴aoe session attach↴aoe session show↴aoe session current↴aoe group↴aoe group list↴aoe group create↴aoe group delete↴aoe group move↴aoe profile↴aoe profile list↴aoe profile create↴aoe profile delete↴aoe profile default↴aoe worktree↴aoe worktree list↴aoe worktree info↴aoe worktree cleanup↴aoe tmux↴aoe tmux status↴aoe sounds↴aoe sounds install↴aoe sounds list↴aoe sounds test↴aoe uninstall↴
aoe
Agent of Empires (aoe) is a terminal session manager that uses tmux to help you manage and monitor AI coding agents like Claude Code and OpenCode.
Run without arguments to launch the TUI dashboard.
Usage: aoe [OPTIONS] [COMMAND]
Subcommands:
add— Add a new sessioninit— Initialize .aoe/config.toml in a repositorylist— List all sessionsremove— Remove a sessionstatus— Show session status summarysession— Manage session lifecycle (start, stop, attach, etc.)group— Manage groups for organizing sessionsprofile— Manage profiles (separate workspaces)worktree— Manage git worktrees for parallel developmenttmux— tmux integration utilitiessounds— Manage sound effects for agent state transitionsuninstall— Uninstall Agent of Empires
Options:
-p,--profile <PROFILE>— Profile to use (separate workspace with its own sessions)
aoe add
Add a new session
Usage: aoe add [OPTIONS] [PATH]
Arguments:
-
<PATH>— Project directory (defaults to current directory)Default value:
.
Options:
-t,--title <TITLE>— Session title (defaults to folder name)-g,--group <GROUP>— Group path (defaults to parent folder)-c,--cmd <COMMAND>— Command to run (e.g., 'claude', 'opencode', 'vibe', 'codex', 'gemini')-P,--parent <PARENT>— Parent session (creates sub-session, inherits group)-l,--launch— Launch the session immediately after creating-w,--worktree <WORKTREE_BRANCH>— Create session in a git worktree for the specified branch-b,--new-branch— Create a new branch (use with --worktree)-s,--sandbox— Run session in Docker sandbox--sandbox-image <SANDBOX_IMAGE>— Custom Docker image for sandbox (implies --sandbox)--trust-hooks— Automatically trust repository hooks without prompting
aoe init
Initialize .aoe/config.toml in a repository
Usage: aoe init [PATH]
Arguments:
-
<PATH>— Directory to initialize (defaults to current directory)Default value:
.
aoe list
List all sessions
Usage: aoe list [OPTIONS]
Options:
--json— Output as JSON--all— List sessions from all profiles
aoe remove
Remove a session
Usage: aoe remove [OPTIONS] <IDENTIFIER>
Arguments:
<IDENTIFIER>— Session ID or title to remove
Options:
--delete-worktree— Delete worktree directory (default: keep worktree)--keep-container— Keep container instead of deleting it (default: delete per config)
aoe status
Show session status summary
Usage: aoe status [OPTIONS]
Options:
-v,--verbose— Show detailed session list-q,--quiet— Only output waiting count (for scripts)--json— Output as JSON
aoe session
Manage session lifecycle (start, stop, attach, etc.)
Usage: aoe session <COMMAND>
Subcommands:
start— Start a session's tmux processstop— Stop session processrestart— Restart sessionattach— Attach to session interactivelyshow— Show session detailscurrent— Auto-detect current session
aoe session start
Start a session's tmux process
Usage: aoe session start <IDENTIFIER>
Arguments:
<IDENTIFIER>— Session ID or title
aoe session stop
Stop session process
Usage: aoe session stop <IDENTIFIER>
Arguments:
<IDENTIFIER>— Session ID or title
aoe session restart
Restart session
Usage: aoe session restart <IDENTIFIER>
Arguments:
<IDENTIFIER>— Session ID or title
aoe session attach
Attach to session interactively
Usage: aoe session attach <IDENTIFIER>
Arguments:
<IDENTIFIER>— Session ID or title
aoe session show
Show session details
Usage: aoe session show [OPTIONS] [IDENTIFIER]
Arguments:
<IDENTIFIER>— Session ID or title (optional, auto-detects in tmux)
Options:
--json— Output as JSON
aoe session current
Auto-detect current session
Usage: aoe session current [OPTIONS]
Options:
-q,--quiet— Just session name (for scripting)--json— Output as JSON
aoe group
Manage groups for organizing sessions
Usage: aoe group <COMMAND>
Subcommands:
list— List all groupscreate— Create a new groupdelete— Delete a groupmove— Move session to group
aoe group list
List all groups
Usage: aoe group list [OPTIONS]
Options:
--json— Output as JSON
aoe group create
Create a new group
Usage: aoe group create [OPTIONS] <NAME>
Arguments:
<NAME>— Group name
Options:
--parent <PARENT>— Parent group for creating subgroups
aoe group delete
Delete a group
Usage: aoe group delete [OPTIONS] <NAME>
Arguments:
<NAME>— Group name
Options:
--force— Force delete by moving sessions to default group
aoe group move
Move session to group
Usage: aoe group move <IDENTIFIER> <GROUP>
Arguments:
<IDENTIFIER>— Session ID or title<GROUP>— Target group
aoe profile
Manage profiles (separate workspaces)
Usage: aoe profile [COMMAND]
Subcommands:
list— List all profilescreate— Create a new profiledelete— Delete a profiledefault— Show or set default profile
aoe profile list
List all profiles
Usage: aoe profile list
aoe profile create
Create a new profile
Usage: aoe profile create <NAME>
Arguments:
<NAME>— Profile name
aoe profile delete
Delete a profile
Usage: aoe profile delete <NAME>
Arguments:
<NAME>— Profile name
aoe profile default
Show or set default profile
Usage: aoe profile default [NAME]
Arguments:
<NAME>— Profile name (optional, shows current if not provided)
aoe worktree
Manage git worktrees for parallel development
Usage: aoe worktree <COMMAND>
Subcommands:
list— List all worktrees in current repositoryinfo— Show worktree information for a sessioncleanup— Cleanup orphaned worktrees
aoe worktree list
List all worktrees in current repository
Usage: aoe worktree list
aoe worktree info
Show worktree information for a session
Usage: aoe worktree info <IDENTIFIER>
Arguments:
<IDENTIFIER>— Session ID or title
aoe worktree cleanup
Cleanup orphaned worktrees
Usage: aoe worktree cleanup [OPTIONS]
Options:
-f,--force— Actually remove worktrees (default is dry-run)
aoe tmux
tmux integration utilities
Usage: aoe tmux <COMMAND>
Subcommands:
status— Output session info for use in custom tmux status bar
aoe tmux status
Output session info for use in custom tmux status bar
Add this to your ~/.tmux.conf: set -g status-right "#(aoe tmux status)"
Usage: aoe tmux status [OPTIONS]
Options:
-
-f,--format <FORMAT>— Output format (text or json)Default value:
text
aoe sounds
Manage sound effects for agent state transitions
Usage: aoe sounds <COMMAND>
Subcommands:
install— Install bundled sound effectslist— List currently installed soundstest— Test a sound by playing it
aoe sounds install
Install bundled sound effects
Usage: aoe sounds install
aoe sounds list
List currently installed sounds
Usage: aoe sounds list
aoe sounds test
Test a sound by playing it
Usage: aoe sounds test <NAME>
Arguments:
<NAME>— Sound file name (without extension)
aoe uninstall
Uninstall Agent of Empires
Usage: aoe uninstall [OPTIONS]
Options:
--keep-data— Keep data directory (sessions, config, logs)--keep-tmux-config— Keep tmux configuration--dry-run— Show what would be removed without removing-y— Skip confirmation prompts
This document was generated automatically by
clap-markdown.
Configuration Reference
AoE uses a layered configuration system. Settings are resolved in this order:
- Global config --
~/.agent-of-empires/config.toml(or~/.config/agent-of-empires/config.tomlon Linux) - Profile config --
~/.agent-of-empires/profiles/<name>/config.toml - Repo config --
.aoe/config.tomlin the project root
Later layers override earlier ones. Only explicitly set fields override; unset fields inherit from the previous layer.
All settings below can also be edited from the TUI settings screen (press S or access via the menu).
File Locations
| Platform | Global Config |
|---|---|
| Linux | $XDG_CONFIG_HOME/agent-of-empires/config.toml (defaults to ~/.config/agent-of-empires/) |
| macOS | ~/.agent-of-empires/config.toml |
~/.agent-of-empires/
config.toml # Global configuration
trusted_repos.toml # Hook trust decisions (auto-managed)
.schema_version # Migration tracking (auto-managed)
profiles/
default/
sessions.json # Session data
groups.json # Group hierarchy
config.toml # Profile-specific overrides
logs/ # Session execution logs
Environment Variables
| Variable | Description |
|---|---|
AGENT_OF_EMPIRES_PROFILE | Default profile to use |
AGENT_OF_EMPIRES_DEBUG | Enable debug logging (1 to enable) |
Session
[session]
default_tool = "claude" # claude, opencode, vibe, codex, gemini
| Option | Default | Description |
|---|---|---|
default_tool | (auto-detect) | Default agent for new sessions. Falls back to the first available tool if unset or unavailable. |
Worktree
[worktree]
enabled = false
path_template = "../{repo-name}-worktrees/{branch}"
bare_repo_path_template = "./{branch}"
auto_cleanup = true
show_branch_in_tui = true
delete_branch_on_cleanup = false
| Option | Default | Description |
|---|---|---|
enabled | false | Enable worktree support for new sessions |
path_template | ../{repo-name}-worktrees/{branch} | Path template for worktrees in regular repos |
bare_repo_path_template | ./{branch} | Path template for worktrees in bare repos |
auto_cleanup | true | Prompt to remove worktree when deleting a session |
show_branch_in_tui | true | Display branch name in the TUI session list |
delete_branch_on_cleanup | false | Also delete the git branch when removing a worktree |
Template variables:
| Variable | Description |
|---|---|
{repo-name} | Repository folder name |
{branch} | Branch name (slashes converted to hyphens) |
{session-id} | First 8 characters of session UUID |
Sandbox (Docker)
[sandbox]
enabled_by_default = false
yolo_mode_default = false
default_image = "ghcr.io/njbrake/aoe-sandbox:latest"
cpu_limit = "4"
memory_limit = "8g"
environment = ["ANTHROPIC_API_KEY", "OPENAI_API_KEY"]
environment_values = { GH_TOKEN = "$AOE_GH_TOKEN" }
extra_volumes = []
volume_ignores = ["node_modules", "target"]
auto_cleanup = true
default_terminal_mode = "host"
| Option | Default | Description |
|---|---|---|
enabled_by_default | false | Auto-enable sandbox for new sessions |
yolo_mode_default | false | Skip agent permission prompts in sandbox |
default_image | ghcr.io/njbrake/aoe-sandbox:latest | Docker image for containers |
cpu_limit | (none) | CPU limit (e.g., "4") |
memory_limit | (none) | Memory limit (e.g., "8g") |
environment | ["TERM", "COLORTERM", "FORCE_COLOR", "NO_COLOR"] | Host env var names to pass through |
environment_values | {} | Env vars with explicit values (see below) |
extra_volumes | [] | Additional Docker volume mounts |
volume_ignores | [] | Directories to exclude from the project mount via anonymous volumes |
auto_cleanup | true | Remove containers when sessions are deleted |
default_terminal_mode | "host" | Paired terminal location: "host" or "container" |
environment vs environment_values
environmentpasses host env vars by name. The host value is read at container start.environment_valuesinjects fixed values. Values starting with$reference a host env var (e.g.,"$AOE_GH_TOKEN"readsAOE_GH_TOKENfrom the host). Use$$for a literal$.
tmux
[tmux]
status_bar = "auto"
mouse = "auto"
| Option | Default | Description |
|---|---|---|
status_bar | "auto" | "auto": apply if no ~/.tmux.conf; "enabled": always apply; "disabled": never apply |
mouse | "auto" | Same modes as status_bar. Controls mouse support in aoe tmux sessions. |
Diff
[diff]
default_branch = "main"
context_lines = 3
| Option | Default | Description |
|---|---|---|
default_branch | (auto-detect) | Base branch for diffs |
context_lines | 3 | Lines of context around changes |
Updates
[updates]
check_enabled = true
auto_update = false
check_interval_hours = 24
notify_in_cli = true
| Option | Default | Description |
|---|---|---|
check_enabled | true | Check for new versions |
auto_update | false | Automatically install updates |
check_interval_hours | 24 | Hours between update checks |
notify_in_cli | true | Show update notifications in CLI output |
Claude
[claude]
config_dir = "~/.claude"
| Option | Default | Description |
|---|---|---|
config_dir | (none) | Custom Claude Code config directory. Supports ~/ prefix. |
Profiles
Profiles provide separate workspaces with their own sessions and groups. Each profile can override any of the settings above.
aoe # Uses "default" profile
aoe -p work # Uses "work" profile
aoe profile create client-xyz
aoe profile list
aoe profile default work # Set "work" as default
Profile overrides go in ~/.agent-of-empires/profiles/<name>/config.toml and use the same format as the global config.
Repo Config
Per-repo settings go in .aoe/config.toml at your project root. Run aoe init to generate a template.
Repo config supports: [hooks], [session], [sandbox], and [worktree] sections. It does not support [tmux], [updates], [claude], or [diff] -- those are personal settings.
See Repo Config & Hooks for details.
Development
Building
cargo build # Debug build
cargo build --release # Release build (with LTO)
cargo build --profile dev-release # Optimized build without LTO (faster compile)
The release binary is at target/release/aoe.
Running
cargo run --release # Run from source
AGENT_OF_EMPIRES_DEBUG=1 cargo run # With debug logging
RUST_LOG=agent_of_empires=debug cargo run # With env_logger debug output
Requires tmux to be installed.
Testing
cargo test # Unit + integration tests
cargo fmt # Format code
cargo clippy # Lint
cargo check # Fast type-check
Some integration tests require tmux to be available and will skip if it's not installed.
Generating the Demo GIF
The demo GIF in the docs is created using VHS.
# Install VHS
brew install vhs
# Clear the demo profile
rm -rf ~/.agent-of-empires/profiles/demo
# Ensure demo directories exist
mkdir -p /tmp/demo-projects/api-server /tmp/demo-projects/web-app
# Generate the GIF (from repo root)
vhs assets/demo.tape
This creates docs/assets/demo.gif. The demo uses -p demo to run in a separate profile.