Use your existing Muse Code subscription in Zed, JetBrains IDEs, and any other ACP client.
muse-acp is a bridge between editors that speak the
Agent Client Protocol (ACP) and
Muse Code. It talks to Muse over its
native Muse Session Protocol
(MSP), so your subscription keeps Muse's own session engine, tools,
authentication, and approval flow.
The adapter is one small Rust binary with no runtime dependencies. It supports ACP v1 and v2, and installs on macOS, Linux, and Windows.
muse-acpis an independent community project. Muse Code and Muse Spark are products of Meta Platforms, Inc. This project is not affiliated with, endorsed by, or supported by Meta.
- Muse Code installed, authenticated, and available as
museonPATH. - A stdio ACP client: Zed, a JetBrains IDE with AI Assistant, or another ACP client such as micro-acp.
- Node.js 22+ if you install from npm.
- Rust 1.88+ if you build from source.
Install Muse and log in before installing the adapter:
curl -fsSL https://dev.meta.ai/install.sh | sh
muse loginOn macOS you can also use Homebrew:
brew install --cask muse-codeConfirm muse --version works, then continue.
With Node.js 22 or later, install from npm:
npm install -g @brokkai/muse-acp
muse-acp --selftestOr run it without a global install:
npx --yes @brokkai/muse-acp --selftestThe npm package bundles the native binaries for every supported platform, so it needs no install scripts or separate downloads.
On Linux and macOS you can install the latest release instead:
curl --proto '=https' --tlsv1.2 -LsSf \
https://github.com/BrokkAi/muse-acp/releases/latest/download/install.sh | shThe installer detects your platform, verifies the archive's SHA-256 checksum,
and installs muse-acp to ~/.local/bin. Pin a version or choose another
absolute destination with environment variables on sh:
curl --proto '=https' --tlsv1.2 -LsSf \
https://github.com/BrokkAi/muse-acp/releases/latest/download/install.sh \
| MUSE_ACP_INSTALL_DIR="$HOME/bin" MUSE_ACP_VERSION=vX.Y.Z shOn Windows x86_64, run the PowerShell installer for the MSVC release:
irm https://github.com/BrokkAi/muse-acp/releases/latest/download/install.ps1 | iexIt verifies the ZIP's SHA-256 checksum and installs muse-acp.exe to
$env:LOCALAPPDATA\Programs\muse-acp, leaving PATH untouched. Set
MUSE_ACP_VERSION or MUSE_ACP_INSTALL_DIR to pin a version or choose another
absolute directory, then add the reported directory to your user PATH.
From a checkout, build and install with Cargo:
cargo install --path .muse-acp install # Zed
muse-acp install-intellij # IntelliJ IDEA and other JetBrains IDEsBoth commands are safe to re-run: they preserve existing agent entries, write a
.bak backup, and replace the settings file atomically. Use --dry-run to
preview an edit.
Any other ACP client can launch muse-acp directly over stdio.
muse-acp install registers the adapter in Zed's settings file,
~/.config/zed/settings.json (%APPDATA%\Zed\settings.json on Windows):
{
"agent_servers": {
"muse-acp": {
"type": "custom",
"command": "muse-acp",
"args": [],
"env": {}
}
}
}On Windows it records the full path to the running muse-acp.exe instead,
because the PowerShell installer leaves PATH untouched.
muse-acp install-intellij writes ~/.jetbrains/acp.json, recording the full
path to the running binary as JetBrains requires:
{
"agent_servers": {
"muse-acp": {
"command": "/Users/you/.local/bin/muse-acp",
"args": [],
"env": {}
}
}
}Then open AI Chat and select muse-acp.
install and install-intellij accept:
muse-acp install --command /absolute/path/to/muse-acp
muse-acp install --env MUSE_CLI=/absolute/path/to/muse
muse-acp install --settings /path/to/settings.json --dry-run
muse-acp uninstall
muse-acp uninstall-intellijRun muse-acp help for the full option list.
The adapter reads its settings from the environment. Export them in your shell, or set them in the client's agent entry so the editor passes them to the adapter.
| Variable | Default | Purpose |
|---|---|---|
MUSE_CLI |
muse |
Muse host binary to launch. Use an absolute path when the editor's PATH differs from your shell's. On Windows the default also finds the muse.cmd launcher that the Muse installer puts on PATH. |
MUSE_SERVE_ARGS |
none | Extra host-lifetime flags for muse serve (see muse serve --help). Split on whitespace; no shell quoting or expansion. |
MUSE_APPROVAL_MODE |
host default | Force an approval posture: allowAll, promptUnmatched, onRequest, or denyUnmatched. promptUnmatched sends every unmatched tool call through session/request_permission. |
MUSE_COMMAND_TIMEOUT_MS |
method-specific | Override the host admission-ack deadline, in milliseconds. |
MUSE_SHUTDOWN_TIMEOUT_MS |
8000 |
Shutdown deadline, 100–60000 ms. |
MUSE_TOOL_OUTPUT_LIMIT |
8000 |
Editor-facing tool output bound, in characters (minimum 200). |
MUSE_LOG |
normal |
Set to debug for per-method protocol tracing (no payloads). |
MUSE_ALLOW_UNSCOPED_READS |
off | Dangerous. Set to 1, true, yes, or on to allow local reads outside the approved workspace roots. |
Without MUSE_COMMAND_TIMEOUT_MS, admission deadlines are 30 seconds for the
handshake, queries, and approval or input decisions; 180 seconds for session
start, resume, and read and for view paging; and 60 seconds for other methods.
These bound how long the adapter waits for a command response, not how long a
model turn may run.
If Muse is saved with the :auto-review permission profile, muse serve
cannot start its automated reviewer. The adapter gives its own muse serve
child a private, temporary settings view that uses :ask-me, so approvals come
to your editor. Your saved Muse settings, editor launcher, and session data are
left untouched, and the temporary view is removed when the host exits. This
requires symbolic-link support (on Windows, Developer Mode or equivalent).
Other permission profiles are passed through unchanged.
- Sessions — new, load, resume, list, close, and fork, with durable Muse session IDs that survive adapter and host restarts.
- Turns — streamed text and tool updates, queued concurrent prompts,
cancellation with a terminal event, and exact-turn steering over the ACP v2
_session/steeringextension. - Approvals — Muse approval requests surfaced as
session/request_permission, with a deny-safe fallback. - Questions — Muse
userInput/requestedbridged to ACPelicitation/createforms when the client advertises form support; otherwise the host falls back to auto-cancel. - Configuration — model, approval mode, and reasoning effort exposed as ACP
configOptionsselectors, refreshed from Muse on create, load, resume, and config change. The reasoning selector starts atMuse defaultand sends no override until you pick a tier. - Skills — Muse's skill catalog drives ACP
available_commands_update. Slash prompts such as/planuse native skill turn parts;/compactinvokes Muse's native compaction. - Goals —
/goal <objective>sets the session goal,/goal edit <objective>replaces it, and/goal pause,/goal resume,/goal clearmanage it, mapping onto the hostgoal/*methods. When a command starts a goal turn, the prompt stays open until that turn ends, and Stop interrupts it (Muse then pauses the goal). Stop also reaches goal turns Muse starts on its own. Objectives may include @-mentions. Goal state still streams back throughsession/goalChangeddisplay metadata. - Session names —
/rename <name>renames the session through the host'ssession/rename; the new title arrives throughsession/nameChangedas an ACPsession_info_update. - Workflow children — workflow cards list each child with its id, and
/workflow-child skip <childId>or/workflow-child retry <childId>controls one child of a running workflow through the host'sworkflow/childControl. A bare/workflow-childlists the children you can control. - Content — text, inline and local-file images,
resource_linktext expansion, and embedded context. Audio is rejected, because Muse's input type is closed totextandimage. - Usage — context occupancy as
usage_update, cumulative session totals, subscription observations under_meta.museSubscriptionUsage, and a client-local list-price cost estimate explicitly labeled as not a billing figure. - Tasks and subagents — backgrounded shell commands, workflows, and native subagents surfaced through negotiated ACP extensions where the client advertises support, with synthesized tool cards otherwise.
- File changes — per-turn workspace file-change reports from the host's native file tools when the client negotiates the AIR extension.
- Stored output — bounded tool output with head and tail retained, plus
opt-in
_session/readOutputaccess to the host's stored bytes.
Beyond core ACP, the adapter negotiates these extensions. Each activates only when the client opts in too, with the documented fallback otherwise:
_session/steering(ACP v2 only) — exact-turn steering; rejected with-32601on v1. Follows the ecosystem_session/steeringconvention (steering.supported); the standards-tracksession/injectproposal is still unmerged — adopting it is future work._session/readOutput— opt-in reads of host-stored tool output._session/userShell— shell commands outside any turn; needs editor opt-in, AIRasyncTasks, and a host grant all together._session/async_task/stop— stop one background task;session/cancelmaps background work totask/stopAll.- JetBrains AIR v1 (
agentFileChangeReport,nativeSubagentSessions,asyncTasks,recommendedValue) — per-turn file-change reports, native subagent sessions, async-task observation and stops, model and reasoning recommendations.
The MSP event compatibility matrix records the ACP mapping or intentional disposition of every notification in the pinned schema. ROADMAP.md tracks compatibility, reliability, and release priorities.
The adapter does not forward MCP servers that an ACP client attaches to a
session, including the stdio server JetBrains may pass. It advertises HTTP and
SSE MCP support as false and logs the omission (ignoring client-provided MCP servers) so the missing tools are diagnosable. Configure MCP servers in Muse
itself instead. ACP client-owned MCP configuration remains a limitation of this
adapter, not of Muse's session-scoped MCP support.
Several independent projects bridge Muse Code to ACP. They broadly split into
two designs: adapters that speak Muse's native session protocol over a
long-lived muse serve, and bridges that wrap the one-shot muse exec --json
event stream. The table below reflects each project's public documentation and
package metadata as of September 2026; check the projects themselves for
current behavior.
| Adapter | Language / runtime | Muse transport | Install | Editor targets | License |
|---|---|---|---|---|---|
| muse-acp (this project) | Rust; single native binary, no runtime | MSP over one long-lived muse serve |
npm @brokkai/muse-acp, release installers, cargo install |
Zed, JetBrains, any stdio ACP client | Apache-2.0 |
| bex-co/muse-code-acp | TypeScript; Node.js 22+ | Muse SDK over muse serve |
npm @bex-co/muse-code-acp |
Zed, VS Code, other ACP clients | Apache-2.0 |
| sanjay3290/muse-acp | TypeScript; Node.js 20+ | MSP over muse serve |
npm muse-acp |
ACP clients (Zed example) | Apache-2.0 |
| julianubico/muse-code-acp-bridge | JavaScript; Node.js 22.13+ | muse exec --json JSONL |
from source (documented npm name not currently published) | acpx custom agents | MIT |
| einklover/muse-acp-server | TypeScript; Node.js 22+ | muse exec --json, with model traffic proxied through OpenCode credentials |
from source | Paseo | MIT |
| jannotix/muse-acp-agent | TypeScript | Uses Muse Code models as the reasoning core | from source | ACP clients | Apache-2.0 |
The headless muse exec --json design is a good fit for one-shot automation and
scripted workflows. This adapter chooses MSP so a single editor session keeps
native streaming, approvals, cancellation, configuration, resume, and usage,
instead of starting a new Muse CLI process for each prompt.
Adjacent projects worth knowing about, though not ACP adapters themselves: BrokkAi/mjolnir is a Rust control plane for several ACP coding agents including Muse, and agentic-control-plane/muse-code-acp-plugin is a Muse plugin that policy-checks tool calls.
One muse serve child serves all ACP sessions for the adapter's lifetime.
session/new starts a host session in the requested cwd; session/start
auto-subscribes the adapter to the session view so turns stream in as item/*
and turn/* notifications. The adapter folds those into ACP session/update
messages:
| Muse (MSP) | Editor (ACP) |
|---|---|
session/start, turns, and history |
session/new, session/prompt, session/load, session/resume, session/fork |
item/delta message text |
agent_message_chunk |
toolCall items |
tool_call and tool_call_update |
turn/completed |
v1 prompt response with stop reason and usage; v2 state_update |
approval/requested |
session/request_permission, answered with approval/decide |
userInput/requested |
elicitation/create form |
model/list, session/setModel, session/setApprovalMode, session/setReasoningEffort |
configOptions selectors and session/set_config_option |
skill/list, skill/changed |
available_commands_update |
session/contextUsage, session/tokenUsage |
usage_update |
turn/steer |
_session/steering (ACP v2) |
| Forks, subagents, async tasks, user shell, stored output | negotiated ACP extensions |
Muse's stable schema is the authority for MSP shapes (muse schema generate-json-schema). A schema fingerprint mismatch with the vendored bundle
is logged, not fatal.
ACP's cwd is the primary workspace root and the base for relative resource
paths; the adapter passes it to Muse as MSP's single workspaceRoot. If a
client sends additionalDirectories, each must be absolute, and the adapter
treats [cwd, ...additionalDirectories] as the ordered set of roots approved
for local image and textual resource_link expansion. MSP v1 has no
additional-root field, so extra roots do not widen Muse's own tool workspace or
sandbox policy.
Local reads are confined to that root set. The adapter resolves each path and
root through the filesystem before checking containment, so ..,
percent-encoded separators, case differences, and symlinks cannot escape the
approved roots. Only valid UTF-8 text without binary control bytes is expanded,
up to 256 KiB per resource; malformed file:// escapes and remote hosts are
rejected. Setting MUSE_ALLOW_UNSCOPED_READS disables this boundary and should
not be used with untrusted sessions.
When Muse has no credential, session/new and session/load fail with ACP's
-32000 authentication-required error, so editors such as Zed open their login
screen before the first prompt. The adapter learns this from Muse's
account/read, which reports only which kind of credential is in effect. That
method is experimental, so the adapter opts into Muse's experimental API. If
the check is unavailable, the first prompt reports the same error instead. A
credential that expires later also yields -32000 with login guidance.
Editors that support ACP terminal auth then offer the
adapter's muse-login method. It runs muse-acp login in a terminal, which
runs muse login with the executable selected by MUSE_CLI, so you can
approve the device code in your browser. You can also run either command
yourself, then restart the editor agent.
muse-acp login # or: npx --yes @brokkai/muse-acp loginMETA_API_KEY, when set in the agent's environment, takes priority over the
account login.
If muse serve cannot start at all (for example, Muse is not installed), the
adapter still completes the ACP handshake. Every later request then returns
the startup diagnostic, so the editor shows what to fix.
Run the login where the adapter runs, as the same OS user. For SSH,
containers, remote IDE backends, or a different OS account, a login on your
desktop does not help; log in on the remote host. The adapter never opens a
browser, never prompts for credentials over ACP stdio, and never copies
credentials between machines. Its only ACP auth method runs Muse's own login
in a terminal, and account/read never returns key material, so credentials
stay in the Muse environment.
Muse 1.0.2 may fail to start its sandbox on Linux arm64 when a required sandbox binary is missing. Prefer upgrading Muse or installing the sandbox support. Only if neither is possible, and only if you accept running host tools without the sandbox's isolation:
MUSE_SERVE_ARGS="--trust-workspace --disable-sandbox"--disable-sandbox materially reduces isolation, and neither approval prompts
nor this adapter's read confinement replace it. Sandbox posture is fixed for
the life of muse serve; re-enable it as soon as the host supports your
platform.
muse-acp --selftest # static payload + schema compatibility + CLI probe
muse-acp --support # redacted support bundle, safe to paste into a report--selftest validates the adapter's built-in payloads, prints the MSP schema
compatibility table, and reports whether the configured Muse CLI can be invoked
(cli-ready or cli-unready). It exits 0 even when Muse is not installed, so
you can collect output on a machine that is still being set up.
Set MUSE_LOG=debug for per-method protocol tracing. Tracing records method
names and outcomes, not payloads.
When the editor closes the ACP connection, the adapter starts a shutdown deadline, fails outstanding requests, and exits. If the deadline expires first, it records a diagnostic and exits nonzero.
| OS | Architecture | Notes |
|---|---|---|
| macOS | x86_64, arm64 | Supported |
| Linux | x86_64, arm64 | glibc; see the Linux arm64 sandbox advisory above |
| Windows | x86_64 | MSVC release |
Windows arm64, Linux musl, 32-bit systems, and other operating systems have no published release target.
Build and run from a checkout:
cargo build
./target/debug/muse-acp --selftestBefore submitting a change:
cargo fmt --check
cargo clippy --locked --all-targets -- -D warnings
cargo test --locked
cargo run --locked -- --selftest
node --test npm/test/launcher.test.cjs
python3 -m unittest discover -s scripts -p 'test_*.py'The integration tests use the checked-in fake MSP host at
tests/fixtures/fake_serve.py, so they do not require a live Muse session.
See CONTRIBUTING.md for the full development workflow and
RELEASING.md for the release process.
Report vulnerabilities privately as described in SECURITY.md, never in a public issue.
Copyright 2026 Brokk.ai. Licensed under the Apache License, Version 2.0. See LICENSE and NOTICE.