Claude Desktop
Claude Desktop talks to LunaRoute as a third-party (“3P”) gateway. It does not read
ANTHROPIC_BASE_URL, environment variables, or ~/.claude/settings.json for this — it has its own
third-party inference configuration, and that is the only lever that routes it.
LunaRoute fills Desktop’s model picker by discovery: Desktop asks GET /v1/models, identifies
itself with a client header, and LunaRoute answers with Claude-shaped names Desktop accepts. Nothing
is hardcoded on your side.
1. Configure it with the CLI
Section titled “1. Configure it with the CLI”Quit Claude Desktop first. It keeps that profile in memory and can write its own copy over your change when it exits — reopen it in step 2. Then install the CLI (CLI setup) and run:
npm install -g @lunaroute/clilunaroute setup claude-desktopDesktop creates its own profile file the first time you configure third-party inference; the CLI merges the gateway keys into that file for you, keeping any other keys it finds. It refuses rather than guess when Desktop has not created a profile yet:
Claude Desktop has not created a third-party inference profile yet — in Desktop open Help → Troubleshooting → Enable Developer Mode, then Developer → Configure Third-Party Inference once; then re-run.
Before its first write the CLI takes a snapshot of that profile, at
~/.config/lunaroute/backups/claude-desktop/ (mode 0600 — it holds your key). That snapshot is what
the undo below restores. Use lunaroute setup claude-desktop --print to preview without writing
anything.
Manual configuration (the GUI way)
Prefer to do it by hand? Open Help → Troubleshooting → Enable Developer Mode, then Developer → Configure Third-Party Inference, and enter your routing URL:
https://gw.lunaroute.comThat is what makes Desktop write a profile file. Let the app create it — do not hand-create one; the file name is generated by the app and the app tracks which profile is applied.
Then open that profile file and merge in these keys:
{ "inferenceProvider": "gateway", "inferenceGatewayBaseUrl": "https://gw.lunaroute.com", "inferenceGatewayApiKey": "lr_your_key_here", "inferenceGatewayAuthScheme": "bearer", "modelDiscoveryEnabled": true, "inferenceCustomHeaders": { "X-LunaRoute-Client": "claude-desktop" }}On Linux that file lives under ~/.config/Claude-3p/configLibrary/. The X-LunaRoute-Client
header is what selects LunaRoute’s Claude-compatible catalog; without it you get the normal
catalog, whose names Desktop filters out.
Two things about that file:
- The key is stored literally. Desktop expands no environment variables here, so paste the key in full and keep the file private.
- Do not add an
inferenceModelslist. A pinned list switches discovery off — Desktop skips the discovery call when every entry is a full model id — and then the picker shows none of LunaRoute’s models. This is the single most common way to get an empty picker.
2. Restart Desktop
Section titled “2. Restart Desktop”Quit and reopen Claude Desktop (on Windows, end the Claude process in Task Manager if it will not quit). The picker now fills from discovery.
Quit Claude Desktop before this too (reopen it after). Then:
lunaroute setup claude-desktop --removeThat restores the profile snapshot taken before setup — byte-for-byte, including any keys your own configuration had before LunaRoute touched the file. It needs no login, and it leaves the snapshot in place, so running it twice is harmless.
If there is no snapshot (you configured the profile by hand, or setup ran on an older CLI), the
command prints the keys to remove and changes nothing — it will not delete a key it cannot prove
it wrote. Add --print to see what it would do without touching the file.
What you will see
Section titled “What you will see”The picker lists Claude-shaped aliases — claude-opus-lr29, claude-haiku-lr37, and so on. The
id is a wire alias that LunaRoute translates back to the catalog model before routing, so nothing
about that mapping is yours to maintain.
The catalog entry also carries a human-readable label in display_name — an
operator-configured value (for example GLM 5.3), falling back to the canonical
LunaRoute model id when none is set. Whether Desktop renders that label in its
picker is not yet verified; the alias id is what it requires.
With a gateway configured, Desktop runs local sessions only: no SSH or cloud environments, and no Remote Control.
Verify without opening the app
Section titled “Verify without opening the app”curl https://gw.lunaroute.com/v1/models \ -H "Authorization: Bearer $LUNAROUTE_API_KEY" \ -H "X-LunaRoute-Client: claude-desktop"You should get the same alias list the picker shows. The same request without the
X-LunaRoute-Client header returns the normal catalog, which is what Desktop rejects.
Platforms
Section titled “Platforms”The profile path above and the CLI’s write are verified on Linux. macOS and Windows use the same configuration shape, but their profile locations have not been verified — so the CLI refuses to guess them there, and you should check where the app wrote its own file before editing it by hand.
Troubleshooting
Section titled “Troubleshooting”| Symptom | Cause |
|---|---|
| Picker is empty | An inferenceModels list is pinned. Remove it — a pinned list disables discovery. |
| Picker is empty, no list pinned | The X-LunaRoute-Client header is missing or misspelled in inferenceCustomHeaders. |
| “Configuration may need attention” | A key in the profile is not one Desktop recognises, or the routing URL has a path — it takes an origin only (https://gw.lunaroute.com, no /v1). |
| Models list, but requests fail with 401 | The key is wrong or expired. Desktop does not expand variables; re-paste the literal key. |
| A model appears but will not answer | Its upstream is unavailable — that model’s provider credential or capacity, not your configuration. |
--remove says “no snapshot exists” |
The profile was configured by hand. Remove the six keys it prints (or re-run setup, then --remove). |
Related
Section titled “Related”- Authentication — key formats and header variants.
- Models API — the catalog
/v1/modelsserves, including the Claude Desktop variant. - Harness setup — Claude Code, Codex, and the other harnesses.
- CLI — the full
lunaroute setupsurface. - Claude Code — the CLI, which routes through environment variables instead of the profile above.
- Codex — Codex CLI, profile-based or per session.