Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 

Repository files navigation

Muse Code — Custom Provider & No Meta Login

Use Muse Code (muse) with any OpenAI-compatible API without creating a Meta account or using muse login.

Muse Code's meta provider defaults to https://api.meta.ai/v1, but you can point it at your own gateway. The meta label is just a provider name — storing a key with muse auth set --provider meta does not require a Meta OAuth login. muse login is optional and only for Meta's hosted auth; API-key auth is enough.

⚠️ Muse Code 1.0.1 changed things. The old per-invocation --base-url flag no longer sends your auth header (the bearer is "withheld" unless the base URL is pinned in settings). If you're on 1.0.1+, use the endpoint_transport settings method below. The old --base-url wrapper only works on 0.2.x — see the legacy section.

Why

  • Route Muse Spark (muse-spark-1.2, etc.) through a gateway/proxy (e.g., self-hosted, OpenCode, Helicone, Cloudflare AI Gateway, LiteLLM)
  • Avoid muse login / browser OAuth entirely
  • Keep the same CLI (muse exec, muse TUI) while swapping the backend

Quick start (no Meta account)

1. Install Muse Code

curl -fsSL https://dev.meta.ai/install.sh | sh
muse --version  # Muse Code 1.0.1 (or newer)

2. Store an API key (no browser)

This does NOT create a Meta account. It just saves a key under the meta provider name.

# paste your gateway/proxy API key on stdin (never as an argv)
echo -n "YOUR_GATEWAY_API_KEY" | muse auth set --provider meta --api-key-stdin

# verify
cat ~/.config/muse/auth.json  # { "schema_version": 1, "providers": { "meta": { "api_key": "..." } } }

# alternative: env var (takes priority over file)
export META_API_KEY="YOUR_GATEWAY_API_KEY"

You never need to run muse login.

3. Pin your gateway in settings (1.0.1+)

Muse Code 1.0.1 hardens endpoint overrides: a bare --base-url flag is treated as "off the sanctioned front door" and your Authorization header will not be sent to it. The sanctioned opt-in is a settings pin — edit ~/.config/muse/settings.json:

{
  "schema_version": 1,
  "model": "muse-spark-1.2",
  "provider": "meta",
  "endpoint_transport": {
    "base_url": "http://127.0.0.1:8914/v1",
    "auth": "bearer"
  }
}
  • base_url — your gateway / proxy root (same value you used to pass to --base-url)
  • auth: "bearer" — required. This pin is what makes Muse attach your stored API key to requests against that base URL. Without it the key is withheld.

That's it — no wrapper needed. Every command (muse, muse exec, subagents, workflows) now goes through your gateway:

muse exec "say hi in 5 words"
muse --image ./photo.jpg exec "describe this image"

Verify it's actually hitting your gateway:

muse exec "Reply with exactly: GATEWAY_OK"
# and/or watch requests land in your proxy log

If you see an auth error mentioning "Meta bearer withheld: base_url is off the sanctioned front door", the settings pin is missing or malformed — re-check endpoint_transport.auth is exactly "bearer".

Multiple gateways? Swap config dirs with XDG_CONFIG_HOME

Muse Code honors XDG_CONFIG_HOME / XDG_DATA_HOME. Keep one settings dir per gateway and switch by env:

# ~/.config-muse-a/muse/settings.json  -> gateway A
# ~/.config-muse-b/muse/settings.json  -> gateway B
XDG_CONFIG_HOME=~/.config-muse-a muse exec "hi via gateway A"
XDG_CONFIG_HOME=~/.config-muse-b muse exec "hi via gateway B"

4. Keep the proxy alive (macOS)

If your custom provider is a local proxy (e.g., translating APIs), run it as a LaunchAgent:

<!-- ~/Library/LaunchAgents/com.muse-proxy.plist -->
<dict>
  <key>Label</key><string>com.muse-proxy</string>
  <key>ProgramArguments</key><array><string>/usr/bin/python3</string><string>/Users/you/.local/bin/my-muse-proxy.py</string></array>
  <key>RunAtLoad</key><true/>
  <key>KeepAlive</key><true/>
</dict>
launchctl load ~/Library/LaunchAgents/com.muse-proxy.plist
curl -s http://127.0.0.1:8914/v1/models | head

5. Minimal proxy example (Python)

Forward Muse's POST /v1/responses to your gateway, with optional fallback to /v1/chat/completions for gateways that don't speak the Responses API. Rewrite model names if needed. See examples/proxy.py — run it with:

GATEWAY_BASE_URL="https://your-gateway.example.com/v1" \
GATEWAY_API_KEY="YOUR_GATEWAY_API_KEY" \
python3 examples/proxy.py

Env vars: GATEWAY_BASE_URL (upstream), GATEWAY_API_KEY (bearer key), PROXY_PORT (default 8914), PROXY_UPSTREAM_PATH (default /responses; set /chat/completions for chat-style gateways). PROXY_USER_AGENT (default Muse/1.0.1 — some CDNs like Cloudflare in front of opencode.ai block python-urllib's default UA with error 1010, so the proxy mimics the Muse client).

Legacy (0.2.x) wrapper — --base-url

Deprecated since 1.0.1 — kept for completeness. On 1.0.1+ this wiring still connects, but Muse withholds your auth header (401 from your gateway). Use the settings method instead.

BIN="$HOME/.local/bin/muse-bin-0.2.1-R1215.1"  # or wherever `muse` is installed
BASE="https://your-gateway.example.com/v1"

cat > ~/.local/bin/muse-wrapper << SH
#!/bin/bash
BIN="$BIN"
BASE="$BASE"
case "\$1" in
  exec|resume|config|export|trace|skills|sandbox|session-message|auth|login|logout|init)
    exec "\$BIN" "\$1" --base-url "\$BASE" "\${@:2}"
    ;;
  *)
    exec "\$BIN" --base-url "\$BASE" "\$@"
    ;;
esac
SH
chmod +x ~/.local/bin/muse-wrapper
ln -sf ~/.local/bin/muse-wrapper ~/.local/bin/muse

Note on exec ordering: muse exec expects options after exec (muse exec --base-url ...), not before. The wrapper above handles this.

Subagents / delegation through a gateway

If you use Muse's native subagents (subagent_spawn etc.) with a custom gateway, two things must be set or the tools stay hidden:

  1. Enable delegation in ~/.config/muse/settings.json:
    "run": { "subagent_delegation_mode": "auto" }
  2. Run inside a trusted workspacegit init your project and either trust it when prompted, or pass --trust-workspace to muse exec. Untrusted workspaces hide the delegation tools entirely.

Both settings coexist fine with endpoint_transport.

OpenCode equivalent

OpenCode also supports custom OpenAI-compatible providers via opencode.json:

{
  "$schema": "https://opencode.ai/config.json",
  "model": "my-gateway/muse-spark-1.2",
  "provider": {
    "my-gateway": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "My Gateway",
      "options": { "baseURL": "https://your-gateway.example.com/v1" },
      "models": {
        "muse-spark-1.2": { "name": "Muse Spark 1.2", "limit": { "context": 1048576, "output": 131072 } }
      }
    }
  }
}
opencode run -m my-gateway/muse-spark-1.2 "fix tests"

FAQ

Do I need a Meta account? No. muse auth set + the settings pin is enough. muse login is only for Meta-hosted OAuth.

Does provider: meta mean I'm calling Meta directly? No — it's just the provider key. With endpoint_transport.base_url it calls your gateway instead. Your Authorization: Bearer ... header is your gateway key.

I get "Meta bearer withheld: base_url is off the sanctioned front door." You passed --base-url (or set the base URL somewhere) without the settings pin. Add endpoint_transport with "auth": "bearer" to ~/.config/muse/settings.json — see step 3.

What about images/PDFs? muse-spark-1.2 supports image, pdf, video as input modalities (1M context). Pass --image (repeatable) to muse exec.

Can I use this with OpenCode Go / other gateways? Yes — any OpenAI-compatible /v1/responses endpoint works as GATEWAY_BASE_URL. For /v1/chat/completions-only gateways, set PROXY_UPSTREAM_PATH=/chat/completions in the proxy example.

My gateway only speaks chat completions, not responses. Run the proxy example locally and set PROXY_UPSTREAM_PATH=/chat/completions; Muse talks Responses to the proxy, the proxy forwards chat-style.

My gateway is behind Cloudflare and returns error 1010 / browser_signature_banned. The proxy mimics the Muse client's User-Agent by default (PROXY_USER_AGENT, default Muse/1.0.1) because Cloudflare blocks python-urllib's default signature. If your gateway blocks that too, set PROXY_USER_AGENT to whatever your CDN allowlists.

Security

  • Never paste API keys as CLI args (they appear in ps). Use --api-key-stdin or env vars.
  • Don't commit ~/.config/muse/auth.json or opencode auth files.
  • Gateways should use Bearer tokens over HTTPS only.

MIT — PRs welcome. Not affiliated with Meta.

About

Use Muse Code with any OpenAI-compatible gateway without Meta login (custom --base-url provider, proxy + OpenCode examples)

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors