Add Cursor CLI as a coding agent choice (#10465)
* Add Cursor CLI as a coding agent choice * Launch Cursor CLI through its agent subcommand with --trust Cursor CLI still dispatches a one-word prompt that names one of its subcommands (update, login, help) even after a bare --, so name the agent subcommand outright and pass the prompt behind -- there, where it also keeps a prompt starting with a dash from being read as an option. --yolo only auto-allows commands; the workspace trust dialog is skipped only by --trust, and a launcher that must not stop to ask needs both. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * Leave an official Cursor CLI install alone Cursor's own installer symlinks ~/.local/bin/cursor-agent, the same path the mise wrapper takes. The migration now installs the wrapper only when no cursor-agent command exists, and Remove Preinstalls deletes the path only when it holds the wrapper omarchy-mise-install wrote, the way the Hermes wrapper is handled. Selecting the agent treats an executable at that path other than the wrapper as the user's own install and skips mise, since the mise shims precede ~/.local/bin on PATH and a mise copy would only shadow it. The wrapper resolves through mise's registry, which lists cursor-agent from 2026.8.15 on. The tests write a real cursor-agent stub before Remove Preinstalls runs, cover the preinstall opt-out for the new migration, and check that a symlinked official install survives removal and selection alike while a dead file at the same path still installs. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * Give Cursor its brand mark and one name in the menu Add Cursor's mark to the Omarchy icon font as U+E90D and point the agent entry and both editor entries at it, so one brand is drawn one way across the menu. Label the agent entry "Cursor CLI", the name the command and the manual already use, and spell it the same in the migration and the tests. Append the manual row after the others at the standard width. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * Keep an official Cursor CLI install through a user re-provision User setup writes every mise wrapper unconditionally, which is fine on a fresh install but replaces the symlink Cursor's own installer leaves at the same path when omarchy-provision-user runs again with --force. Guard that one line the way the migration does. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> --------- Co-authored-by: John Cavanaugh <59479+cavanaug@users.noreply.github.com> Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
11 files changed
+110
-10
No files matched your search
@@ -98,6 +98,7 @@ omp_package="github:can1357/oh-my-pi"
|
||||
crush_package="crush"
|
||||
agy_package="antigravity-cli"
|
||||
ori_package="github:OpenRouterLabs/ori-releases"
|
||||
cursor_agent_package="cursor-agent"
|
||||
|
||||
assert_lazy_stub() {
|
||||
local package=$1
|
||||
@@ -116,16 +117,23 @@ assert_lazy_stub "$grok_package" grok
|
||||
assert_lazy_stub "$omp_package" omp
|
||||
assert_lazy_stub "$crush_package" crush
|
||||
assert_lazy_stub "$ori_package" ori
|
||||
assert_lazy_stub "$cursor_agent_package" cursor-agent
|
||||
pass "custom agent lazy stubs preserve their mise packages"
|
||||
|
||||
source "$ROOT/install/user/mise.sh"
|
||||
OMARCHY_TEST_MISSING_COMMAND=cursor-agent source "$ROOT/install/user/mise.sh"
|
||||
grep -Fx "$agy_package agy" "$stub_log" >/dev/null || fail "user setup creates the Antigravity lazy stub"
|
||||
grep -Fx "$grok_package grok" "$stub_log" >/dev/null || fail "user setup creates the Grok lazy stub"
|
||||
grep -Fx "$cursor_agent_package" "$stub_log" >/dev/null || fail "user setup creates the Cursor CLI lazy stub"
|
||||
grep -Fx "$omp_package omp" "$stub_log" >/dev/null || fail "user setup creates the Oh My Pi lazy stub"
|
||||
grep -Fx "$crush_package" "$stub_log" >/dev/null || fail "user setup creates the Crush lazy stub"
|
||||
grep -Fx "$ori_package ori" "$stub_log" >/dev/null || fail "user setup creates the Ori lazy stub"
|
||||
pass "user setup creates the custom agent lazy stubs"
|
||||
|
||||
: >"$stub_log"
|
||||
source "$ROOT/install/user/mise.sh"
|
||||
grep -Fx "$cursor_agent_package" "$stub_log" >/dev/null && fail "user setup replaces an existing cursor-agent command"
|
||||
pass "user setup keeps an existing Cursor CLI install"
|
||||
|
||||
: >"$stub_log"
|
||||
source "$ROOT/migrations/1785617047.sh" >/dev/null
|
||||
grep -Fx "$omp_package omp" "$stub_log" >/dev/null || fail "Oh My Pi migration creates a working lazy stub"
|
||||
@@ -134,6 +142,17 @@ grep -Fx "$omp_package omp" "$stub_log" >/dev/null || fail "Oh My Pi migration c
|
||||
source "$ROOT/migrations/1787342993.sh" >/dev/null
|
||||
grep -Fx "$ori_package ori" "$stub_log" >/dev/null || fail "Ori migration creates a working lazy stub"
|
||||
|
||||
: >"$stub_log"
|
||||
export OMARCHY_TEST_MISSING_COMMAND=cursor-agent
|
||||
source "$ROOT/migrations/1788577553.sh" >/dev/null
|
||||
unset OMARCHY_TEST_MISSING_COMMAND
|
||||
grep -Fx "$cursor_agent_package" "$stub_log" >/dev/null || fail "Cursor CLI migration creates a working lazy stub"
|
||||
|
||||
: >"$stub_log"
|
||||
source "$ROOT/migrations/1788577553.sh" >/dev/null
|
||||
[[ ! -s $stub_log ]] || fail "Cursor CLI migration reinstalls an existing cursor-agent command"
|
||||
pass "Cursor CLI migration preserves an existing Cursor CLI install"
|
||||
|
||||
: >"$stub_log"
|
||||
source "$ROOT/migrations/1785846769.sh" >/dev/null
|
||||
grep -Fx "$omp_package omp" "$stub_log" >/dev/null || fail "agent migration repairs the Oh My Pi lazy stub"
|
||||
@@ -216,6 +235,7 @@ touch "$test_home/.local/state/omarchy/preinstalls-removed"
|
||||
source "$ROOT/migrations/1785617047.sh" >/dev/null
|
||||
source "$ROOT/migrations/1785846769.sh" >/dev/null
|
||||
source "$ROOT/migrations/1787342993.sh" >/dev/null
|
||||
OMARCHY_TEST_MISSING_COMMAND=cursor-agent source "$ROOT/migrations/1788577553.sh" >/dev/null
|
||||
[[ ! -s $stub_log ]] || fail "agent migrations respect the preinstall opt-out"
|
||||
[[ ! -e $test_home/.local/bin/omp ]] || fail "agent migration removes the obsolete Oh My Pi wrapper after opt-out"
|
||||
|
||||
@@ -242,11 +262,20 @@ pass "agent migrations install working wrappers without overriding the preinstal
|
||||
|
||||
touch "$test_home/.local/bin/agy" "$test_home/.local/bin/ori"
|
||||
omarchy-remove-preinstalls >/dev/null
|
||||
for command in agy omp ori grok crush; do
|
||||
for command in agy omp ori grok crush cursor-agent; do
|
||||
[[ ! -e $test_home/.local/bin/$command ]] || fail "Remove Preinstalls deletes the $command lazy stub"
|
||||
done
|
||||
pass "Remove Preinstalls deletes every optional agent lazy stub"
|
||||
|
||||
# Cursor's installer links the same path, so anything but the mise wrapper is
|
||||
# the user's own install.
|
||||
touch "$test_home/.local/bin/cursor-agent.official"
|
||||
ln -s cursor-agent.official "$test_home/.local/bin/cursor-agent"
|
||||
omarchy-remove-preinstalls >/dev/null
|
||||
[[ -L $test_home/.local/bin/cursor-agent ]] || fail "Remove Preinstalls keeps an official Cursor CLI install"
|
||||
rm -f "$test_home/.local/bin/cursor-agent" "$test_home/.local/bin/cursor-agent.official"
|
||||
pass "Remove Preinstalls keeps an official Cursor CLI install"
|
||||
|
||||
[[ -z $(omarchy-default-agent) ]] || fail "default agent is unset until one is chosen"
|
||||
pass "default agent is unset until one is chosen"
|
||||
|
||||
@@ -307,6 +336,8 @@ declare -A expected_agents=(
|
||||
[gemini-cli]="agy"
|
||||
[copilot]="copilot"
|
||||
[github-copilot]="copilot"
|
||||
[cursor]="cursor-agent"
|
||||
[cursor-agent]="cursor-agent"
|
||||
)
|
||||
|
||||
declare -A expected_packages=(
|
||||
@@ -320,6 +351,7 @@ declare -A expected_packages=(
|
||||
[grok]="$grok_package"
|
||||
[agy]="$agy_package"
|
||||
[copilot]="copilot"
|
||||
[cursor-agent]="$cursor_agent_package"
|
||||
)
|
||||
|
||||
for selection in "${!expected_agents[@]}"; do
|
||||
@@ -380,6 +412,35 @@ mapfile -d '' -t agent_open_args <"$agent_open_log"
|
||||
fail "installed agent opens in a new terminal after selection"
|
||||
pass "installed agents select and open without notifications"
|
||||
|
||||
# Cursor's installer links the wrapper's path, and the mise shims precede
|
||||
# ~/.local/bin, so a mise copy would shadow the user's own install.
|
||||
touch "$test_home/.local/bin/cursor-agent.official"
|
||||
chmod +x "$test_home/.local/bin/cursor-agent.official"
|
||||
ln -s cursor-agent.official "$test_home/.local/bin/cursor-agent"
|
||||
: >"$terminal_log"
|
||||
: >"$mise_log"
|
||||
: >"$agent_open_log"
|
||||
omarchy-default-agent cursor-agent
|
||||
[[ ! -s $terminal_log ]] || fail "an official Cursor CLI install needs no install terminal"
|
||||
[[ ! -s $mise_log ]] || fail "an official Cursor CLI install is left to itself by mise"
|
||||
[[ $(<"$agent_file") == "cursor-agent" ]] || fail "an official Cursor CLI install becomes the default"
|
||||
mapfile -d '' -t agent_open_args <"$agent_open_log"
|
||||
[[ ${#agent_open_args[@]} == 1 && ${agent_open_args[0]} == "omarchy-agent" ]] ||
|
||||
fail "an official Cursor CLI install opens after selection"
|
||||
rm -f "$test_home/.local/bin/cursor-agent" "$test_home/.local/bin/cursor-agent.official"
|
||||
printf '%s\n' copilot >"$agent_file"
|
||||
pass "selecting an official Cursor CLI install skips mise"
|
||||
|
||||
# A file nothing can run is not an install; the wrapper is still wanted.
|
||||
touch "$test_home/.local/bin/cursor-agent"
|
||||
: >"$terminal_log"
|
||||
omarchy-default-agent cursor-agent
|
||||
mapfile -d '' -t terminal_args <"$terminal_log"
|
||||
[[ ${terminal_args[*]} == "omarchy-default-agent --install cursor-agent" ]] ||
|
||||
fail "a dead file at the wrapper's path still installs Cursor CLI"
|
||||
rm -f "$test_home/.local/bin/cursor-agent"
|
||||
pass "a dead file at the wrapper's path does not pass for an install"
|
||||
|
||||
: >"$agent_open_log"
|
||||
if omarchy-default-agent unsupported >"$test_tmp/invalid-output" 2>&1; then
|
||||
fail "default agent rejects unsupported providers"
|
||||
@@ -464,6 +525,7 @@ assert_launch claude claude --permission-mode auto -- "Review this project"
|
||||
assert_launch codex codex --approve-for-me -- "Review this project"
|
||||
assert_launch crush crush run "Review this project"
|
||||
assert_launch grok grok --permission-mode bypassPermissions -- "Review this project"
|
||||
assert_launch cursor-agent cursor-agent --yolo --trust agent -- "Review this project"
|
||||
assert_launch hermes env -u HERMES_SESSION_SOURCE hermes chat --yolo --tui "--query=Review this project"
|
||||
assert_launch agy agy --dangerously-skip-permissions --prompt-interactive "Review this project"
|
||||
assert_launch copilot copilot --allow-all --interactive "Review this project"
|
||||
@@ -484,6 +546,7 @@ assert_bypass claude claude --permission-mode auto
|
||||
assert_bypass codex codex --approve-for-me
|
||||
assert_bypass crush crush --yolo
|
||||
assert_bypass grok grok --permission-mode bypassPermissions
|
||||
assert_bypass cursor-agent cursor-agent --yolo --trust
|
||||
assert_bypass hermes hermes --yolo
|
||||
assert_bypass agy agy --dangerously-skip-permissions
|
||||
assert_bypass copilot copilot --allow-all
|
||||
|
||||
@@ -228,6 +228,7 @@ const expectedAgents = {
|
||||
openclaw: { icon: '\ue90c', iconFont: 'omarchy', label: 'OpenClaw' },
|
||||
copilot: { icon: '', label: 'Copilot' },
|
||||
crush: { icon: '', label: 'Crush' },
|
||||
'cursor-agent': { icon: '\ue90d', iconFont: 'omarchy', label: 'Cursor CLI' },
|
||||
}
|
||||
assert(
|
||||
Object.entries(expectedAgents).every(([agent, expected]) => {
|
||||
@@ -246,7 +247,7 @@ assertDeepEqual(
|
||||
defaultItems
|
||||
.filter(item => item.parent === 'setup.default.agent')
|
||||
.map(item => item.label),
|
||||
['Antigravity', 'Claude', 'Codex', 'Copilot', 'Crush', 'Grok', 'Hermes', 'omp', 'OpenClaw', 'OpenCode', 'Ori', 'Pi'],
|
||||
['Antigravity', 'Claude', 'Codex', 'Copilot', 'Crush', 'Cursor CLI', 'Grok', 'Hermes', 'omp', 'OpenClaw', 'OpenCode', 'Ori', 'Pi'],
|
||||
'menu sorts coding agents alphabetically'
|
||||
)
|
||||
const expectedDefaults = {
|
||||
@@ -638,5 +639,5 @@ assert(
|
||||
JS
|
||||
|
||||
font_charset=$(fc-query --format='%{charset}' "$ROOT/default/fonts/omarchy/omarchy.ttf")
|
||||
[[ $font_charset == *"e900-e90c"* ]] || fail "Omarchy icon font includes every custom menu glyph"
|
||||
[[ $font_charset == *"e900-e90d"* ]] || fail "Omarchy icon font includes every custom menu glyph"
|
||||
pass "Omarchy icon font includes the official agent marks"
|
||||
Reference in new issue
Block a user