Reshape the agent launcher into omarchy agent (#6757)

* Reshape the agent launcher into omarchy agent

omarchy-launch-agent becomes omarchy-agent, with prompts on omarchy-agent-prompt
rather than the bare route: `omarchy agent` is both a command and a group, so a
positional prompt there would shadow any subcommand under it. The launcher takes
flags only and points at `omarchy agent prompt` when handed one.

Every agent window now launches under a fixed org.omarchy.agent app-id instead of
omarchy-launch-tui's default of org.omarchy.<binary>, so one rule floats them all
whichever agent is default.

Omarchy also stops picking an agent for you. omarchy-default-agent prints nothing
until one is chosen, leaving every entry under Setup > Defaults > Agent unchecked,
and a first-run invitation offers to take you there.

* Wordsmith

* Cover the agent routes and the invitation

The route split is the point of the change, so exercise `omarchy agent`,
`omarchy agent prompt`, and a rejected positional prompt through the router
rather than only the binaries behind them.

The invitation gets the same treatment as the Voxtype and fingerprint ones: it
notifies once, opens the agent defaults menu, and leaves both the notification
and the marker alone for anyone who already chose an agent.

* Offer the agent choice from the keybinding

Super + Shift + Ctrl + A now runs `omarchy-agent --pick`, which opens Setup >
Defaults > Agent when nothing is chosen yet. A keypress that writes to stderr
and opens nothing just looks broken.

* Reach existing installs with the agent invitation

first-run installs the invitation hook, and existing accounts marked it complete
long ago, so they would never see it -- while being the accounts most likely to
need it, since the old getter returned opencode implicitly and most have no
agent recorded at all. Post-update hooks run later in the same update, so the
invitation arrives without waiting for another one.

* Say what the Defaults submenus set

Setup > Defaults lists Agent, Browser, Terminal, Editor, but the header inside
each repeated the same bare word, which reads as a category rather than a
setting -- and says nothing at all when the menu is summoned straight into it.
The list keeps its short labels; the headers now name the setting.
This commit is contained in:
David Heinemeier Hansson
2026-08-12 17:56:19 +02:00
committed by GitHub
parent b97a1480dc
commit 9502b81f3b
12 changed files with 240 additions and 45 deletions
+40 -13
View File
@@ -1,15 +1,35 @@
#!/bin/bash
# omarchy:summary=Launch the default coding agent in a terminal
# omarchy:args=[--inline] [prompt...]
# omarchy:examples=omarchy launch agent | omarchy launch agent "Review this project"
# omarchy:args=[--inline] [--pick]
# omarchy:examples=omarchy agent | omarchy agent --inline
if [[ ${1:-} == "--inline" ]]; then
inline=true
shift
else
inline=false
fi
inline=false
pick=false
# Flags only. A bare prompt would shadow the subcommands under this group, so
# prompts go through omarchy-agent-prompt, which passes one here as --prompt.
while (($#)); do
case "$1" in
--inline)
inline=true
shift
;;
--pick)
pick=true
shift
;;
--prompt)
prompt=${2:?--prompt needs a value}
shift 2
;;
*)
echo "Unexpected argument: $1" >&2
echo "To pass a prompt: omarchy agent prompt \"$*\"" >&2
exit 1
;;
esac
done
# Agents refuse to remember trust for $HOME, so launches from the keybinding or
# menu start in the work directory instead of re-asking on every session.
@@ -17,13 +37,18 @@ fi
agent=$(omarchy-default-agent)
if omarchy-cmd-missing "$agent"; then
echo "$agent is not installed. Choose an installed agent with: omarchy default agent <name>" >&2
# Omarchy ships without a default, so there is nothing to launch until one is
# picked. --pick offers the choice instead of the error, which is what the
# keybinding wants: a keypress that opens nothing explains nothing.
if [[ -z $agent ]]; then
[[ $pick == "true" ]] && exec omarchy-menu summon setup.default.agent
echo "Choose default agent with: omarchy default agent <name>" >&2
exit 1
fi
if (($# > 0)); then
prompt="$*"
if omarchy-cmd-missing "$agent"; then
echo "$agent is not installed. Choose an installed agent with: omarchy default agent <name>" >&2
exit 1
fi
# Agents launched from the keybinding or menu run unattended, so each one starts
@@ -74,5 +99,7 @@ esac
if [[ $inline == "true" ]]; then
exec "${command[@]}"
else
exec omarchy-launch-tui "${command[@]}"
# A fixed app-id rather than the default org.omarchy.<binary>, so every agent
# window shares one class for default/hypr/apps/agent.lua to float.
exec omarchy-launch-tui --app-id=org.omarchy.agent "${command[@]}"
fi
+23
View File
@@ -0,0 +1,23 @@
#!/bin/bash
# omarchy:summary=Launch the default coding agent with a prompt
# omarchy:args=[--inline] <prompt...>
# omarchy:examples=omarchy agent prompt "Review this project"
# Prompts live here rather than on `omarchy agent`, where a bare prompt would
# shadow the subcommands under that group.
set -euo pipefail
inline=()
if [[ ${1:-} == "--inline" ]]; then
inline=(--inline)
shift
fi
if (($# == 0)); then
echo "Usage: omarchy agent prompt [--inline] <prompt...>" >&2
exit 1
fi
exec omarchy-agent "${inline[@]}" --prompt "$*"
+5 -3
View File
@@ -17,7 +17,9 @@ if (($# == 0)); then
read -r agent <"$agent_file"
fi
[[ -n $agent ]] && echo "$agent" || echo "opencode"
# Silent when unset rather than defaulting: Omarchy picks no agent for you, so
# the menu leaves every entry unchecked until one is chosen.
[[ -n ${agent:-} ]] && echo "$agent"
exit 0
fi
@@ -57,7 +59,7 @@ printf '%s\n' "$agent" >"$agent_file"
if [[ $installing == "true" ]]; then
printf '\033[2J\033[3J\033[H'
exec omarchy-launch-agent --inline
exec omarchy-agent --inline
else
exec omarchy-launch-agent
exec omarchy-agent
fi
+2
View File
@@ -72,6 +72,8 @@ run_first_run_step "install Voxtype post-update hook" \
omarchy-hook-install post-update "$OMARCHY_PATH/install/user/first-run/install-voxtype.hook"
run_first_run_step "install fingerprint setup post-update hook" \
omarchy-hook-install post-update "$OMARCHY_PATH/install/user/first-run/setup-fingerprint.hook"
run_first_run_step "install agent setup post-update hook" \
omarchy-hook-install post-update "$OMARCHY_PATH/install/user/first-run/setup-agent.hook"
run_first_run_step "enable user systemd units" \
bash "$OMARCHY_PATH/install/user/first-run/enable-user-units.sh"
+1 -1
View File
@@ -43,7 +43,7 @@ alias ...='cd ../..'
alias ....='cd ../../..'
# Tools
alias a='omarchy-launch-agent --inline'
alias a='omarchy-agent --inline'
alias c='opencode --auto'
alias cx='printf "\033[2J\033[3J\033[H" && claude --permission-mode bypassPermissions'
alias cy='codex -s danger-full-access -a never'
+3
View File
@@ -0,0 +1,3 @@
-- omarchy-agent gives every agent terminal the same app-id, so this
-- floats the keybinding, the menu, and a crash diagnosis alike.
o.window("org\\.omarchy\\.agent", { float = true, center = true, size = { 1200, 800 } })
+1 -1
View File
@@ -93,7 +93,7 @@ o.bind("SUPER + CTRL + ALT + T", "Show time", "omarchy-notification-time")
o.bind("SUPER + CTRL + ALT + B", "Show battery remaining", "omarchy-notification-battery")
o.bind("SUPER + CTRL + ALT + W", "Toggle weather", "omarchy-notification-weather")
o.bind("SUPER + SHIFT + CTRL + A", "Agent", "omarchy-launch-agent")
o.bind("SUPER + SHIFT + CTRL + A", "Agent", "omarchy-agent --pick")
o.bind("SUPER + CTRL + A", "Audio", "omarchy-shell shell toggle omarchy.audio")
o.bind("SUPER + CTRL + B", "Bluetooth", "omarchy-shell shell toggle omarchy.bluetooth")
o.bind("SUPER + CTRL + D", "Display", "omarchy-shell shell toggle omarchy.monitor")
+4 -4
View File
@@ -128,7 +128,7 @@
"setup.network.dns.custom": {"icon":"","label":"Custom","checked":"[[ \"$(omarchy-dns)\" == \"Custom\" ]]","action":"omarchy-launch-floating-terminal-with-presentation 'omarchy-dns Custom'"},
"setup.network.qr": {"icon":"󰐲","label":"QR Code","aliases":["wifi-qr"],"when":"[[ $(omarchy-network-status) == wifi* ]]","action":"omarchy-shell shell summon omarchy.wifiqr"},
"setup.default": {"icon":"","label":"Defaults","aliases":["default","defaults"]},
"setup.default.agent": {"icon":"󰚩","label":"Agent"},
"setup.default.agent": {"icon":"󰚩","label":"Agent","title":"Default Agent"},
"setup.default.agent.claude": {"icon":"󰛄","label":"Claude","checked":"[[ \"$(omarchy-default-agent)\" == \"claude\" ]]","action":"omarchy-default-agent claude"},
"setup.default.agent.codex": {"icon":"","iconFont":"omarchy","label":"Codex","checked":"[[ \"$(omarchy-default-agent)\" == \"codex\" ]]","action":"omarchy-default-agent codex"},
"setup.default.agent.copilot": {"icon":"","label":"Copilot","checked":"[[ \"$(omarchy-default-agent)\" == \"copilot\" ]]","action":"omarchy-default-agent copilot"},
@@ -138,7 +138,7 @@
"setup.default.agent.omp": {"icon":"","iconFont":"omarchy","label":"omp","checked":"[[ \"$(omarchy-default-agent)\" == \"omp\" ]]","action":"omarchy-default-agent omp"},
"setup.default.agent.opencode": {"icon":"","iconFont":"omarchy","label":"OpenCode","checked":"[[ \"$(omarchy-default-agent)\" == \"opencode\" ]]","action":"omarchy-default-agent opencode"},
"setup.default.agent.pi": {"icon":"","iconFont":"omarchy","label":"Pi","checked":"[[ \"$(omarchy-default-agent)\" == \"pi\" ]]","action":"omarchy-default-agent pi"},
"setup.default.browser": {"icon":"","label":"Browser"},
"setup.default.browser": {"icon":"","label":"Browser","title":"Default Browser"},
"setup.default.browser.chromium": {"icon":"","label":"Chromium","when":"omarchy-cmd-present chromium","checked":"[[ \"$(omarchy-default-browser)\" == \"chromium\" ]]","action":"omarchy-default-browser chromium"},
"setup.default.browser.chrome": {"icon":"󰊯","label":"Chrome","when":"omarchy-cmd-present google-chrome-stable","checked":"[[ \"$(omarchy-default-browser)\" == \"chrome\" ]]","action":"omarchy-default-browser chrome"},
"setup.default.browser.brave": {"icon":"󰖟","label":"Brave","when":"omarchy-cmd-present brave","checked":"[[ \"$(omarchy-default-browser)\" == \"brave\" ]]","action":"omarchy-default-browser brave"},
@@ -146,12 +146,12 @@
"setup.default.browser.edge": {"icon":"󰇩","label":"Edge","when":"omarchy-cmd-present microsoft-edge-stable","checked":"[[ \"$(omarchy-default-browser)\" == \"edge\" ]]","action":"omarchy-default-browser edge"},
"setup.default.browser.firefox": {"icon":"","label":"Firefox","when":"omarchy-cmd-present firefox","checked":"[[ \"$(omarchy-default-browser)\" == \"firefox\" ]]","action":"omarchy-default-browser firefox"},
"setup.default.browser.zen": {"icon":"󰖟","label":"Zen","when":"omarchy-cmd-present zen-browser","checked":"[[ \"$(omarchy-default-browser)\" == \"zen\" ]]","action":"omarchy-default-browser zen"},
"setup.default.terminal": {"icon":"","label":"Terminal"},
"setup.default.terminal": {"icon":"","label":"Terminal","title":"Default Terminal"},
"setup.default.terminal.alacritty": {"icon":"","label":"Alacritty","when":"omarchy-cmd-present alacritty","checked":"[[ \"$(omarchy-default-terminal)\" == \"alacritty\" ]]","action":"omarchy-default-terminal alacritty"},
"setup.default.terminal.foot": {"icon":"","label":"Foot","when":"omarchy-cmd-present foot","checked":"[[ \"$(omarchy-default-terminal)\" == \"foot\" ]]","action":"omarchy-default-terminal foot"},
"setup.default.terminal.ghostty": {"icon":"","label":"Ghostty","when":"omarchy-cmd-present ghostty","checked":"[[ \"$(omarchy-default-terminal)\" == \"ghostty\" ]]","action":"omarchy-default-terminal ghostty"},
"setup.default.terminal.kitty": {"icon":"","label":"Kitty","when":"omarchy-cmd-present kitty","checked":"[[ \"$(omarchy-default-terminal)\" == \"kitty\" ]]","action":"omarchy-default-terminal kitty"},
"setup.default.editor": {"icon":"","label":"Editor"},
"setup.default.editor": {"icon":"","label":"Editor","title":"Default Editor"},
"setup.default.editor.neovim": {"icon":"","label":"Neovim","when":"omarchy-cmd-present nvim","checked":"[[ \"$(omarchy-default-editor)\" == \"nvim\" ]]","action":"omarchy-default-editor nvim"},
"setup.default.editor.vscode": {"icon":"","label":"VSCode","when":"omarchy-cmd-present code","checked":"[[ \"$(omarchy-default-editor)\" == \"code\" ]]","action":"omarchy-default-editor code"},
"setup.default.editor.cursor": {"icon":"","label":"Cursor","when":"omarchy-cmd-present cursor","checked":"[[ \"$(omarchy-default-editor)\" == \"cursor\" ]]","action":"omarchy-default-editor cursor"},
+11
View File
@@ -0,0 +1,11 @@
#!/bin/bash
set -e
# Omarchy ships no default agent, so invite once rather than picking one. An
# agent already chosen means the invitation has nothing to offer.
if [[ -z $(omarchy-default-agent) ]] && omarchy-done ensure agent-setup-invitation; then
omarchy-notification-send -u critical -g 󰚩 "Set your default agent" \
"Let your favorite agent help with Omarchy." \
--exec "omarchy menu summon setup.default.agent"
fi
+10
View File
@@ -0,0 +1,10 @@
echo "Invite existing installs to pick a default agent"
# The invitation is installed by first-run, which existing accounts have already
# marked complete, so they would never receive it. They are also the accounts
# most likely to need it: the old getter returned opencode implicitly, so most
# have no agent recorded at all.
#
# Post-update hooks run later in this same update, so the invitation appears
# without waiting for another one. The hook decides whether to notify.
omarchy-hook-install post-update "$OMARCHY_PATH/install/user/first-run/setup-agent.hook"
+61
View File
@@ -0,0 +1,61 @@
#!/bin/bash
source "$(dirname "$0")/base-test.sh"
test_home=$(mktemp -d)
test_bin=$(mktemp -d)
log_file=$(mktemp)
hook_path="$test_home/.config/omarchy/hooks/post-update.d/setup-agent.hook"
cleanup() {
rm -rf "$test_home" "$test_bin"
rm -f "$log_file"
}
trap cleanup EXIT
mkdir -p "$(dirname "$hook_path")"
cat >"$test_bin/omarchy-notification-send" <<'EOF'
#!/bin/bash
echo notification >>"$TEST_LOG"
while (($# > 0)); do
[[ $1 == "--exec" ]] && echo "exec:$2" >>"$TEST_LOG"
shift
done
EOF
chmod +x "$test_bin/omarchy-notification-send"
run_invitation_hook() {
cp "$ROOT/install/user/first-run/setup-agent.hook" "$hook_path"
HOME="$test_home" PATH="$test_bin:$ROOT/bin:$PATH" TEST_LOG="$log_file" bash "$hook_path"
}
run_invitation_hook
[[ -f $test_home/.local/state/omarchy/done/agent-setup-invitation ]] || fail "agent invitation records completion"
[[ -f $hook_path ]] || fail "agent invitation keeps its hook installed"
[[ $(grep -c '^notification$' "$log_file") -eq 1 ]] || fail "agent invitation sends one notification"
grep -qx 'exec:omarchy menu summon setup.default.agent' "$log_file" ||
fail "agent invitation opens the agent defaults menu"
run_invitation_hook
[[ $(grep -c '^notification$' "$log_file") -eq 1 ]] || fail "completed agent invitation does not notify again"
pass "agent invitation only runs once"
# Someone who already chose an agent has nothing to be invited to, and must not
# burn the marker either -- otherwise clearing the choice later leaves them with
# no invitation and no default.
fresh_home=$(mktemp -d)
mkdir -p "$fresh_home/.config/omarchy/defaults"
printf 'claude\n' >"$fresh_home/.config/omarchy/defaults/agent"
: >"$log_file"
cp "$ROOT/install/user/first-run/setup-agent.hook" "$hook_path"
HOME="$fresh_home" PATH="$test_bin:$ROOT/bin:$PATH" TEST_LOG="$log_file" bash "$hook_path"
[[ ! -s $log_file ]] || fail "agent invitation stays quiet when a default is already set"
[[ ! -f $fresh_home/.local/state/omarchy/done/agent-setup-invitation ]] ||
fail "agent invitation leaves its marker unset when a default is already set"
rm -rf "$fresh_home"
pass "agent invitation skips anyone who already chose an agent"
+79 -23
View File
@@ -18,6 +18,7 @@ mise_log="$test_tmp/mise"
mise_history="$test_tmp/mise-history"
stub_log="$test_tmp/stubs"
terminal_log="$test_tmp/terminal"
menu_log="$test_tmp/menu"
mkdir -p "$mock_bin" "$test_home"
cat >"$mock_bin/omarchy-notification-send" <<'SH'
@@ -63,6 +64,11 @@ fi
[[ ${OMARCHY_TEST_MISE_FAIL:-false} != "true" ]]
SH
cat >"$mock_bin/omarchy-menu" <<'SH'
#!/bin/bash
printf '%s\0' "$@" >"$OMARCHY_TEST_AGENT_MENU_LOG"
SH
cat >"$mock_bin/omarchy-test-noop" <<'SH'
#!/bin/bash
exit 0
@@ -84,6 +90,7 @@ export OMARCHY_TEST_MISE_LOG="$mise_log"
export OMARCHY_TEST_MISE_HISTORY="$mise_history"
export OMARCHY_TEST_STUB_LOG="$stub_log"
export OMARCHY_TEST_AGENT_TERMINAL_LOG="$terminal_log"
export OMARCHY_TEST_AGENT_MENU_LOG="$menu_log"
grok_package="npm:@xai-official/grok"
omp_package="github:can1357/oh-my-pi"
@@ -140,30 +147,44 @@ for command in omp grok crush; do
done
pass "Remove Preinstalls deletes every optional agent lazy stub"
[[ $(omarchy-default-agent) == "opencode" ]] || fail "default agent falls back to OpenCode"
pass "default agent falls back to OpenCode"
[[ -z $(omarchy-default-agent) ]] || fail "default agent is unset until one is chosen"
pass "default agent is unset until one is chosen"
omarchy-launch-agent
mapfile -d '' -t launch_args <"$launch_log"
[[ ${launch_args[*]} == "opencode --auto" ]] ||
fail "agent launcher falls back to OpenCode before a default is selected"
pass "agent launcher falls back to OpenCode before a default is selected"
: >"$launch_log"
if omarchy-agent >"$test_tmp/no-agent-output" 2>&1; then
fail "agent launcher refuses to launch without a default"
fi
grep -Fq "Choose default agent with" "$test_tmp/no-agent-output" ||
fail "agent launcher explains that no default is set"
[[ ! -s $launch_log ]] || fail "agent launcher starts nothing without a default"
pass "agent launcher refuses to launch without a default"
# The keybinding uses --pick, where an error on stderr nobody sees would make
# the keypress look broken. It offers the choice instead.
: >"$launch_log"
: >"$menu_log"
omarchy-agent --pick
mapfile -d '' -t menu_args <"$menu_log"
[[ ${menu_args[*]} == "summon setup.default.agent" ]] ||
fail "--pick opens the agent defaults menu when none is set"
[[ ! -s $launch_log ]] || fail "--pick starts nothing when no agent is set"
pass "--pick opens the agent defaults menu when none is set"
source "$ROOT/default/bash/aliases"
[[ $(alias a) == "alias a='omarchy-launch-agent --inline'" ]] ||
[[ $(alias a) == "alias a='omarchy-agent --inline'" ]] ||
fail "terminal alias launches the default agent inline"
pass "terminal alias launches the default agent inline"
grep -Fq 'o.bind("SUPER + SHIFT + CTRL + A", "Agent", "omarchy-launch-agent")' \
grep -Fq 'o.bind("SUPER + SHIFT + CTRL + A", "Agent", "omarchy-agent --pick")' \
"$ROOT/default/hypr/bindings/utilities.lua" ||
fail "agent launcher has a keyboard shortcut"
pass "agent launcher has a keyboard shortcut"
cat >"$mock_bin/omarchy-launch-agent" <<'SH'
cat >"$mock_bin/omarchy-agent" <<'SH'
#!/bin/bash
printf '%s\0' omarchy-launch-agent "$@" >"$OMARCHY_TEST_AGENT_OPEN_LOG"
printf '%s\0' omarchy-agent "$@" >"$OMARCHY_TEST_AGENT_OPEN_LOG"
SH
chmod +x "$mock_bin/omarchy-launch-agent"
chmod +x "$mock_bin/omarchy-agent"
hash -r
declare -A expected_agents=(
@@ -206,7 +227,7 @@ for selection in "${!expected_agents[@]}"; do
fail "default agent installs $selection globally through mise"
mapfile -d '' -t agent_open_args <"$agent_open_log"
[[ ${#agent_open_args[@]} == 1 && ${agent_open_args[0]} == "omarchy-launch-agent" ]] ||
[[ ${#agent_open_args[@]} == 1 && ${agent_open_args[0]} == "omarchy-agent" ]] ||
fail "default agent opens $selection after selecting it"
done
pass "default agent selects and opens every supported provider and alias"
@@ -235,7 +256,7 @@ mapfile -d '' -t mise_args <"$mise_log"
[[ $(<"$test_tmp/install-output") == $'\033[2J\033[3J\033[H' ]] ||
fail "visible agent installation clears its terminal before opening the agent"
mapfile -d '' -t agent_open_args <"$agent_open_log"
[[ ${#agent_open_args[@]} == 2 && ${agent_open_args[0]} == "omarchy-launch-agent" && ${agent_open_args[1]} == "--inline" ]] ||
[[ ${#agent_open_args[@]} == 2 && ${agent_open_args[0]} == "omarchy-agent" && ${agent_open_args[1]} == "--inline" ]] ||
fail "newly installed agent opens in the installation terminal"
pass "missing agents install visibly and open in the same terminal"
@@ -249,7 +270,7 @@ mapfile -d '' -t mise_args <"$mise_log"
[[ ${mise_args[0]} == "use" && ${mise_args[1]} == "-g" && ${mise_args[2]} == "copilot" ]] ||
fail "default agent still activates an installed provider globally through mise"
mapfile -d '' -t agent_open_args <"$agent_open_log"
[[ ${#agent_open_args[@]} == 1 && ${agent_open_args[0]} == "omarchy-launch-agent" ]] ||
[[ ${#agent_open_args[@]} == 1 && ${agent_open_args[0]} == "omarchy-agent" ]] ||
fail "installed agent opens in a new terminal after selection"
pass "installed agents select and open without notifications"
@@ -287,14 +308,16 @@ grep -F "Could not set Codex as the default coding agent" "$test_tmp/setup-failu
[[ ! -s $agent_open_log ]] || fail "failed activation does not open an agent"
pass "default agent reports mise failures without notifications"
rm "$mock_bin/omarchy-launch-agent"
rm "$mock_bin/omarchy-agent"
hash -r
assert_launched() {
local agent=$1
local description=$2
shift 2
local expected=("$@")
# Every agent window launches under the same app-id, whichever agent is
# default, so default/hypr/apps/agent.lua can float them all.
local expected=(--app-id=org.omarchy.agent "$@")
mapfile -d '' -t actual <"$launch_log"
@@ -312,7 +335,7 @@ assert_launch() {
shift
printf '%s\n' "$agent" >"$agent_file"
omarchy-launch-agent "Review this" project
omarchy-agent-prompt "Review this" project
assert_launched "$agent" "forwards the interactive prompt" "$@"
}
@@ -321,7 +344,7 @@ assert_bypass() {
shift
printf '%s\n' "$agent" >"$agent_file"
omarchy-launch-agent
omarchy-agent
assert_launched "$agent" "skips permission prompts" "$@"
}
@@ -348,20 +371,53 @@ assert_bypass copilot copilot --allow-all
pass "agent launcher skips permission prompts for every supported agent"
printf '%s\n' "opencode" >"$agent_file"
omarchy-launch-agent
omarchy-agent
mapfile -d '' -t launch_args <"$launch_log"
[[ ${launch_args[*]} == "opencode --auto" ]] ||
[[ ${launch_args[*]} == "--app-id=org.omarchy.agent opencode --auto" ]] ||
fail "agent launcher starts the selected agent without an initial prompt"
pass "agent launcher starts the selected agent without an initial prompt"
omarchy-launch-agent --inline "Review this project"
omarchy-agent-prompt --inline "Review this project"
mapfile -d '' -t inline_args <"$inline_log"
[[ ${inline_args[*]} == "opencode --auto --prompt Review this project" ]] ||
fail "inline agent launcher runs in the current terminal"
pass "inline agent launcher runs in the current terminal"
# The prompt route exists so the router can tell a prompt from a subcommand, so
# cover the public routes and not only the binaries behind them.
: >"$launch_log"
omarchy agent
mapfile -d '' -t launch_args <"$launch_log"
[[ ${launch_args[*]} == "--app-id=org.omarchy.agent opencode --auto" ]] ||
fail "omarchy agent routes to the launcher"
# With an agent chosen there is nothing to pick, so the keybinding launches.
: >"$launch_log"
: >"$menu_log"
omarchy-agent --pick
mapfile -d '' -t launch_args <"$launch_log"
[[ ${launch_args[*]} == "--app-id=org.omarchy.agent opencode --auto" ]] ||
fail "--pick launches once an agent is chosen"
[[ ! -s $menu_log ]] || fail "--pick opens no menu once an agent is chosen"
pass "--pick launches once an agent is chosen"
: >"$launch_log"
omarchy agent prompt "Review this project"
mapfile -d '' -t launch_args <"$launch_log"
[[ ${launch_args[*]} == "--app-id=org.omarchy.agent opencode --auto --prompt Review this project" ]] ||
fail "omarchy agent prompt routes the prompt to the launcher"
: >"$launch_log"
if omarchy agent Review this project >"$test_tmp/positional-output" 2>&1; then
fail "omarchy agent rejects a positional prompt"
fi
grep -F "omarchy agent prompt" "$test_tmp/positional-output" >/dev/null ||
fail "omarchy agent points a positional prompt at the prompt route"
[[ ! -s $launch_log ]] || fail "omarchy agent starts nothing for a positional prompt"
pass "omarchy agent keeps prompts on the prompt route"
printf '%s\n' "missing" >"$agent_file"
if OMARCHY_TEST_MISSING_COMMAND=missing omarchy-launch-agent >"$test_tmp/missing-output" 2>&1; then
if OMARCHY_TEST_MISSING_COMMAND=missing omarchy-agent >"$test_tmp/missing-output" 2>&1; then
fail "agent launcher rejects a missing default command"
fi
grep -F "missing is not installed" "$test_tmp/missing-output" >/dev/null ||