OpenClaw Model Manager: a GUI so I stop hand-editing model routing JSON
- Category
- Tools & Downloads
- Posted
- July 11, 2026
- By
- Jacob Lloyd — written with AI assistance, post-project
- Read time
- 7 min read
In plain terms: A free desktop app that gives my home AI setup a proper control panel, replacing risky hand-editing of a settings file. It shows which AI "brain" each helper is using and lets me switch them with a click, refusing to save anything that would break the system. It exists because one typo once silently knocked an assistant offline.
I once typo'd a model id in a JSON file and the agent using it just went quiet. No error, no crash. It sat there talking to a model that didn't exist while I hunted for a much more interesting bug. This app is my never-again.
TL;DR
- What it is: a GTK4/libadwaita desktop app that edits
openclaw.json, the config deciding which LLM every agent, subagent, and cron job in my OpenClaw stack talks to. - What it costs: free, MIT licensed, source in the zip below.
- What you need: Linux with GTK4 + libadwaita + PyGObject (one package-manager line), Python 3.11+, and an OpenClaw install — or the bundled example config to start from scratch.
- What you end up with: a one-screen dashboard of every agent's model, saves that can't corrupt the file or assign a dead model, and a point-and-click switch that routes the Claude Code CLI to a free local model, cheap DeepSeek, or real Anthropic billing.
What you end up with
Screenshots first. These come from a sandboxed copy running against a dummy config in a throwaway HOME. Real app, fake data, none of my keys.
The main window answers the question I used to answer by grepping JSON: which model is running where, and what does it cost? Every agent, the stack-wide defaults, the subagent override, cron jobs, even a sibling email agent's models. Each entry gets a color badge: Local (this PC), Remote (the second PC), or Cloud (the one that shows up on a bill).
Why this exists
OpenClaw is the multi-agent stack I run at home: several AI agents, each pointed at a model, some local and free, some cloud and billed. All the routing lives in one file, ~/.openclaw/openclaw.json: model catalog, per-agent primary/fallback assignments, provider configs, and the gateway's own auth token. Hand-editing it kept going wrong in two ways.
First, a bad model id fails silently. A stale default once pointed an agent at vllm/google/gemma-4-31b-qat, a model the provider never served. A malformed save is worse: one bad edit and the whole gateway crash-loops.
Second, switching the Claude Code CLI between backends is invisible env-var surgery. OpenClaw spawns Claude Code for coding tasks, and where those requests go — and who gets billed — is set by ANTHROPIC_* environment variables on the gateway's systemd unit. Flipping between free local, cheap DeepSeek, and real Anthropic meant hand-writing a systemd drop-in each time. Exactly the kind of thing I get wrong at 11pm.
The save path
The part I need to trust is what happens when you click Save. This is it, in order:
Two steps carry the weight. Validation refuses any model id its provider doesn't advertise, which makes the typo bug from the intro structurally impossible instead of something I have to remember to check. And the atomic write exists because openclaw.json holds the gateway's auth token and must stay chmod 600: the temp file gets the original's permissions before any content is written, then it's fsync'd and renamed over the original. Crash mid-save and the old file is untouched.
A bad save is one rename away from undone, and you keep five generations of history instead of one.
The Coding Helper drop-in
Rerouting the Claude Code CLI is a separate flow because it never touches openclaw.json. It writes a systemd drop-in that overrides the gateway's environment before the gateway spawns Claude Code.
Four modes, one dropdown: LM Studio (free, local), DeepSeek via its Anthropic-compatible endpoint (cheap), Anthropic Cloud (the default: no drop-in at all, nothing overridden), or Disabled, which points the CLI at http://127.0.0.1:9/blocked so every call fails fast instead of hanging. There's also a one-click live test that fires a real Anthropic-shaped ping at LM Studio or DeepSeek and reports which model actually answered. You're not trusting a config screen, you're trusting a request that just happened.
Keeping the API key out of the unit file
DeepSeek mode needs an API key, and a systemd unit file is a lousy place for one: anything written there directly sits in plain text on disk and in systemctl show output. So the drop-in never contains the key. It writes this instead:
ExecStart=/usr/bin/bash -c 'export ANTHROPIC_API_KEY="$$DEEPSEEK_API_KEY"; exec <gateway cmd>'
The trick is $$. In a unit file, $$ escapes a literal $. Without it, systemd expands the variable itself while building the command line, and the real key lands in the process's argv where ps can read it. With the double dollar, bash receives a literal $DEEPSEEK_API_KEY and expands it at runtime from the gateway's EnvironmentFile (~/.openclaw/gateway.systemd.env, chmod 600). The secret never appears in the unit file, in systemctl show, or in a process listing — only inside bash's own environment, for that one process. The zip's examples/ folder documents the pattern with CHANGE_ME placeholders.
Setup
From the README shipped in the zip:
# 1. Install GTK4 + libadwaita + PyGObject from your distro's packages
# (one dnf/apt line — see README-SETUP.md for the exact package names)
# 2. Install the app and its launcher
install -Dm755 openclaw-model-manager ~/.local/bin/openclaw-model-manager
# .desktop file goes to ~/.local/share/applications/
# 3. If you don't already have an OpenClaw config:
cp examples/openclaw.json.example ~/.openclaw/openclaw.json
chmod 600 ~/.openclaw/openclaw.json
# then replace every CHANGE_ME placeholder inside it
# 4. Optional — API keys, both chmod 600, examples provided:
# ~/.openclaw/.env
# ~/.openclaw/gateway.systemd.env
No pip installs beyond PyGObject; everything else is Python 3.11+ stdlib, tomllib included. The whole thing is one executable script (164KB, 3,570 lines), a .desktop launcher, a README, an MIT license, and four example configs. Zips to 49KB.
Gotchas
- Cloud mode means "no drop-in," not "definitely my Anthropic account." Nothing gets overridden, so whatever was already configured on the unit keeps running. The app warns when the mode you picked has no working key, but check anyway.
- The drop-in shadows your real Anthropic key, by design. Local mode sets
ANTHROPIC_API_KEY=lm-studiofor everything the gateway spawns. On my machine that silently rerouted my interactiveclaudeCLI aliases to LM Studio — Claude Code kept "working," the answers just came from a local model. If Claude starts sounding off, runsystemctl --user cat openclaw-gateway.serviceand look for a drop-in before blaming the model. - After
openclaw updatechanges the gateway's ExecStart, re-select DeepSeek mode once to re-wrap the new command. The app reads the canonical ExecStart from the unit fragment and detects its own wrapper (it keys onindex.jsplus the absence of$$DEEPSEEK_API_KEY), so it never double-wraps — but it won't auto-fix a command it hasn't been told to look at again. reasoning: trueis the safe default for local models. A model that emitsreasoning_contentwhile configuredreasoning: falsereads as stalled to the gateway: about 390 seconds of silence, then a kill. It's harmless left on for non-thinking models, so the add-model dialog defaults it on. This one cost real debugging time.- A non-empty
plugins.allowis a strict allowlist.enabled: trueon a plugin entry does nothing unless its id is also inallow. The app reads this correctly and deliberately never writesplugins.*at all, so if a plugin misbehaves, this isn't the tool that'll tell you why. - The gateway rewrites
openclaw.jsonon its own (identity reconcile,openclaw update). The app tracks the file's mtime and warns before overriding an external edit, and the pre-save backup keeps whatever was actually on disk. - Model ids are
provider/raw-id. A bare id with no slash resolves through the local LM Studio endpoint. Not an error, just a convention worth knowing before you go hunting for a provider field that isn't there.
Downloads
Free for personal use. If it saves you an afternoon, the coffee button's nearby.