Skip to content

Commit 85e9075

Browse files
covlllpclaudenjbrake
authored
feat: add Cursor CLI (agent) support (#285)
* feat: add Cursor CLI (agent) support Add Cursor as a supported agent using the new centralized registry. Cursor CLI is built on Claude Code's codebase, so status detection delegates to the existing Claude detector. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: address PR review feedback for Cursor CLI support - Fix YOLO flag: --yolo -> --force (per Cursor CLI docs) - Add instruction_flag: --append-system-prompt (Claude Code compatible) - Use RunWithArg detection: agent --version instead of which agent - Add container_env: CURSOR_CONFIG_DIR for sandbox support - Add AGENT_CONFIG_MOUNTS entry for ~/.cursor/ sandbox syncing - Remove Cursor from sandbox image descriptions (Dockerfile not updated) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * add cursor cli --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Nathan Brake <33383515+njbrake@users.noreply.github.com> Co-authored-by: njbrake <njbrake@gmail.com>
1 parent cb0bc04 commit 85e9075

19 files changed

Lines changed: 118 additions & 31 deletions

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Run multiple AI agents in parallel across different branches of your codebase, e
2222

2323
## Features
2424

25-
- **Multi-agent support** -- Claude Code, OpenCode, Mistral Vibe, Codex CLI, and Gemini CLI
25+
- **Multi-agent support** -- Claude Code, OpenCode, Mistral Vibe, Codex CLI, Gemini CLI, and Cursor CLI
2626
- **TUI dashboard** -- visual interface to create, monitor, and manage sessions
2727
- **Agent + terminal views** -- toggle between your AI agents and paired shell terminals with `t`
2828
- **Status detection** -- see which agents are running, waiting for input, or idle
@@ -96,7 +96,7 @@ Nothing. Sessions are tmux sessions running in the background. Open and close `a
9696

9797
### Which AI tools are supported?
9898

99-
Claude Code, OpenCode, Mistral Vibe, Codex CLI, and Gemini CLI. AoE auto-detects which are installed on your system.
99+
Claude Code, OpenCode, Mistral Vibe, Codex CLI, Gemini CLI, and Cursor CLI. AoE auto-detects which are installed on your system.
100100

101101
## Troubleshooting
102102

docker/Dockerfile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# aoe-sandbox: Docker image for Agent of Empires sandbox sessions
2-
# This image provides Claude Code, OpenCode, Mistral Vibe, Codex CLI, and Gemini CLI in an isolated environment
2+
# This image provides Claude Code, OpenCode, Mistral Vibe, Codex CLI, Gemini CLI, and Cursor CLI in an isolated environment
33

44
FROM ubuntu:24.04
55

@@ -47,13 +47,17 @@ RUN npm install -g @google/gemini-cli
4747
RUN curl -LsSf https://mistral.ai/vibe/install.sh | bash
4848
ENV PATH="/root/.vibe/bin:${PATH}"
4949

50+
# Install Cursor CLI
51+
RUN curl -fsSL https://cursor.com/install | bash
52+
5053
# Create directories for credential mounts
5154
RUN mkdir -p /root/.claude \
5255
/root/.config/opencode \
5356
/root/.local/share/opencode \
5457
/root/.vibe \
5558
/root/.codex \
5659
/root/.gemini \
60+
/root/.cursor \
5761
/root/.ssh
5862

5963
# Allow Claude Code to use --dangerously-skip-permissions as root

docs/cli/reference.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ This document contains the help content for the `aoe` command-line program.
4343

4444
## `aoe`
4545

46-
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.
46+
Agent of Empires (aoe) is a terminal session manager that uses tmux to help you manage and monitor AI coding agents like Claude Code, OpenCode, and Cursor CLI.
4747

4848
Run without arguments to launch the TUI dashboard.
4949

@@ -87,7 +87,7 @@ Add a new session
8787

8888
* `-t`, `--title <TITLE>` — Session title (defaults to folder name)
8989
* `-g`, `--group <GROUP>` — Group path (defaults to parent folder)
90-
* `-c`, `--cmd <COMMAND>` — Command to run (e.g., 'claude', 'opencode', 'vibe', 'codex', 'gemini')
90+
* `-c`, `--cmd <COMMAND>` — Command to run (e.g., 'claude', 'opencode', 'vibe', 'codex', 'gemini', 'cursor')
9191
* `-P`, `--parent <PARENT>` — Parent session (creates sub-session, inherits group)
9292
* `-l`, `--launch` — Launch the session immediately after creating
9393
* `-w`, `--worktree <WORKTREE_BRANCH>` — Create session in a git worktree for the specified branch

docs/guides/configuration.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ name = "phosphor" # phosphor, tokyo-night-storm, catppuccin-latte
5252

5353
```toml
5454
[session]
55-
default_tool = "claude" # claude, opencode, vibe, codex, gemini
55+
default_tool = "claude" # claude, opencode, vibe, codex, gemini, cursor
5656
yolo_mode_default = false
5757
```
5858

docs/guides/repo-config.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ For sandboxed sessions, hooks run inside the Docker container.
4040
default_tool = "opencode" # Override the default agent for this repo
4141
```
4242

43-
Available tools: `claude`, `opencode`, `vibe`, `codex`, `gemini`.
43+
Available tools: `claude`, `opencode`, `vibe`, `codex`, `gemini`, `cursor`.
4444

4545
### Sandbox
4646

docs/guides/sandbox.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## Overview
44

5-
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.
5+
Docker sandboxing runs your AI coding agents (Claude Code, OpenCode, Mistral Vibe, Codex CLI, Gemini CLI, Cursor CLI) inside isolated Docker containers while maintaining access to your project files and credentials.
66

77
**Key Features:**
88
- One container per session
@@ -84,11 +84,11 @@ environment = ["ANTHROPIC_API_KEY"]
8484

8585
### Shared Agent Config Directories
8686

87-
AOE shares your host agent credentials with sandboxed containers so agents can authenticate without re-login. This works for all supported agents: Claude Code, OpenCode, Codex, Gemini, and Vibe.
87+
AOE shares your host agent credentials with sandboxed containers so agents can authenticate without re-login. This works for all supported agents: Claude Code, OpenCode, Codex, Gemini, Vibe, and Cursor.
8888

8989
Rather than bind-mounting your actual host config directories (which would let container writes modify your host files), AOE creates a **shared sandbox directory** per agent:
9090

91-
1. For each agent whose host config directory exists (e.g. `~/.claude/`, `~/.codex/`, `~/.gemini/`, `~/.local/share/opencode/`, `~/.vibe/`), AOE syncs credential files into a shared sandbox directory.
91+
1. For each agent whose host config directory exists (e.g. `~/.claude/`, `~/.codex/`, `~/.gemini/`, `~/.local/share/opencode/`, `~/.vibe/`, `~/.cursor/`), AOE syncs credential files into a shared sandbox directory.
9292
2. The sandbox directory is mounted read-write into **all** containers that use that agent.
9393
3. Containers can read credentials and write runtime state freely without affecting your host config.
9494
4. In-container changes (e.g. permission approvals, settings tweaks) persist across sessions since all containers share the same directory.
@@ -117,6 +117,7 @@ If an agent's config directory doesn't exist on the host (e.g. you haven't insta
117117
~/.gemini/sandbox/ # Gemini (shared by all containers)
118118
~/.local/share/opencode/sandbox/ # OpenCode (shared by all containers)
119119
~/.vibe/sandbox/ # Vibe (shared by all containers)
120+
~/.cursor/sandbox/ # Cursor (shared by all containers)
120121
```
121122

122123
Deleting an agent's config directory (e.g. `rm -rf ~/.codex/`) removes everything related to that agent, including the sandbox directory. To reset just the sandbox state for an agent, delete its `sandbox/` subdirectory (e.g. `rm -rf ~/.claude/sandbox/`) -- it will be re-created on the next session start.
@@ -137,7 +138,7 @@ Example: `aoe-sandbox-a1b2c3d4`
137138

138139
1. **Session Creation:** When you add a sandboxed session, aoe records the sandbox configuration
139140
2. **Container Start:** When you start the session, aoe creates/starts the Docker container with appropriate volume mounts
140-
3. **tmux + docker exec:** Host tmux runs `docker exec -it <container> <tool>` (claude, opencode, vibe, codex, or gemini)
141+
3. **tmux + docker exec:** Host tmux runs `docker exec -it <container> <tool>` (claude, opencode, vibe, codex, gemini, or cursor)
141142
4. **Cleanup:** When you remove the session, the container is automatically deleted
142143

143144

@@ -187,7 +188,7 @@ AOE provides two official sandbox images:
187188

188189
| Image | Description |
189190
|-------|-------------|
190-
| `ghcr.io/njbrake/aoe-sandbox:latest` | Base image with Claude Code, OpenCode, Mistral Vibe, Codex CLI, Gemini CLI, git, ripgrep, fzf |
191+
| `ghcr.io/njbrake/aoe-sandbox:latest` | Base image with Claude Code, OpenCode, Mistral Vibe, Codex CLI, Gemini CLI, Cursor CLI, git, ripgrep, fzf |
191192
| `ghcr.io/njbrake/aoe-dev-sandbox:latest` | Extended image with additional dev tools |
192193

193194
### Dev Sandbox Tools
@@ -212,7 +213,7 @@ default_image = "ghcr.io/njbrake/aoe-dev-sandbox:latest"
212213

213214
## Custom Docker Images
214215

215-
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.
216+
The default sandbox image includes Claude Code, OpenCode, Mistral Vibe, Codex CLI, Gemini CLI, Cursor CLI, git, and basic development tools. For projects requiring additional dependencies beyond what the dev sandbox provides, you can extend either base image.
216217

217218
### Step 1: Create a Dockerfile
218219

docs/index.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ AoE lets you run multiple AI agents in parallel -- each in its own tmux session,
1010

1111
## Why AoE?
1212

13-
**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.
13+
**The problem:** You're working with AI coding agents (Claude Code, OpenCode, Cursor, 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.
1414

1515
**AoE handles it for you:**
1616

@@ -22,7 +22,7 @@ AoE lets you run multiple AI agents in parallel -- each in its own tmux session,
2222

2323
## Supported Agents
2424

25-
Claude Code, OpenCode, Mistral Vibe, Codex CLI, and Gemini CLI. AoE auto-detects which are installed.
25+
Claude Code, OpenCode, Mistral Vibe, Codex CLI, Gemini CLI, and Cursor CLI. AoE auto-detects which are installed.
2626

2727
<div class="cta-box">
2828
<p><strong>Ready to get started?</strong></p>

docs/quick-start.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ aoe add -c opencode .
6868
aoe add -c vibe .
6969
aoe add -c codex .
7070
aoe add -c gemini .
71+
aoe add -c cursor .
7172
```
7273

7374
In the TUI, select the tool from the dropdown in the new session dialog.

src/agents.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,18 @@ pub const AGENTS: &[AgentDef] = &[
110110
detect_status: status_detection::detect_gemini_status,
111111
container_env: &[],
112112
},
113+
AgentDef {
114+
name: "cursor",
115+
binary: "agent",
116+
aliases: &["agent"],
117+
detection: DetectionMethod::Which("agent"),
118+
yolo: Some(YoloMode::CliFlag("--yolo")),
119+
instruction_flag: None,
120+
set_default_command: false,
121+
supports_host_launch: true,
122+
detect_status: status_detection::detect_cursor_status,
123+
container_env: &[("CURSOR_CONFIG_DIR", "/root/.cursor")],
124+
},
113125
];
114126

115127
/// Look up an agent by canonical name.
@@ -174,6 +186,7 @@ mod tests {
174186
assert_eq!(get_agent("vibe").unwrap().binary, "vibe");
175187
assert_eq!(get_agent("codex").unwrap().binary, "codex");
176188
assert_eq!(get_agent("gemini").unwrap().binary, "gemini");
189+
assert_eq!(get_agent("cursor").unwrap().binary, "agent");
177190
}
178191

179192
#[test]
@@ -184,7 +197,10 @@ mod tests {
184197
#[test]
185198
fn test_agent_names() {
186199
let names = agent_names();
187-
assert_eq!(names, vec!["claude", "opencode", "vibe", "codex", "gemini"]);
200+
assert_eq!(
201+
names,
202+
vec!["claude", "opencode", "vibe", "codex", "gemini", "cursor"]
203+
);
188204
}
189205

190206
#[test]
@@ -194,7 +210,9 @@ mod tests {
194210
assert_eq!(resolve_tool_name("mistral-vibe"), Some("vibe"));
195211
assert_eq!(resolve_tool_name("codex"), Some("codex"));
196212
assert_eq!(resolve_tool_name("gemini"), Some("gemini"));
213+
assert_eq!(resolve_tool_name("cursor"), Some("cursor"));
197214
assert_eq!(resolve_tool_name(""), Some("claude"));
215+
assert_eq!(resolve_tool_name("agent"), Some("cursor"));
198216
assert_eq!(resolve_tool_name("unknown-tool"), None);
199217
}
200218

@@ -203,10 +221,12 @@ mod tests {
203221
assert_eq!(settings_index_from_name(None), 0);
204222
assert_eq!(settings_index_from_name(Some("claude")), 1);
205223
assert_eq!(settings_index_from_name(Some("gemini")), 5);
224+
assert_eq!(settings_index_from_name(Some("cursor")), 6);
206225

207226
assert_eq!(name_from_settings_index(0), None);
208227
assert_eq!(name_from_settings_index(1), Some("claude"));
209228
assert_eq!(name_from_settings_index(5), Some("gemini"));
229+
assert_eq!(name_from_settings_index(6), Some("cursor"));
210230
assert_eq!(name_from_settings_index(99), None);
211231
}
212232

src/cli/add.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ pub struct AddArgs {
2222
#[arg(short = 'g', long)]
2323
group: Option<String>,
2424

25-
/// Command to run (e.g., 'claude', 'opencode', 'vibe', 'codex', 'gemini')
25+
/// Command to run (e.g., 'claude', 'opencode', 'vibe', 'codex', 'gemini', 'cursor')
2626
#[arg(short = 'c', long = "cmd")]
2727
command: Option<String>,
2828

@@ -167,8 +167,14 @@ pub async fn run(profile: &str, args: AddArgs) -> Result<()> {
167167
}
168168

169169
if let Some(cmd) = &args.command {
170-
instance.command = cmd.clone();
171-
instance.tool = detect_tool(cmd)?;
170+
let tool_name = detect_tool(cmd)?;
171+
instance.tool = tool_name;
172+
// Only store a custom command when the user passed extra args
173+
// (e.g. "claude --resume xyz"). A bare tool name/alias should resolve
174+
// through the agent definition so the correct binary is used.
175+
if cmd.trim().contains(' ') {
176+
instance.command = cmd.clone();
177+
}
172178
}
173179

174180
if let Some(worktree_info) = worktree_info_opt {

0 commit comments

Comments
 (0)