Add Muse Code as a default coding agent (#9915)
* Add Muse Code as a default coding agent
Meta ships Muse Code only as a binary, so it installs from the AUR
(muse-code-bin) instead of mise, and a fresh install runs the muse login
browser flow in the install terminal before the agent opens.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0148qKzr366p2Ubu2igCLvPg
* Refine Muse Code menu and prompt forwarding
* Install Muse Code from OPR
* Install Muse Code through mise's HTTP backend
* Preinstall the Muse mise stub
* Use the shared Muse installation flow
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: David Heinemeier Hansson <david@hey.com>
(cherry picked from commit 0d223fe820)
This commit is contained in:
1 parent
a9e1c01ee9
commit
c5b59bcfff
10 files changed
+177
-7
No files matched your search
@@ -110,6 +110,11 @@ hermes)
|
|||||||
command=(hermes --yolo)
|
command=(hermes --yolo)
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
|
muse)
|
||||||
|
# --approval-mode never skips the tool prompts but keeps Muse's own sandbox.
|
||||||
|
command=(muse --approval-mode never)
|
||||||
|
[[ -n ${prompt:-} ]] && command+=(-- "$prompt")
|
||||||
|
;;
|
||||||
omp)
|
omp)
|
||||||
command=(omp --auto-approve)
|
command=(omp --auto-approve)
|
||||||
[[ -n ${prompt:-} ]] && command+=(-- "$prompt")
|
[[ -n ${prompt:-} ]] && command+=(-- "$prompt")
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# omarchy:summary=Set and launch the default coding agent
|
# omarchy:summary=Set and launch the default coding agent
|
||||||
# omarchy:args=[pi|omp|opencode|claude|codex|grok|gemini|openclaw|hermes|copilot|crush|cursor-agent]
|
# omarchy:args=[pi|omp|opencode|claude|codex|grok|gemini|openclaw|hermes|copilot|crush|cursor-agent|muse]
|
||||||
# omarchy:examples=omarchy default agent | omarchy default agent codex | omarchy default agent claude
|
# omarchy:examples=omarchy default agent | omarchy default agent codex | omarchy default agent claude
|
||||||
|
|
||||||
installing=false
|
installing=false
|
||||||
@@ -35,9 +35,14 @@ gemini | gemini-cli) agent="gemini"; name="Gemini" ;;
|
|||||||
openclaw) agent="openclaw"; name="OpenClaw"; agent_installer="omarchy-install-openclaw-cli" ;;
|
openclaw) agent="openclaw"; name="OpenClaw"; agent_installer="omarchy-install-openclaw-cli" ;;
|
||||||
hermes) agent="hermes"; name="Hermes"; agent_installer="omarchy-install-hermes-cli" ;;
|
hermes) agent="hermes"; name="Hermes"; agent_installer="omarchy-install-hermes-cli" ;;
|
||||||
copilot | github-copilot) agent="copilot"; name="GitHub Copilot" ;;
|
copilot | github-copilot) agent="copilot"; name="GitHub Copilot" ;;
|
||||||
|
muse | muse-code | musecode)
|
||||||
|
agent="muse"; name="Muse Code"
|
||||||
|
# Meta's launcher verifies and updates the native binary for this platform.
|
||||||
|
agent_package="http:muse[url=https://api.meta.ai/muse-launcher.sh,bin=muse,version_list_url=https://api.meta.ai/muse-code/channels/muse-stable,version_json_path=.version]"
|
||||||
|
;;
|
||||||
cursor | cursor-agent) agent="cursor-agent"; name="Cursor CLI" ;;
|
cursor | cursor-agent) agent="cursor-agent"; name="Cursor CLI" ;;
|
||||||
*)
|
*)
|
||||||
echo "Usage: omarchy-default-agent <pi|omp|opencode|claude|codex|grok|gemini|openclaw|hermes|copilot|crush|cursor-agent>"
|
echo "Usage: omarchy-default-agent <pi|omp|opencode|claude|codex|grok|gemini|openclaw|hermes|copilot|crush|cursor-agent|muse>"
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|||||||
@@ -24,6 +24,12 @@ if gum confirm "Are you sure you want to remove all preinstalled web apps, TUI w
|
|||||||
rm -f ~/.local/bin/cursor-agent
|
rm -f ~/.local/bin/cursor-agent
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Preserve a user-managed Muse launcher at the same path.
|
||||||
|
if [[ -f ~/.local/bin/muse && ! -L ~/.local/bin/muse ]] &&
|
||||||
|
grep -Eq '^mise use -g .*"http:muse\[' ~/.local/bin/muse; then
|
||||||
|
rm -f ~/.local/bin/muse
|
||||||
|
fi
|
||||||
|
|
||||||
# Only the wrapper omarchy-install-hermes-cli wrote is a preinstall. Hermes
|
# Only the wrapper omarchy-install-hermes-cli wrote is a preinstall. Hermes
|
||||||
# Desktop's command, an official install, or anything else at that path is
|
# Desktop's command, an official install, or anything else at that path is
|
||||||
# the user's, so it is the installer that decides whether the wrapper is its
|
# the user's, so it is the installer that decides whether the wrapper is its
|
||||||
|
|||||||
@@ -138,6 +138,7 @@
|
|||||||
"setup.default.agent.gemini": {"icon":"","label":"Gemini","checked":"[[ \"$(omarchy-default-agent)\" == \"gemini\" ]]","action":"omarchy-default-agent gemini"},
|
"setup.default.agent.gemini": {"icon":"","label":"Gemini","checked":"[[ \"$(omarchy-default-agent)\" == \"gemini\" ]]","action":"omarchy-default-agent gemini"},
|
||||||
"setup.default.agent.grok": {"icon":"","iconFont":"omarchy","label":"Grok","checked":"[[ \"$(omarchy-default-agent)\" == \"grok\" ]]","action":"omarchy-default-agent grok"},
|
"setup.default.agent.grok": {"icon":"","iconFont":"omarchy","label":"Grok","checked":"[[ \"$(omarchy-default-agent)\" == \"grok\" ]]","action":"omarchy-default-agent grok"},
|
||||||
"setup.default.agent.hermes": {"icon":"","iconFont":"omarchy","label":"Hermes","checked":"[[ \"$(omarchy-default-agent)\" == \"hermes\" ]]","action":"omarchy-default-agent hermes"},
|
"setup.default.agent.hermes": {"icon":"","iconFont":"omarchy","label":"Hermes","checked":"[[ \"$(omarchy-default-agent)\" == \"hermes\" ]]","action":"omarchy-default-agent hermes"},
|
||||||
|
"setup.default.agent.muse": {"icon":"","label":"Muse Code","checked":"[[ \"$(omarchy-default-agent)\" == \"muse\" ]]","action":"omarchy-default-agent muse"},
|
||||||
"setup.default.agent.omp": {"icon":"","iconFont":"omarchy","label":"omp","checked":"[[ \"$(omarchy-default-agent)\" == \"omp\" ]]","action":"omarchy-default-agent omp"},
|
"setup.default.agent.omp": {"icon":"","iconFont":"omarchy","label":"omp","checked":"[[ \"$(omarchy-default-agent)\" == \"omp\" ]]","action":"omarchy-default-agent omp"},
|
||||||
"setup.default.agent.openclaw": {"icon":"","iconFont":"omarchy","label":"OpenClaw","checked":"[[ \"$(omarchy-default-agent)\" == \"openclaw\" ]]","action":"omarchy-default-agent openclaw"},
|
"setup.default.agent.openclaw": {"icon":"","iconFont":"omarchy","label":"OpenClaw","checked":"[[ \"$(omarchy-default-agent)\" == \"openclaw\" ]]","action":"omarchy-default-agent openclaw"},
|
||||||
"setup.default.agent.opencode": {"icon":"","iconFont":"omarchy","label":"OpenCode","checked":"[[ \"$(omarchy-default-agent)\" == \"opencode\" ]]","action":"omarchy-default-agent opencode"},
|
"setup.default.agent.opencode": {"icon":"","iconFont":"omarchy","label":"OpenCode","checked":"[[ \"$(omarchy-default-agent)\" == \"opencode\" ]]","action":"omarchy-default-agent opencode"},
|
||||||
|
|||||||
@@ -23,3 +23,6 @@ omarchy-mise-install aqua:modem-dev/hunk hunk
|
|||||||
# omarchy-provision-user -- the default browser, the mailto handler and the
|
# omarchy-provision-user -- the default browser, the mailto handler and the
|
||||||
# finalize-user marker all come after it.
|
# finalize-user marker all come after it.
|
||||||
omarchy-install-hermes-cli || true
|
omarchy-install-hermes-cli || true
|
||||||
|
if omarchy-cmd-missing muse; then
|
||||||
|
omarchy-mise-install "http:muse[url=https://api.meta.ai/muse-launcher.sh,bin=muse,version_list_url=https://api.meta.ai/muse-code/channels/muse-stable,version_json_path=.version]" muse
|
||||||
|
fi
|
||||||
@@ -14,6 +14,7 @@ Omarchy treats AI coding agents as first-class citizens, but it doesn't pick a f
|
|||||||
| `pi` | [Mario Zechner's Pi](https://github.com/badlogic/pi-mono) |
|
| `pi` | [Mario Zechner's Pi](https://github.com/badlogic/pi-mono) |
|
||||||
| `omp` | [Oh My Pi](https://github.com/can1357/oh-my-pi) |
|
| `omp` | [Oh My Pi](https://github.com/can1357/oh-my-pi) |
|
||||||
| `hermes` | [Hermes](https://hermes-agent.nousresearch.com/), Nous Research's agent |
|
| `hermes` | [Hermes](https://hermes-agent.nousresearch.com/), Nous Research's agent |
|
||||||
|
| `muse` | [Muse Code](https://dev.meta.ai), Meta's coding agent |
|
||||||
| `cursor-agent` | [Cursor CLI](https://cursor.com/cli) |
|
| `cursor-agent` | [Cursor CLI](https://cursor.com/cli) |
|
||||||
|
|
||||||
To wrap an additional CLI the same way, run `omarchy-mise-install <package> [command-name]`. The stubs are kept current along with everything else mise manages when you run `omarchy update` (or the `mup` alias).
|
To wrap an additional CLI the same way, run `omarchy-mise-install <package> [command-name]`. The stubs are kept current along with everything else mise manages when you run `omarchy update` (or the `mup` alias).
|
||||||
@@ -22,6 +23,8 @@ To wrap an additional CLI the same way, run `omarchy-mise-install <package> [com
|
|||||||
|
|
||||||
Pick your default agent with `omarchy default agent <name>` or under _Setup > Defaults > Agent_ in the Omarchy Menu (`Super + Space`). If the agent isn't installed yet, picking it installs it first. A fresh Omarchy will invite you to make this choice with a one-time notification.
|
Pick your default agent with `omarchy default agent <name>` or under _Setup > Defaults > Agent_ in the Omarchy Menu (`Super + Space`). If the agent isn't installed yet, picking it installs it first. A fresh Omarchy will invite you to make this choice with a one-time notification.
|
||||||
|
|
||||||
|
[Muse Code](https://dev.meta.ai) — Meta's `muse` — uses a preinstalled mise stub like the other agents. Picking it as the default installs Meta's official launcher through mise's HTTP backend. The launcher verifies and updates the native binary for your machine.
|
||||||
|
|
||||||
Once you've chosen, `Super + Shift + Ctrl + A` launches the default agent in a dedicated terminal window (or brings up the picker if you haven't chosen yet). You can also launch it straight into a task with `omarchy agent prompt "Review this project"`. Agents launched this way run unattended in their respective don't-stop-to-ask modes, so be ready for them to actually do things! And since agents refuse to remember trust for your home directory, launches from `$HOME` start in `~/Work` instead.
|
Once you've chosen, `Super + Shift + Ctrl + A` launches the default agent in a dedicated terminal window (or brings up the picker if you haven't chosen yet). You can also launch it straight into a task with `omarchy agent prompt "Review this project"`. Agents launched this way run unattended in their respective don't-stop-to-ask modes, so be ready for them to actually do things! And since agents refuse to remember trust for your home directory, launches from `$HOME` start in `~/Work` instead.
|
||||||
|
|
||||||
There are terminal shortcuts too: `a` runs the default agent inline in the current terminal, while `c`, `cx`, and `cy` start OpenCode, Claude Code, and Codex directly (again in their auto-approving modes). Theme changes sync to the agents as well: Claude Code, Pi, OpenCode, and Hermes (once Hermes Desktop is installed) all follow along when you switch the Omarchy theme.
|
There are terminal shortcuts too: `a` runs the default agent inline in the current terminal, while `c`, `cx`, and `cy` start OpenCode, Claude Code, and Codex directly (again in their auto-approving modes). Theme changes sync to the agents as well: Claude Code, Pi, OpenCode, and Hermes (once Hermes Desktop is installed) all follow along when you switch the Omarchy theme.
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
echo "Install Muse Code via mise wrapper"
|
||||||
|
|
||||||
|
if omarchy-cmd-missing muse && [[ ! -f $HOME/.local/state/omarchy/preinstalls-removed ]]; then
|
||||||
|
omarchy-mise-install "http:muse[url=https://api.meta.ai/muse-launcher.sh,bin=muse,version_list_url=https://api.meta.ai/muse-code/channels/muse-stable,version_json_path=.version]" muse
|
||||||
|
fi
|
||||||
@@ -19,6 +19,7 @@ mise_history="$test_tmp/mise-history"
|
|||||||
stub_log="$test_tmp/stubs"
|
stub_log="$test_tmp/stubs"
|
||||||
terminal_log="$test_tmp/terminal"
|
terminal_log="$test_tmp/terminal"
|
||||||
menu_log="$test_tmp/menu"
|
menu_log="$test_tmp/menu"
|
||||||
|
muse_login_log="$test_tmp/muse-login"
|
||||||
mkdir -p "$mock_bin" "$test_home"
|
mkdir -p "$mock_bin" "$test_home"
|
||||||
|
|
||||||
cat >"$mock_bin/omarchy-notification-send" <<'SH'
|
cat >"$mock_bin/omarchy-notification-send" <<'SH'
|
||||||
@@ -69,6 +70,22 @@ cat >"$mock_bin/omarchy-menu" <<'SH'
|
|||||||
printf '%s\0' "$@" >"$OMARCHY_TEST_AGENT_MENU_LOG"
|
printf '%s\0' "$@" >"$OMARCHY_TEST_AGENT_MENU_LOG"
|
||||||
SH
|
SH
|
||||||
|
|
||||||
|
cat >"$mock_bin/omarchy-pkg-add" <<'SH'
|
||||||
|
#!/bin/bash
|
||||||
|
echo "Muse must install through mise" >&2
|
||||||
|
exit 1
|
||||||
|
SH
|
||||||
|
ln -s omarchy-pkg-add "$mock_bin/omarchy-pkg-aur-add"
|
||||||
|
|
||||||
|
cat >"$mock_bin/muse" <<'SH'
|
||||||
|
#!/bin/bash
|
||||||
|
if [[ ${1:-} == "login" ]]; then
|
||||||
|
printf 'muse %s\n' "$*" >>"$OMARCHY_TEST_MUSE_LOGIN_LOG"
|
||||||
|
else
|
||||||
|
printf '%s\0' muse "$@" >"$OMARCHY_TEST_AGENT_INLINE_LOG"
|
||||||
|
fi
|
||||||
|
SH
|
||||||
|
|
||||||
cat >"$mock_bin/omarchy-test-noop" <<'SH'
|
cat >"$mock_bin/omarchy-test-noop" <<'SH'
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
exit 0
|
exit 0
|
||||||
@@ -91,11 +108,14 @@ export OMARCHY_TEST_MISE_HISTORY="$mise_history"
|
|||||||
export OMARCHY_TEST_STUB_LOG="$stub_log"
|
export OMARCHY_TEST_STUB_LOG="$stub_log"
|
||||||
export OMARCHY_TEST_AGENT_TERMINAL_LOG="$terminal_log"
|
export OMARCHY_TEST_AGENT_TERMINAL_LOG="$terminal_log"
|
||||||
export OMARCHY_TEST_AGENT_MENU_LOG="$menu_log"
|
export OMARCHY_TEST_AGENT_MENU_LOG="$menu_log"
|
||||||
|
export OMARCHY_TEST_MUSE_LOGIN_LOG="$muse_login_log"
|
||||||
|
export OMARCHY_PATH="$ROOT"
|
||||||
|
|
||||||
grok_package="npm:@xai-official/grok"
|
grok_package="npm:@xai-official/grok"
|
||||||
omp_package="github:can1357/oh-my-pi"
|
omp_package="github:can1357/oh-my-pi"
|
||||||
crush_package="crush"
|
crush_package="crush"
|
||||||
cursor_agent_package="cursor-agent"
|
cursor_agent_package="cursor-agent"
|
||||||
|
muse_package="http:muse[url=https://api.meta.ai/muse-launcher.sh,bin=muse,version_list_url=https://api.meta.ai/muse-code/channels/muse-stable,version_json_path=.version]"
|
||||||
|
|
||||||
assert_lazy_stub() {
|
assert_lazy_stub() {
|
||||||
local package=$1
|
local package=$1
|
||||||
@@ -114,6 +134,7 @@ assert_lazy_stub "$grok_package" grok
|
|||||||
assert_lazy_stub "$omp_package" omp
|
assert_lazy_stub "$omp_package" omp
|
||||||
assert_lazy_stub "$crush_package" crush
|
assert_lazy_stub "$crush_package" crush
|
||||||
assert_lazy_stub "$cursor_agent_package" cursor-agent
|
assert_lazy_stub "$cursor_agent_package" cursor-agent
|
||||||
|
assert_lazy_stub "$muse_package" muse
|
||||||
pass "custom agent lazy stubs preserve their mise packages"
|
pass "custom agent lazy stubs preserve their mise packages"
|
||||||
|
|
||||||
OMARCHY_TEST_MISSING_COMMAND=cursor-agent source "$ROOT/install/user/mise.sh"
|
OMARCHY_TEST_MISSING_COMMAND=cursor-agent source "$ROOT/install/user/mise.sh"
|
||||||
@@ -121,12 +142,29 @@ grep -Fx "$grok_package grok" "$stub_log" >/dev/null || fail "user setup creates
|
|||||||
grep -Fx "$cursor_agent_package" "$stub_log" >/dev/null || fail "user setup creates the Cursor CLI 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 "$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 "$crush_package" "$stub_log" >/dev/null || fail "user setup creates the Crush lazy stub"
|
||||||
|
OMARCHY_TEST_MISSING_COMMAND=muse source "$ROOT/install/user/mise.sh"
|
||||||
|
grep -Fx "$muse_package muse" "$stub_log" >/dev/null || fail "user setup creates the Muse lazy stub"
|
||||||
pass "user setup creates the custom agent lazy stubs"
|
pass "user setup creates the custom agent lazy stubs"
|
||||||
|
|
||||||
: >"$stub_log"
|
: >"$stub_log"
|
||||||
source "$ROOT/install/user/mise.sh"
|
source "$ROOT/install/user/mise.sh"
|
||||||
grep -Fx "$cursor_agent_package" "$stub_log" >/dev/null && fail "user setup replaces an existing cursor-agent command"
|
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"
|
pass "user setup keeps an existing Cursor CLI install"
|
||||||
|
grep -Fx "$muse_package muse" "$stub_log" >/dev/null && fail "user setup replaces an existing Muse command"
|
||||||
|
|
||||||
|
: >"$stub_log"
|
||||||
|
OMARCHY_TEST_MISSING_COMMAND=muse source "$ROOT/migrations/1788724825.sh" >/dev/null
|
||||||
|
grep -Fx "$muse_package muse" "$stub_log" >/dev/null || fail "Muse migration creates its lazy stub"
|
||||||
|
: >"$stub_log"
|
||||||
|
source "$ROOT/migrations/1788724825.sh" >/dev/null
|
||||||
|
[[ ! -s $stub_log ]] || fail "Muse migration replaces an existing command"
|
||||||
|
mkdir -p "$test_home/.local/state/omarchy"
|
||||||
|
touch "$test_home/.local/state/omarchy/preinstalls-removed"
|
||||||
|
OMARCHY_TEST_MISSING_COMMAND=muse source "$ROOT/migrations/1788724825.sh" >/dev/null
|
||||||
|
[[ ! -s $stub_log ]] || fail "Muse migration ignores the preinstall opt-out"
|
||||||
|
rm "$test_home/.local/state/omarchy/preinstalls-removed"
|
||||||
|
pass "Muse migration preserves existing installs and the preinstall opt-out"
|
||||||
|
|
||||||
|
|
||||||
: >"$stub_log"
|
: >"$stub_log"
|
||||||
source "$ROOT/migrations/1785617047.sh" >/dev/null
|
source "$ROOT/migrations/1785617047.sh" >/dev/null
|
||||||
@@ -179,8 +217,9 @@ rm -f "$test_home/.local/bin/omp"
|
|||||||
rm "$test_home/.local/state/omarchy/preinstalls-removed"
|
rm "$test_home/.local/state/omarchy/preinstalls-removed"
|
||||||
pass "agent migrations install working wrappers without overriding the preinstall opt-out"
|
pass "agent migrations install working wrappers without overriding the preinstall opt-out"
|
||||||
|
|
||||||
|
"$ROOT/bin/omarchy-mise-install" "$muse_package" muse
|
||||||
omarchy-remove-preinstalls >/dev/null
|
omarchy-remove-preinstalls >/dev/null
|
||||||
for command in omp grok crush cursor-agent; do
|
for command in omp grok crush cursor-agent muse; do
|
||||||
[[ ! -e $test_home/.local/bin/$command ]] || fail "Remove Preinstalls deletes the $command lazy stub"
|
[[ ! -e $test_home/.local/bin/$command ]] || fail "Remove Preinstalls deletes the $command lazy stub"
|
||||||
done
|
done
|
||||||
pass "Remove Preinstalls deletes every optional agent lazy stub"
|
pass "Remove Preinstalls deletes every optional agent lazy stub"
|
||||||
@@ -193,6 +232,13 @@ omarchy-remove-preinstalls >/dev/null
|
|||||||
[[ -L $test_home/.local/bin/cursor-agent ]] || fail "Remove Preinstalls keeps an official Cursor CLI install"
|
[[ -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"
|
rm -f "$test_home/.local/bin/cursor-agent" "$test_home/.local/bin/cursor-agent.official"
|
||||||
pass "Remove Preinstalls keeps an official Cursor CLI install"
|
pass "Remove Preinstalls keeps an official Cursor CLI install"
|
||||||
|
printf '#!/bin/bash\necho user-muse\n' >"$test_home/.local/bin/muse"
|
||||||
|
chmod +x "$test_home/.local/bin/muse"
|
||||||
|
omarchy-remove-preinstalls >/dev/null
|
||||||
|
[[ $("$test_home/.local/bin/muse") == "user-muse" ]] || fail "Remove Preinstalls deletes a user-managed Muse"
|
||||||
|
rm "$test_home/.local/bin/muse"
|
||||||
|
pass "Remove Preinstalls keeps a user-managed Muse install"
|
||||||
|
|
||||||
|
|
||||||
[[ -z $(omarchy-default-agent) ]] || fail "default agent is unset until one is chosen"
|
[[ -z $(omarchy-default-agent) ]] || fail "default agent is unset until one is chosen"
|
||||||
pass "default agent is unset until one is chosen"
|
pass "default agent is unset until one is chosen"
|
||||||
@@ -251,6 +297,9 @@ declare -A expected_agents=(
|
|||||||
[github-copilot]="copilot"
|
[github-copilot]="copilot"
|
||||||
[cursor]="cursor-agent"
|
[cursor]="cursor-agent"
|
||||||
[cursor-agent]="cursor-agent"
|
[cursor-agent]="cursor-agent"
|
||||||
|
[muse]="muse"
|
||||||
|
[muse-code]="muse"
|
||||||
|
[musecode]="muse"
|
||||||
)
|
)
|
||||||
|
|
||||||
declare -A expected_packages=(
|
declare -A expected_packages=(
|
||||||
@@ -264,6 +313,7 @@ declare -A expected_packages=(
|
|||||||
[gemini]="gemini"
|
[gemini]="gemini"
|
||||||
[copilot]="copilot"
|
[copilot]="copilot"
|
||||||
[cursor-agent]="$cursor_agent_package"
|
[cursor-agent]="$cursor_agent_package"
|
||||||
|
[muse]="$muse_package"
|
||||||
)
|
)
|
||||||
|
|
||||||
for selection in "${!expected_agents[@]}"; do
|
for selection in "${!expected_agents[@]}"; do
|
||||||
@@ -273,8 +323,12 @@ for selection in "${!expected_agents[@]}"; do
|
|||||||
[[ $(omarchy-default-agent) == $expected ]] || fail "default agent canonicalizes $selection"
|
[[ $(omarchy-default-agent) == $expected ]] || fail "default agent canonicalizes $selection"
|
||||||
|
|
||||||
mapfile -d '' -t mise_args <"$mise_log"
|
mapfile -d '' -t mise_args <"$mise_log"
|
||||||
[[ ${mise_args[0]} == "use" && ${mise_args[1]} == "-g" && ${mise_args[2]} == ${expected_packages[$expected]} ]] ||
|
[[ ${mise_args[0]} == "use" && ${mise_args[1]} == "-g" ]] ||
|
||||||
fail "default agent installs $selection globally through mise"
|
fail "default agent installs $selection globally through mise"
|
||||||
|
case ${mise_args[2]} in
|
||||||
|
"${expected_packages[$expected]}") ;;
|
||||||
|
*) fail "default agent preserves $selection backend options" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
mapfile -d '' -t agent_open_args <"$agent_open_log"
|
mapfile -d '' -t agent_open_args <"$agent_open_log"
|
||||||
[[ ${#agent_open_args[@]} == 1 && ${agent_open_args[0]} == "omarchy-agent" ]] ||
|
[[ ${#agent_open_args[@]} == 1 && ${agent_open_args[0]} == "omarchy-agent" ]] ||
|
||||||
@@ -387,6 +441,76 @@ 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"
|
[[ ! -s $agent_open_log ]] || fail "failed activation does not open an agent"
|
||||||
pass "default agent reports mise failures without notifications"
|
pass "default agent reports mise failures without notifications"
|
||||||
|
|
||||||
|
# Muse follows the shared mise installation and launch path.
|
||||||
|
: >"$notification_history"
|
||||||
|
: >"$agent_open_log"
|
||||||
|
: >"$terminal_log"
|
||||||
|
omarchy-default-agent muse
|
||||||
|
mapfile -d '' -t terminal_args <"$terminal_log"
|
||||||
|
[[ ${terminal_args[0]} == "omarchy-default-agent" && ${terminal_args[1]} == "--install" && ${terminal_args[2]} == "muse" ]] ||
|
||||||
|
fail "missing Muse installation opens in a terminal"
|
||||||
|
[[ ! -s $notification_history ]] || fail "missing Muse installation skips notifications"
|
||||||
|
[[ ! -s $agent_open_log ]] || fail "missing Muse installation waits to open the agent"
|
||||||
|
[[ $(omarchy-default-agent) == "copilot" ]] || fail "missing Muse installation waits to change the selection"
|
||||||
|
|
||||||
|
if OMARCHY_TEST_MISE_FAIL=true omarchy-default-agent --install muse >"$test_tmp/muse-install-failure-output" 2>&1; then
|
||||||
|
fail "missing Muse rejects a failed mise installation"
|
||||||
|
fi
|
||||||
|
[[ $(omarchy-default-agent) == "copilot" ]] || fail "failed Muse installation preserves the current default"
|
||||||
|
[[ ! -s $muse_login_log && ! -s $agent_open_log ]] || fail "failed Muse installation skips login and launch"
|
||||||
|
grep -F "Could not install Muse Code with mise" "$test_tmp/muse-install-failure-output" >/dev/null ||
|
||||||
|
fail "failed Muse installation identifies mise"
|
||||||
|
pass "failed Muse mise installation preserves the selection and skips login"
|
||||||
|
|
||||||
|
: >"$mise_history"
|
||||||
|
: >"$stub_log"
|
||||||
|
omarchy-default-agent --install muse >"$test_tmp/muse-install-output"
|
||||||
|
grep -Fx "use -g $muse_package" "$mise_history" >/dev/null || fail "visible Muse installation uses the HTTP backend"
|
||||||
|
[[ ! -s $stub_log ]] || fail "Muse selection recreates its preinstalled wrapper"
|
||||||
|
[[ ! -s $muse_login_log ]] || fail "Muse selection runs a separate login flow"
|
||||||
|
[[ $(omarchy-default-agent) == "muse" ]] || fail "visible Muse installation changes the selection"
|
||||||
|
mapfile -d '' -t agent_open_args <"$agent_open_log"
|
||||||
|
[[ ${#agent_open_args[@]} == 2 && ${agent_open_args[0]} == "omarchy-agent" && ${agent_open_args[1]} == "--inline" ]] ||
|
||||||
|
fail "newly installed Muse opens in the installation terminal"
|
||||||
|
pass "Muse installs visibly through mise and opens directly"
|
||||||
|
|
||||||
|
: >"$terminal_log"
|
||||||
|
: >"$muse_login_log"
|
||||||
|
: >"$agent_open_log"
|
||||||
|
OMARCHY_TEST_AGENT_INSTALLED=true omarchy-default-agent muse-code
|
||||||
|
[[ ! -s $terminal_log ]] || fail "installed Muse selection skips the terminal"
|
||||||
|
[[ ! -s $muse_login_log ]] || fail "installed Muse selection skips the login"
|
||||||
|
[[ $(omarchy-default-agent) == "muse" ]] || fail "default agent canonicalizes muse-code"
|
||||||
|
mapfile -d '' -t agent_open_args <"$agent_open_log"
|
||||||
|
[[ ${#agent_open_args[@]} == 1 && ${agent_open_args[0]} == "omarchy-agent" ]] ||
|
||||||
|
fail "installed Muse opens in a new terminal after selection"
|
||||||
|
pass "installed Muse selects and opens directly"
|
||||||
|
|
||||||
|
OMARCHY_TEST_AGENT_INSTALLED=true omarchy-default-agent pi
|
||||||
|
: >"$agent_open_log"
|
||||||
|
if OMARCHY_TEST_AGENT_INSTALLED=true OMARCHY_TEST_MISE_FAIL=true omarchy-default-agent musecode >"$test_tmp/muse-failure-output" 2>&1; then
|
||||||
|
fail "default agent rejects a failed Muse activation"
|
||||||
|
fi
|
||||||
|
[[ $(omarchy-default-agent) == "pi" ]] || fail "failed Muse activation preserves the current default agent"
|
||||||
|
grep -F "Could not set Muse Code as the default coding agent" "$test_tmp/muse-failure-output" >/dev/null ||
|
||||||
|
fail "default agent reports a failed Muse activation"
|
||||||
|
[[ ! -s $agent_open_log ]] || fail "failed Muse activation does not open an agent"
|
||||||
|
pass "default agent reports Muse mise failures without changing the selection"
|
||||||
|
|
||||||
|
# A manually installed launcher belongs to the user; selecting it must not
|
||||||
|
# install a second copy or replace it with the Omarchy wrapper.
|
||||||
|
printf '#!/bin/bash\necho user-muse\n' >"$test_home/.local/bin/muse"
|
||||||
|
chmod +x "$test_home/.local/bin/muse"
|
||||||
|
: >"$mise_history"
|
||||||
|
: >"$stub_log"
|
||||||
|
: >"$terminal_log"
|
||||||
|
omarchy-default-agent muse
|
||||||
|
[[ $(omarchy-default-agent) == "muse" ]] || fail "a user-installed Muse can be selected"
|
||||||
|
[[ ! -s $mise_history && ! -s $stub_log && ! -s $terminal_log ]] || fail "a user-installed Muse skips installation and wrapper creation"
|
||||||
|
[[ $("$test_home/.local/bin/muse") == "user-muse" ]] || fail "a user-installed Muse is preserved"
|
||||||
|
rm "$test_home/.local/bin/muse"
|
||||||
|
pass "selecting a user-installed Muse preserves its launcher"
|
||||||
|
|
||||||
rm "$mock_bin/omarchy-agent"
|
rm "$mock_bin/omarchy-agent"
|
||||||
hash -r
|
hash -r
|
||||||
|
|
||||||
@@ -434,6 +558,7 @@ assert_launch omp omp --auto-approve -- "Review this project"
|
|||||||
assert_launch opencode opencode --auto --prompt "Review this project"
|
assert_launch opencode opencode --auto --prompt "Review this project"
|
||||||
assert_launch claude claude --permission-mode auto -- "Review this project"
|
assert_launch claude claude --permission-mode auto -- "Review this project"
|
||||||
assert_launch codex codex --approve-for-me -- "Review this project"
|
assert_launch codex codex --approve-for-me -- "Review this project"
|
||||||
|
assert_launch muse muse --approval-mode never -- "Review this project"
|
||||||
assert_launch crush crush run "Review this project"
|
assert_launch crush crush run "Review this project"
|
||||||
assert_launch grok grok --permission-mode bypassPermissions -- "Review this project"
|
assert_launch grok grok --permission-mode bypassPermissions -- "Review this project"
|
||||||
assert_launch gemini gemini --yolo --prompt-interactive "Review this project"
|
assert_launch gemini gemini --yolo --prompt-interactive "Review this project"
|
||||||
@@ -442,6 +567,12 @@ assert_launch hermes env -u HERMES_SESSION_SOURCE hermes chat --yolo --tui "--qu
|
|||||||
assert_launch copilot copilot --allow-all --interactive "Review this project"
|
assert_launch copilot copilot --allow-all --interactive "Review this project"
|
||||||
pass "agent launcher adapts initial prompts for every supported agent"
|
pass "agent launcher adapts initial prompts for every supported agent"
|
||||||
|
|
||||||
|
literal_muse_prompt=$'--disable-sandbox !Crash {$(touch must-not-run)}\ntrailing\\ '
|
||||||
|
printf '%s\n' "muse" >"$agent_file"
|
||||||
|
omarchy-agent-prompt "$literal_muse_prompt"
|
||||||
|
assert_launched muse "separates prompt text from options" muse --approval-mode never -- "$literal_muse_prompt"
|
||||||
|
pass "Muse receives option-like prompts as one literal argument"
|
||||||
|
|
||||||
literal_hermes_prompt=$' --help !Crash /quit {$(touch must-not-run)}\ntrailing\\ '
|
literal_hermes_prompt=$' --help !Crash /quit {$(touch must-not-run)}\ntrailing\\ '
|
||||||
printf '%s\n' "hermes" >"$agent_file"
|
printf '%s\n' "hermes" >"$agent_file"
|
||||||
omarchy-agent-prompt "$literal_hermes_prompt"
|
omarchy-agent-prompt "$literal_hermes_prompt"
|
||||||
@@ -454,6 +585,7 @@ assert_bypass omp omp --auto-approve
|
|||||||
assert_bypass opencode opencode --auto
|
assert_bypass opencode opencode --auto
|
||||||
assert_bypass claude claude --permission-mode auto
|
assert_bypass claude claude --permission-mode auto
|
||||||
assert_bypass codex codex --approve-for-me
|
assert_bypass codex codex --approve-for-me
|
||||||
|
assert_bypass muse muse --approval-mode never
|
||||||
assert_bypass crush crush --yolo
|
assert_bypass crush crush --yolo
|
||||||
assert_bypass grok grok --permission-mode bypassPermissions
|
assert_bypass grok grok --permission-mode bypassPermissions
|
||||||
assert_bypass gemini gemini --yolo
|
assert_bypass gemini gemini --yolo
|
||||||
|
|||||||
@@ -207,7 +207,9 @@ const expectedAgents = {
|
|||||||
openclaw: { icon: '\ue90c', iconFont: 'omarchy', label: 'OpenClaw' },
|
openclaw: { icon: '\ue90c', iconFont: 'omarchy', label: 'OpenClaw' },
|
||||||
copilot: { icon: '', label: 'Copilot' },
|
copilot: { icon: '', label: 'Copilot' },
|
||||||
crush: { icon: '', label: 'Crush' },
|
crush: { icon: '', label: 'Crush' },
|
||||||
|
muse: { icon: '', label: 'Muse Code' },
|
||||||
'cursor-agent': { icon: '\ue90d', iconFont: 'omarchy', label: 'Cursor CLI' },
|
'cursor-agent': { icon: '\ue90d', iconFont: 'omarchy', label: 'Cursor CLI' },
|
||||||
|
|
||||||
}
|
}
|
||||||
assert(
|
assert(
|
||||||
Object.entries(expectedAgents).every(([agent, expected]) => {
|
Object.entries(expectedAgents).every(([agent, expected]) => {
|
||||||
@@ -220,13 +222,13 @@ assert(
|
|||||||
&& !entry.when
|
&& !entry.when
|
||||||
&& entry.checked.includes(`== \"${agent}\"`)
|
&& entry.checked.includes(`== \"${agent}\"`)
|
||||||
}),
|
}),
|
||||||
'menu exposes every mise-installable coding agent with its own glyph under Defaults > Agent'
|
'menu exposes every supported coding agent with its own glyph under Defaults > Agent'
|
||||||
)
|
)
|
||||||
assertDeepEqual(
|
assertDeepEqual(
|
||||||
defaultItems
|
defaultItems
|
||||||
.filter(item => item.parent === 'setup.default.agent')
|
.filter(item => item.parent === 'setup.default.agent')
|
||||||
.map(item => item.label),
|
.map(item => item.label),
|
||||||
['Claude', 'Codex', 'Copilot', 'Crush', 'Cursor CLI', 'Gemini', 'Grok', 'Hermes', 'omp', 'OpenClaw', 'OpenCode', 'Pi'],
|
['Claude', 'Codex', 'Copilot', 'Crush', 'Cursor CLI', 'Gemini', 'Grok', 'Hermes', 'Muse Code', 'omp', 'OpenClaw', 'OpenCode', 'Pi'],
|
||||||
'menu sorts coding agents alphabetically'
|
'menu sorts coding agents alphabetically'
|
||||||
)
|
)
|
||||||
assert(!defaultById['install.ai.crush'], 'menu removes Crush from Install > AI')
|
assert(!defaultById['install.ai.crush'], 'menu removes Crush from Install > AI')
|
||||||
|
|||||||
@@ -24,7 +24,15 @@ for (const [id, [pkg, glyph]] of Object.entries(selected)) {
|
|||||||
assert(fs.existsSync(path.join(root, `bin/omarchy-remove-ai-${id}`)), `${id} remover exists`)
|
assert(fs.existsSync(path.join(root, `bin/omarchy-remove-ai-${id}`)), `${id} remover exists`)
|
||||||
}
|
}
|
||||||
assertDeepEqual(Object.keys(rows).filter(k => k.startsWith('remove.ai.')).sort(), Object.keys(selected).map(k => `remove.ai.${k}`).sort(), 'removal prerequisite imports no unselected apps')
|
assertDeepEqual(Object.keys(rows).filter(k => k.startsWith('remove.ai.')).sort(), Object.keys(selected).map(k => `remove.ai.${k}`).sort(), 'removal prerequisite imports no unselected apps')
|
||||||
assertDeepEqual(Object.keys(rows).filter(k => k.startsWith('setup.default.agent.')).map(k => k.split('.').pop()).sort(), ['claude', 'codex', 'copilot', 'crush', 'cursor-agent', 'gemini', 'grok', 'hermes', 'omp', 'openclaw', 'opencode', 'pi'], 'baseline agent choices survive with only selected release agents added')
|
assertDeepEqual(Object.keys(rows).filter(k => k.startsWith('setup.default.agent.')).map(k => k.split('.').pop()).sort(), ['claude', 'codex', 'copilot', 'crush', 'cursor-agent', 'gemini', 'grok', 'hermes', 'muse', 'omp', 'openclaw', 'opencode', 'pi'], 'baseline agent choices survive with only selected release agents added')
|
||||||
|
for (const id of ['setup.default.agent.cursor-agent', 'setup.default.editor.cursor', 'install.editor.cursor']) {
|
||||||
|
assertEqual(rows[id].icon, '\ue90d', `${id} uses the upstream Cursor glyph`)
|
||||||
|
assertEqual(rows[id].iconFont, 'omarchy', `${id} uses the packaged icon font`)
|
||||||
|
}
|
||||||
|
assertEqual(rows['setup.default.editor.cursor'].when, 'omarchy-cmd-present cursor', 'Cursor editor retains baseline default visibility')
|
||||||
|
assertEqual(rows['install.editor.cursor'].when, '! omarchy-pkg-present cursor-bin', 'Cursor editor retains baseline install visibility')
|
||||||
|
assertEqual(rows['setup.default.agent.muse'].icon, '', 'Muse uses the Nerd infinity glyph')
|
||||||
|
assert(!rows['setup.default.agent.muse'].iconFont, 'Muse needs no Omarchy font addition')
|
||||||
assert(!fs.existsSync(path.join(root, 'bin/omarchy-theme-set-openclaw')), 'deferred OpenClaw theming is absent')
|
assert(!fs.existsSync(path.join(root, 'bin/omarchy-theme-set-openclaw')), 'deferred OpenClaw theming is absent')
|
||||||
JS
|
JS
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user