muse-shim is an unofficial local model-provider shim that lets Meta Muse Code use OpenAI-compatible Responses APIs (including OpenRouter), OpenAI Codex OAuth, and the official Claude Code CLI—without changing Muse itself.
It is a loopback protocol shim. Start it with Muse, then switch between Codex and Claude from Muse's built-in /model menu. Codex uses the native Responses API; Claude uses the installed official CLI's non-interactive claude -p mode by default. Direct Anthropic Messages/API-key mode remains available as an explicit option.
Python 3.10+, standard library only (no runtime pip dependencies).
| Mode | Auth | Upstream wire format | What the shim does |
|---|---|---|---|
auto (default) |
Codex OAuth + Claude Code login | Codex Responses + Claude CLI print mode | Advertises both catalogs to Muse; routes each request from the /model selection |
generic / http |
API key (MUSE_SHIM_API_KEY or Muse’s bearer) |
OpenAI Responses (POST …/responses) |
Flattens Muse namespace tools; optional portable field stripping; streams JSON/SSE through |
codex |
Codex OAuth (CLI auth.json or env token) |
Codex Responses backend | Loads/refreshes OAuth; preflights request; streams Responses events back to Muse |
claude |
Claude Code's existing login | Official claude -p structured output |
Sends each turn on stdin and maps text/tool calls back to Responses for Muse |
Default listen address: http://127.0.0.1:8787 (loopback only unless you explicitly opt out).
- Python 3.10+
- Meta Muse Code CLI (
muse) installed and runnable on your machine - For generic mode: an upstream that implements OpenAI Responses (
POST /responseswith SSE/streaming and function tools as needed). Chat Completions-only servers need a separate adapter (e.g. LiteLLM) in front. - For codex mode: Codex CLI logged in (
codex login) so~/.codex/auth.json(orCODEX_HOME) exists, or access/refresh tokens in the environment - For claude mode: the official Claude Code CLI (
claude) installed and logged in. Runclaude login(or your normal Claude Code authentication flow) first.
Clone and run from source (no install required):
git clone https://github.com/luckeyfaraday/muse-shim.git
cd muse-shim
./muse-shim --helpmuse-shim: command not found means the package has not been installed into your shell's PATH. Either keep using the zero-install ./muse-shim launcher above, or install the command with pipx:
pipx install .
muse-shim --helpFor contributors who want edits to take effect immediately, use pipx install --force --editable ..
Authenticate once, then launch the shim and Muse together:
codex login # if not already logged in
claude login # if not already logged in
./muse-shim run
# installed command: muse-shim runThat is the whole launch command. run starts the local proxy, supplies Muse's
local-only compatibility settings internally, opens Muse in the foreground, and
stops the proxy when Muse exits. Arguments after run are passed to Muse (for
example, muse-shim run --resume). Put shim options before it, as in
muse-shim --port 9000 run.
Inside Muse, enter /model (or /models) and choose an entry labeled Codex · … or Claude · …. Codex models are discovered from the account-visible catalog when possible; Claude CLI mode uses the configurable bundled Claude catalog.
Customize fallback entries without changing code:
MUSE_SHIM_CODEX_MODELS=gpt-5.6-sol,gpt-5.6-terra \
MUSE_SHIM_CLAUDE_MODELS=claude-fable-5,claude-opus-5,claude-sonnet-5 \
MUSE_SHIM_NO_MODEL_DISCOVERY=1 ./muse-shim runTo run the server and Muse in separate terminals, start ./muse-shim, then use
the manual Muse command in How Muse is launched.
Terminal 1 — authenticate once with the Codex CLI, then start the shim:
codex login # one-time setup; not used for inference
./muse-shim codex
# installed command: muse-shim codexTerminal 2 — point Muse at the loopback proxy:
META_API_KEY=local-shim-placeholder \
muse \
--provider meta \
--base-url http://127.0.0.1:8787Choose the Codex model with /model inside Muse. --model YOUR_CODEX_MODEL remains available when you intentionally want to pin provider-specific mode.
META_API_KEY only satisfies Muse’s local provider check. The shim uses Codex OAuth credentials for the real upstream call.
Check credentials without starting the server:
python3 muse_shim.py doctor --doctor-provider codexTerminal 1:
claude login # one-time setup
./muse-shim claudeTerminal 2:
META_API_KEY=local-shim-placeholder \
muse \
--provider meta \
--base-url http://127.0.0.1:8787The default Claude transport intentionally invokes the official CLI once per turn using claude -p, structured JSON output, safe mode, and disabled built-in tools. Muse remains responsible for executing Muse tools.
To use the Anthropic Messages API directly instead, opt into HTTP transport:
ANTHROPIC_API_KEY=sk-ant-your-key-here \
./muse-shim claude --claude-transport http --model claude-sonnet-5python3 muse_shim.py doctor --doctor-provider claudeOpenRouter example (default upstream base is OpenRouter’s API):
MUSE_SHIM_API_KEY="$OPENROUTER_API_KEY" \
MUSE_SHIM_MODEL="anthropic/claude-sonnet-4.5" \
./muse-shim genericAny Responses-compatible base URL:
MUSE_SHIM_UPSTREAM=https://api.openai.com/v1 \
MUSE_SHIM_API_KEY="$OPENAI_API_KEY" \
MUSE_SHIM_MODEL=gpt-5 \
./muse-shim genericThen launch Muse the same way:
META_API_KEY=local-shim-placeholder \
muse \
--provider meta \
--base-url http://127.0.0.1:8787 \
--model anthropic/claude-sonnet-4.5If you omit MUSE_SHIM_API_KEY, the shim forwards Muse’s incoming Authorization bearer (so you can put the real upstream key in Muse’s META_API_KEY instead).
Normally, use muse-shim run; it applies the settings below for you. The
expanded command is documented for debugging, custom process managers, and
two-terminal setups:
META_API_KEY=local-shim-placeholder \
muse --provider meta --base-url http://127.0.0.1:8787Muse is configured as if the provider were Meta’s own endpoint:
| Muse flag / env | Typical value with muse-shim |
|---|---|
--provider |
meta |
--base-url |
http://127.0.0.1:8787 |
--model |
Omit in auto mode; choose a codex/… or claude/… entry with Muse /model |
META_API_KEY |
Set internally by muse-shim run; a placeholder when launching manually and the shim supplies upstream auth |
The shim exposes:
GET /health— livenessGET /muse-code/modelsandGET /v1/muse-code/models— unified model catalog used by Muse/modelPOST /responsesandPOST /v1/responses— main inference path
python3 muse_shim.py doctor
python3 muse_shim.py doctor --doctor-provider codex
python3 muse_shim.py doctor --doctor-provider claude
python3 muse_shim.py doctor --doctor-provider genericDoctor reports the listen address, Codex credential status, whether the Claude CLI executable is available (or direct-HTTP credential status), and capability notes. It never prints secret values (secrets: not displayed).
Exit status is 0 when the checked providers look ready, otherwise non-zero.
┌─────────────┐ Responses JSON/SSE ┌────────────┐ Codex HTTP / Claude CLI ┌──────────────────┐
│ Muse Code │ ──────────────────────► │ muse-shim │ ─────────────────► │ Upstream provider│
│ (CLI) │ ◄────────────────────── │ :8787 │ ◄───────────────── │ │
└─────────────┘ └────────────┘ └──────────────────┘
│ │
│ META_API_KEY placeholder │ generic: Bearer API key
│ --base-url loopback │ codex: OAuth + Codex Responses
└──────────────────────────────────────│ claude: official CLI print mode
│
local only (default bind 127.0.0.1)
- Muse sends OpenAI Responses requests (including Meta-specific namespace tool groups).
- muse-shim flattens namespace tools into ordinary function tools and optionally rewrites model / max tokens / portable fields.
- generic: forward to
UPSTREAM/responseswith API key. - codex: resolve OAuth from env or
~/.codex/auth.json, preflight body (store=false, drop empty tools /max_output_tokensas required by the Codex backend), call the Codex Responses endpoint, stream events back. - claude: serialize the normalized turn and tool schemas to stdin for the official
claude -pclient, then convert structured text/tool calls back to Responses events/JSON. Direct Messages mode is available with--claude-transport http.
- Muse namespace tool wrappers are flattened for all modes (duplicate names rejected).
- generic / codex: function tools stay in Responses shape end-to-end (Codex receives the preflighted Responses payload).
- claude CLI: the shim supplies tool schemas through a structured-output envelope while launching Claude with built-in tools disabled. Returned tool calls are validated and mapped to Responses function calls for Muse to execute.
- claude HTTP: tools, tool calls, and tool results are mapped between Responses and Anthropic Messages.
- Streaming and non-streaming Muse responses reconstruct text, tool use, and usage. CLI-mode SSE begins after the
claude -pprocess completes; it is not token-by-token Claude streaming.
Environment variables and flags are interchangeable for most settings (python3 muse_shim.py --help).
| Setting | Env | Flag / notes |
|---|---|---|
| Mode | MUSE_SHIM_PROVIDER |
positional auto/generic/http/codex/claude or --provider; default auto |
| Listen | MUSE_SHIM_HOST, MUSE_SHIM_PORT |
default 127.0.0.1:8787 |
| Upstream | MUSE_SHIM_UPSTREAM |
generic default https://openrouter.ai/api/v1 |
| Codex upstream | MUSE_SHIM_CODEX_UPSTREAM / MUSE_SHIM_CODEX_BASE_URL |
default Codex Responses endpoint |
| Claude upstream | MUSE_SHIM_CLAUDE_UPSTREAM / MUSE_SHIM_CLAUDE_BASE_URL |
default Anthropic Messages |
| Claude transport | MUSE_SHIM_CLAUDE_TRANSPORT |
`--claude-transport cli |
| Claude executable | MUSE_SHIM_CLAUDE_CLI |
--claude-cli; default claude |
| API key | MUSE_SHIM_API_KEY |
generic (and Claude API-key path via ANTHROPIC_API_KEY) |
| Model override | MUSE_SHIM_MODEL |
--model |
| Codex fallback models | MUSE_SHIM_CODEX_MODELS |
--codex-models, comma-separated |
| Claude fallback models | MUSE_SHIM_CLAUDE_MODELS |
--claude-models, comma-separated |
| Disable live catalog lookup | MUSE_SHIM_NO_MODEL_DISCOVERY=1 |
--no-model-discovery |
| Portable mode | MUSE_SHIM_PORTABLE=1 |
strips include, prompt_cache_key, reasoning |
| Max output tokens | MUSE_SHIM_MAX_OUTPUT_TOKENS |
caps Muse’s large defaults |
| Verbose logs | MUSE_SHIM_VERBOSE=1 |
paths/status only; never bodies or keys |
| Codex auth file | MUSE_SHIM_CODEX_AUTH, CODEX_HOME |
--codex-auth-path, --codex-home |
| Claude creds file | MUSE_SHIM_CLAUDE_CREDENTIALS, CLAUDE_CODE_CREDENTIALS_PATH, CLAUDE_CONFIG_DIR |
--claude-credentials; direct HTTP mode only |
| Non-loopback bind | — | --allow-non-loopback only (no env opt-in) |
| OAuth host override | — | --allow-oauth-host-override only (dev fakes; no env opt-in) |
- Default bind is loopback. Binding to non-loopback requires
--allow-non-loopbackand prints a warning. Do not expose this proxy on a public interface without your own auth and network controls—the shim does not implement client authentication for Muse. - Secrets stay local. Claude CLI mode lets Claude Code own its credentials; the shim does not read them. Direct provider modes read tokens or keys from the environment or standard credential files. Verbose mode does not log bodies or credentials.
- Prompts are not command arguments. Claude CLI requests are written to stdin. The subprocess is launched without a shell, in safe mode, with Claude built-in tools and session persistence disabled.
- Native OAuth hosts are allow-listed. Codex and Claude endpoints and token URLs must match approved hosts unless you pass the explicit development flag
--allow-oauth-host-override. - TLS:
--insecure-upstreamis for generic development only and is rejected in codex/claude modes. - Credential refresh may update local auth files atomically when a refresh token is present; treat those files like passwords.
- This project is unofficial and not affiliated with Meta, OpenAI, or Anthropic. Using third-party endpoints with Muse may be subject to each vendor’s terms of service and your account limits.
| Symptom | What to try |
|---|---|
credentials not found / 401 from doctor or Muse |
Run codex login or claude login; re-run doctor |
Claude CLI executable 'claude' not found |
Install Claude Code or set MUSE_SHIM_CLAUDE_CLI to its executable path |
| Claude 429 / session limit | Wait for the reset shown by Claude Code, or use another authenticated account/transport; the shim preserves the provider message |
muse-shim: command not found |
Run ./muse-shim, or install it with pipx install . |
Codex/Claude model missing from /model |
Set MUSE_SHIM_CODEX_MODELS / MUSE_SHIM_CLAUDE_MODELS, then restart the shim and Muse |
Claude rejects previous_response_id |
Expected: Claude mode has no durable response-state store; avoid multi-turn that depends on that field |
| Upstream “unknown field” / strict Responses | Try MUSE_SHIM_PORTABLE=1 and/or lower MUSE_SHIM_MAX_OUTPUT_TOKENS |
| Chat Completions-only server fails | Needs a Responses adapter in front; generic mode is Responses-only |
| Connection refused from Muse | Confirm shim is listening on the same host/port as --base-url |
| Want remote clients | Only with --allow-non-loopback and your own hardening—not recommended for shared networks |
Meta Muse Code is a closed, auto-updating binary. muse-shim targets the wire format observed in current Muse Code Responses traffic (including namespace tools). A future Muse release can break the proxy; treat this as best-effort community tooling.
Validation note: unit and adapter tests cover transforms, structured CLI output, tool calls, streaming conversion, OAuth refresh paths, and safety guards with local fakes. Production provider calls are not asserted in CI; validate against your own accounts before relying on a given model.
Is this an official Meta / OpenAI / Anthropic product?
No. It is an unofficial local AI coding agent proxy for Muse.
Does it run Codex or Claude as a subprocess?
Codex uses its HTTP Responses backend and never runs codex exec. Claude intentionally uses the official claude -p print-mode subprocess by default; it runs in safe mode with built-in tools disabled. --claude-transport http selects the direct Messages adapter instead.
Can I use OpenRouter?
Yes—generic mode defaults toward OpenRouter’s Responses API base URL. Provide your OpenRouter API key and a model id OpenRouter accepts.
What is the difference between generic and http?
Aliases for the same mode (historical name http).
Where are OAuth credentials read from?
- Codex: env tokens,
--codex-auth-path,CODEX_HOME/auth.json, then~/.codex/auth.json. - Claude CLI mode: credentials remain owned by Claude Code. Direct HTTP mode: env tokens /
ANTHROPIC_API_KEY, credential path env vars,~/.claude/.credentials.json, then macOS Keychain when available.
Does verbose logging leak prompts or keys?
No. Verbose mode logs HTTP request lines suitable for debugging connectivity, not bodies or secrets.
- Unofficial; Muse updates may require shim updates.
- Generic mode requires a Responses API, not Chat Completions alone.
- Claude mode does not support
previous_response_id. CLI mode maps Muse reasoning effort to Claude's effort option where supported, but not to explicit thinking blocks. - Claude CLI mode is turn-at-a-time and currently supports text and structured Muse tool calls; its SSE output is emitted after CLI completion rather than token by token.
- Codex mode applies backend-specific request preflight (e.g.
store=false). - No multi-tenant auth on the loopback server.
- No guarantee of feature parity with Meta’s first-party models (vision, caching, reasoning depth, rate limits, etc.).
- Contributing: see CONTRIBUTING.md
- Security: see SECURITY.md (use GitHub private security advisories)
- Code of conduct: see CODE_OF_CONDUCT.md
- License: MIT — copyright muse-shim contributors
Meta Muse Code model provider shim · Claude Code CLI integration · claude -p print mode · Codex OAuth · Anthropic Messages API · OpenAI Responses API · OpenRouter · Muse /model provider · Muse namespace tools · loopback Responses proxy