Skip to content

Models & Providers

Everything about how gald3r talks to LLMs — local (Ollama, LM Studio, vLLM, llama.cpp) or cloud (OpenRouter, Anthropic, OpenAI, and any OpenAI-compatible endpoint). Every command output on this page was verified against a real checkout unless a block is explicitly marked illustrative — see troubleshooting.md for that same real-output discipline applied to doctor/selftest/errors.

At a glance

Verb What it does
gald3r init-providers Write (or preview) a starter providers.yaml, auto-detecting installed local backends
gald3r providers set-key Store a provider's API key in your OS keyring instead of the plaintext file
gald3r connect <provider> Device-code sign-in for a provider account — see below for a real capture
gald3r local-model assess Recommend a local model size/quant for your hardware
gald3r local-model serve Print the exact copy-pasteable command to serve that recommendation

providers.yaml anatomy

gald3r init-providers

gald3r init-providers --help
Get set up to use local LLMs (Ollama, LM Studio, vLLM, llama.cpp) -- auto-detects what's
installed and writes the config for you.

Flags:
      --dry-run         Print the rendered starter YAML without writing it
      --overwrite       Replace an existing providers.yaml instead of leaving it untouched
      --target string   Destination path (default: <gald3r home>/providers.yaml)

The default location is <gald3r home>/providers.yaml — that home directory resolves to $GALD3R_HOME when set, else ~/.gald3r (the same directory gald3r doctor reports on its gald3r_home line). It is one file shared across every project on the machine — provider credentials are a per-install concern, not a per-project one — pass --target to point at a different path if you need one.

The full starter file (real capture)

gald3r init-providers --dry-run
# providers.yaml
# Edit to add/remove providers. API keys with $ prefix are env var references.

default_provider: ollama
default_model: qwen2.5:7b-instruct

providers:
  ollama:
    type: openai_compat
    base_url: http://localhost:11434/v1
    api_key: ollama
    models:
      - id: qwen2.5-coder:14b
        role: coding
        context_window: 32768
      - id: qwen3:4b
        role: general
        context_window: 32768
      - id: qwen3-vl:4b
        role: vision
        context_window: 32768
      - id: deepseek-r1:32b
        role: reasoning
        context_window: 65536
      - id: llava:7b
        role: vision
        context_window: 4096
      - id: gpt-oss:20b
        role: coding
        context_window: 65536
      - id: gpt-oss:120b
        role: coding_heavy
        context_window: 131072

  lmstudio:
    type: openai_compat
    base_url: http://localhost:1234/v1
    api_key: lm-studio
    models:
      - id: Qwen2.5-Coder-14B-Instruct-GGUF/Qwen2.5-Coder-14B-Instruct-Q4_K_M.gguf
        alias: qwen2.5-coder-14b
        role: coding
        context_window: 32768
      # ... (more LM Studio entries, trimmed here — see the full block this
      # page's Ollama/LM Studio recipes below reproduce in full)

  openrouter:
    type: openai_compat
    base_url: https://openrouter.ai/api/v1
    api_key: $OPENROUTER_API_KEY
    models:
      - id: anthropic/claude-sonnet-4-5
        role: planning
      - id: google/gemini-2.5-flash
        role: general_cheap
      - id: qwen/qwen2.5-coder-32b-instruct
        role: coding_cloud

  anthropic:
    type: anthropic
    api_key: $ANTHROPIC_API_KEY
    models:
      - id: claude-opus-4-5-20260514
        role: planning_heavy
      - id: claude-sonnet-4-5
        role: planning
      - id: claude-haiku-3-5
        role: general_cheap

  openai:
    type: openai_compat
    base_url: https://api.openai.com/v1
    api_key: $OPENAI_API_KEY
    models:
      - id: gpt-4o
        role: general
      - id: gpt-4o-mini
        role: general_cheap

(Trimmed the LM Studio block's remaining entries and one bundled Sakana Fugu provider block for length — every provider shown above and elided is transcribed unedited from a real --dry-run run; nothing here is invented.)

Reading the shape

Key Meaning
default_provider / default_model (top-level) Used when you run gald3r run "..." with no --model flag at all
providers.<id>.type openai_compat (anything speaking the OpenAI Chat Completions wire format — local backends, OpenRouter, OpenAI itself) or anthropic (the native Anthropic Messages API)
providers.<id>.base_url Required for every openai_compat provider (irrelevant for anthropic, which has a fixed endpoint)
providers.<id>.api_key A literal string, a $ENV_VAR reference (expanded at read time), or — once you run set-key — overridden transparently by an OS-keyring secret (see Keys: keyring vs. plaintext below)
providers.<id>.models[] One entry per model: id (the real model identifier sent to the endpoint), optional alias (a short name you can use instead of the full id — handy for LM Studio's long GGUF filenames), optional context_window, and role

role is organizational metadata today, not a live routing switch. Resolving a model never reads a model's role field to pick it — the only things that select a model are an explicit provider:model_or_alias spec, the YAML's own default_provider/default_model, or (with neither set) that provider's first models[] entry. role exists so a human (or an agent reading the file) can tell at a glance which model in a provider's list is meant for which job — and it's also what init-providers' auto-discovery heuristic assigns to a newly-detected Ollama model by name pattern (coder/codecoding, vl/vision/llavavision, deepseek...r1reasoning, a 120b tag → coding_heavy, everything else → general) when it writes the starter file. There is no code path today that reads role back out to auto-select a model for a task; if you want a specific model, name it explicitly.

Resolving a provider:model spec

--model (on gald3r run) and default_provider/default_model (in the YAML) both accept either bare provider or provider:model_or_alias:

  • ollama alone → that provider's first models[] entry (qwen2.5-coder:14b in the starter file above).
  • lmstudio:qwen2.5-coder-14b → matched against alias first (this is exactly why LM Studio's block gives its long GGUF filenames short aliases), then against the literal id.
  • ollama:qwen3:4b → model ids may themselves contain colons, so only the first colon splits provider from model.
  • A model you name that doesn't appear in models[] at all is still passed through as-is (model lists aren't exhaustive — you may have pulled something brand new); the real backend returns its own error if the name truly doesn't exist. See Troubleshooting below for exactly what that looks like.
  • An unconfigured provider id raises immediately with a clear message — also covered below.

gald3r providers set-key — keys: keyring vs. plaintext

gald3r providers set-key --help
Store (or delete) a provider's API key in the OS keyring

Usage:
  gald3r providers set-key PROVIDER [flags]

Flags:
      --delete         Remove the stored keyring entry instead of setting one
      --value string   Secret value (omit to be prompted -- passing this flag exposes the
                        secret in shell history/process list, so prefer the interactive
                        prompt unless scripting).

gald3r providers set-key openrouter prompts (securely — nothing echoed, nothing in shell history) and stores the secret in your OS's native keyring (Credential Manager on Windows, Keychain on macOS, Secret Service on Linux) under service gald3r-providers, account <provider id>. Once stored, the keyring value takes precedence over anything in providers.yaml for that provider — a literal api_key: string or a $ENV_VAR reference both get overridden. That precedence is deliberate: the whole point of set-key is letting you migrate a real secret out of the plaintext file, and if the file stayed authoritative after that migration you'd have to separately go blank it out for the migration to mean anything.

If no keyring backend is available on the system, set-key says so plainly and does not fall back to writing the secret to a file:

gald3r providers set-key --delete gald3r_docs_probe_nonexistent
No keyring entry found for 'gald3r_docs_probe_nonexistent' (or no keyring backend is available on this system).

(Real output — a safe, non-destructive probe against a provider id that was never stored, run while writing this page.)

init_providers_file (the code behind init-providers) never writes a real secret itself — only template placeholders (ollama, lm-studio) and $ENV_VAR references. A hand-typed literal key in the file is still supported, but every providers.yaml load logs a warning if it finds one (or loose file permissions, on POSIX) — prefer set-key or a $ENV_VAR reference.

Local backends

Each recipe below: install the runtime, pull/load a model, the providers.yaml block, and how to confirm gald3r actually reaches it. gald3r init-providers auto-detects three of the first four runtimes below by probing their default port for a live, unauthenticated OpenAI-compatible /models endpoint — Ollama is discovered differently, via its own ollama list CLI — so re-running init-providers after a backend is up is itself the verification step for that backend. Unsloth Studio (below) is NOT part of that auto-discovery: its /models endpoint requires a bearer token (see its own subsection), so an unauthenticated probe would just get a 401 rather than a usable model list — configure its providers.yaml block by hand instead.

Ollama

Install from ollama.com, then:

ollama pull qwen2.5-coder:14b

gald3r init-providers shells out to ollama list and writes a models: entry per installed model automatically — the ollama: block in the full starter capture above (base URL http://localhost:11434/v1, api_key: ollama — a dummy value Ollama ignores, not a real credential) is exactly what that discovery produced against models actually pulled on the machine this page's example was drafted from.

Verify: gald3r doctor's providers line reports how many providers are configured (...\providers.yaml: N provider(s) configured — see troubleshooting.md), or re-run gald3r init-providers --dry-run and confirm your pulled models show up under ollama:.

LM Studio

Install from lmstudio.ai, load a model in its UI, and start LM Studio's local server (Developer tab → Start Server — default port 1234). The lmstudio: block in the starter capture above was written by the same local-runtime discovery probe hitting http://localhost:1234/v1/models while the server this page was drafted against had those GGUF models loaded:

lmstudio:
  type: openai_compat
  base_url: http://localhost:1234/v1
  api_key: lm-studio
  models:
    - id: Qwen2.5-Coder-14B-Instruct-GGUF/Qwen2.5-Coder-14B-Instruct-Q4_K_M.gguf
      alias: qwen2.5-coder-14b
      role: coding
      context_window: 32768

The long id is LM Studio's own model-file path — that's why init-providers' auto-discovery gives it a short alias (qwen2.5-coder-14b) you can use instead: --model lmstudio:qwen2.5-coder-14b.

Verify: same as Ollama — gald3r doctor or a fresh init-providers --dry-run with the LM Studio server running.

vLLM

Illustrative — no vLLM instance was available to probe while writing this page, but the shape below is grounded in the real discovery behavior: the fixed default-port table probes vLLM at http://localhost:8000/v1 by default, and render_starter_yaml's block-writer sets type: openai_compat, that base_url, a placeholder api_key: local (vLLM's OpenAI-compat server doesn't check it locally), and one models: entry per id the /models probe returns — the exact same code path the real Ollama/LM Studio blocks above went through.

pip install vllm
vllm serve Qwen/Qwen2.5-Coder-14B-Instruct --port 8000
vllm:
  type: openai_compat
  base_url: http://localhost:8000/v1
  api_key: local
  models:
    - id: Qwen/Qwen2.5-Coder-14B-Instruct
      role: coding

Verify: start vllm serve, then run gald3r init-providers --dry-run — a reachable vLLM server on port 8000 gets auto-discovered and written into the block exactly like LM Studio's, the same way you'd confirm any of these.

llama.cpp

Illustrative — same honesty note as vLLM above. llama.cpp's server binary (or llama-server) defaults to port 8080 in the local-runtime discovery table:

# build llama.cpp per its own README, then:
llama-server -m ./models/qwen2.5-coder-14b-q4_k_m.gguf --port 8080
llama-cpp:
  type: openai_compat
  base_url: http://localhost:8080/v1
  api_key: local
  models:
    - id: qwen2.5-coder-14b-q4_k_m
      role: coding

Verify: identical pattern — gald3r init-providers --dry-run with the server running auto-discovers it via the same /models probe.

Unsloth Studio

Illustrative — no live Unsloth Studio instance was available to probe while writing this page; the shape below is sourced directly from Unsloth's own docs (unsloth.ai/docs/desktop and its linked API guide, unsloth.ai/docs/basics/api.md), verified against those docs directly — not guessed, and not (yet) confirmed against a running instance. Unsloth Studio is a new open-source local AI engine from the Unsloth team (github.com/unslothai/unsloth); gald3r treats it as a fourth "known" local runtime alongside Ollama/LM Studio/OpenRouter, with a dedicated unsloth provider id.

Unlike the three runtimes above, Unsloth Studio's OpenAI-compatible endpoint is not keyless — every request needs a real bearer token:

unsloth studio -p 8888
unsloth:
  type: openai_compat
  base_url: http://localhost:8888/v1
  api_key: $UNSLOTH_API_KEY
  models:
    - id: gemma-4-26B-A4B-it-GGUF
      role: general
  • Port: Unsloth's API guide states it "exposes these endpoints on whichever port it booted on (typically http://localhost:8000 or http://localhost:8888)" — genuinely ambiguous prose in the source docs — but every concrete example in that same guide (unsloth studio -p 8888, the /v1/models curl sample below) targets 8888, so that's the default gald3r ships. Confirm against whichever port your own instance printed on launch if it differs.
  • Auth: generate a key in Studio's Settings → API (format sk-unsloth-...), then export it as UNSLOTH_API_KEY (matches both gald3r's own <PROVIDER>_API_KEY convention and the exact variable name Unsloth's own docs use). There is no keyless placeholder for unsloth the way ollama/lm-studio have one — a missing key fails at call time with a real auth error, not silently.
  • Model listing: GET /v1/models with Authorization: Bearer sk-unsloth-... — per the API guide's own example: bash curl http://localhost:8888/v1/models \ -H "Authorization: Bearer sk-unsloth-xxxxxxxxxxxx"

unsloth start interop (agent CLIs, not providers.yaml)

Unsloth Studio ships its own wrapper, independent of gald3r's providers.yaml: from a project folder, with a model loaded in Studio,

unsloth start claude    # or: codex, opencode, hermes

launches that agent CLI directly, pointed at the local model via a temporary, session-scoped provider configuration — per Unsloth's own integration guide, it does not touch the CLI's normal config files at all. This is a separate entry point from the providers.yaml block above:

You want... Use
gald3r's own provider registry to reach a running Unsloth Studio endpoint (--model unsloth:<id>, providers.yaml's unsloth: block) The providers.yaml block above
Unsloth's own wrapper to launch an agent CLI (Claude Code, Codex, OpenCode, Hermes Agent) against a local model for you unsloth start <agent>

Both reach the same underlying local server — pick whichever fits how you're launching that session. unsloth start is Unsloth's tooling, not a gald3r verb; run unsloth start --help (or consult unsloth.ai/docs/integrations/unsloth-start) for its own flags.

Verify: once real hardware access is available, this section should be re-captured against a live instance the same way the Ollama/LM Studio sections above were — flagged here rather than silently presented as verified.

Cloud providers

OpenRouter (worked example)

The starter file's openrouter: block (real capture, above) is the template:

openrouter:
  type: openai_compat
  base_url: https://openrouter.ai/api/v1
  api_key: $OPENROUTER_API_KEY
  models:
    - id: anthropic/claude-sonnet-4-5
      role: planning
    - id: google/gemini-2.5-flash
      role: general_cheap
    - id: qwen/qwen2.5-coder-32b-instruct
      role: coding_cloud

Get a key from openrouter.ai, then store it — prefer the keyring over the $ENV_VAR the template ships with:

gald3r providers set-key openrouter

(prompts securely; see Keys: keyring vs. plaintext above for the exact success/failure message shapes). --model openrouter:anthropic/claude-sonnet-4-5 (or any other listed id) selects a specific model; bare openrouter uses the first one.

Generic OpenAI-compatible cloud pattern

Any hosted endpoint that speaks the OpenAI Chat Completions wire format — a proxy, a self-hosted gateway, a provider not shown above — uses the exact same openai_compat shape:

my-custom-endpoint:
  type: openai_compat
  base_url: https://my-endpoint.example.com/v1
  api_key: $MY_ENDPOINT_API_KEY
  models:
    - id: whatever-the-endpoint-calls-it
      role: general

Every openai_compat entry requires base_url — omit it and you get a clear ProvidersYAMLError at load/build time rather than a silent failure.

connect, and the two local-model verbs

gald3r connect

gald3r connect [PROVIDER]

connect drives a real device-code sign-in round-trip (request → poll → store token) against world_tree, gald3r's optional hosted coordination service — this is the world_tree account link itself; for a third-party AI provider's own API key, use gald3r providers add/set-key instead. Real capture:

gald3r connect openai
gald3r connect openai: visit http://api.gald3r.ai/api/v1/auth/device/verify?user_code=CHMC-3D77 and enter code CHMC-3D77 (waiting up to 600s)...
gald3r connect openai: device code expired before authorization completed -- run `gald3r connect` again.

(Real — the run printed a genuine verification URL and one-time code, then polled for up to 600 seconds. Nothing visited that URL during this capture, so it expired unused — this page did not go on to test what happens after a completed authorization.) If you get this far, follow the printed URL and enter the code in any browser to finish linking the account; gald3r login --token <token> remains the direct power-user/CI path if you'd rather skip the device-code flow entirely (see troubleshooting.md for that page's own login capture — worth a grain of salt given this page's fresher finding above). None of this is required for local-only providers.yaml use — connect/login only matter once you're using world_tree-backed, cross-machine features.

gald3r local-model assess

gald3r local-model assess --help
Recommend a local-model variant/quant for this (or manually-described) hardware

Flags:
      --apple-chip string
      --apple-silicon               Host is macOS arm64
      --auto                        Probe this host's real OS/CPU/RAM/GPU facts instead of the manual flags below. Wins over every manual hardware flag when both are given.
      --cpu-cores int
      --efficiency-cores int
      --gpu-count int                Number of discrete GPUs with --gpu-vram-gib VRAM each (multi-GPU rigs are assumed uniform)
      --gpu-name string
      --gpu-vendor string
      --gpu-vram-gib float          Largest single discrete GPU's VRAM in GiB (0 = no discrete GPU)
      --os-name string
      --perf-cores int
      --ram-gib float
      --unified-memory-gib float

assess is a decision table over hardware facts — pass --auto to have it probe this host's real OS/CPU/RAM/GPU facts directly, or supply any of the manual flags yourself to assess a different machine (a manual flag always wins over --auto when both are given, so you can override just the one fact you want to test). Three real runs against different hardware profiles:

gald3r local-model assess --ram-gib 32 --gpu-vram-gib 24 --gpu-name "NVIDIA GeForce RTX 4090" --gpu-vendor nvidia
tier: 24gb
recommended variant: ornith-35b-moe (Q4_K_M)

[24gb tier] Recommend serving Ornith-1.0 35B MoE (~3B active/token) at Q4_K_M (~21.2 GiB) on NVIDIA GeForce RTX 4090 (24.0 GiB VRAM). 24GB baseline (RTX 4090 / 3090) — the validated default: 35B MoE Q4_K_M (~21 GiB) fits with room for context. Routine/bulk agent calls run locally at $0/token; reserve cloud models for hard tasks. Run 'gald3r local-model --serve-cmd' for the exact serve command.
gald3r local-model assess --ram-gib 16
tier: floor
recommended variant: ornith-floor (Q4_K_M)

No discrete GPU detected (CPU-only / integrated graphics) — FLOOR tier. Recommend the tiny SmolLM2 1.7B (tiny floor — routing/classification only) for cheap LOCAL routing / classification / autocomplete ONLY; it is NOT a coding model. Ornith 9B Q4 will run on CPU but slowly. Steer real coding to the CLOUD (reserve cloud for anything non-trivial). Run 'gald3r local-model --serve-cmd' for the floor + cloud guidance.
gald3r local-model assess --apple-silicon --apple-chip "Apple M4 Max" --unified-memory-gib 64
tier: apple_unified
recommended variant: ornith-35b-moe (Q8_0)

Apple M4 Max with 64 GiB UNIFIED memory — Apple-Silicon path (GPU shares system RAM, so the budget is far larger than a discrete card of the same price). Recommend serving Ornith-1.0 35B MoE (~3B active/token) at Q8_0 — runtime: PRIMARY is Ollama 0.19+ (MLX, ~2x faster) — its engine is MLX-backed automatically on Apple Silicon (no flag) on this 32 GiB+ Mac; mlx_lm.server is the fallback (Ollama-MLX-unsupported models). 64GB+ unified (M Max) — 35B MoE at higher precision with headroom for long context. Run 'gald3r local-model --serve-cmd' for the exact Mac serve command.

(All three real — the Apple-Silicon run works on any host since the hardware facts are supplied as flags, not detected; nothing above requires actually owning that hardware.) The recommendation is about Ornith, gald3r's own model family, sized to what your hardware can actually run — the "floor" tier explicitly steers real coding work to the cloud rather than pretending a 1.7B model can do it.

gald3r local-model serve

gald3r local-model serve --help
Print the copy-pasteable serve command(s) for a recommended variant

Flags:
      --apple-silicon
      --tensor-parallel-size int
      --unified-memory-gib float
      --variant string   one of: cloud_only, ornith-31b, ornith-35b-moe, ornith-397b-moe, ornith-9b, ornith-floor

Feed it the recommended variant from assess's output:

gald3r local-model serve --variant ornith-35b-moe
variant: ornith-35b-moe
served_model_id: ornith-1.0-35b-moe
vLLM (primary):   vllm serve ornith/Ornith-1.0-35B-MoE --served-model-name ornith-1.0-35b-moe --quantization gguf --max-model-len 16384 --gpu-memory-utilization 0.92 --port 8000 --enable-auto-tool-choice --tool-call-parser hermes
Ollama pull:      ollama pull ornith-1.0:35b-moe-q4_K_M
Ollama run:       ollama run ornith-1.0:35b-moe-q4_K_M
notes: Q4_K_M. 35B MoE Q4_K_M is ~21.2 GiB — fits a 24GB card 'barely' at 8-16K context. If you hit OOM, lower --max-model-len or --gpu-memory-utilization, or use Q5_K_M with ~1-2 layers offloaded to RAM. On multi-GPU (e.g. 2×24GB) tensor-parallel removes the fit pressure and allows higher precision.

Same variant, Apple-Silicon flags added:

gald3r local-model serve --variant ornith-35b-moe --apple-silicon --unified-memory-gib 64
variant: ornith-35b-moe
served_model_id: ornith-1.0-35b-moe
vLLM (primary):   vllm serve ornith/Ornith-1.0-35B-MoE --served-model-name ornith-1.0-35b-moe --quantization gguf --max-model-len 16384 --gpu-memory-utilization 0.92 --port 8000 --enable-auto-tool-choice --tool-call-parser hermes
Ollama pull:      ollama pull ornith-1.0:35b-moe-q4_K_M
Ollama run:       ollama run ornith-1.0:35b-moe-q4_K_M
MLX (Apple):      mlx_lm.server --model mlx-community/Ornith-1.0-35B-MoE-4bit --port 8080 --host 127.0.0.1
notes: Q4_K_M. 35B MoE Q4_K_M is ~21.2 GiB — fits a 24GB card 'barely' at 8-16K context. ... Apple Silicon (>= 32 GiB unified): PRIMARY is Ollama 0.19+ ('ollama run ornith-1.0:35b-moe-q4_K_M') — its engine is MLX-backed AUTOMATICALLY on Apple Silicon (no flag), ~2x faster than the old llama.cpp/Metal path. ... FALLBACK (< 32 GiB unified, or models Ollama-MLX can't serve yet): 'mlx_lm.server --model mlx-community/Ornith-1.0-35B-MoE-4bit --port 8080'.

It only ever prints commands — it never auto-installs a runtime or auto-pulls a model for you; you still run the printed command yourself. Neither local-model verb reads or writes providers.yaml; pair a locally-served Ornith model with a providers.yaml block the same way the Ollama/LM Studio/vLLM/llama.cpp recipes above show, once it's actually running.

Troubleshooting

Every message below is a real [error] a real gald3r run prints, captured against a scratch providers.yaml built specifically to trigger each failure — except the last, marked illustrative.

Missing key (a configured provider with no usable credential)

gald3r run "hi" --model anthropic
[error] Could not resolve provider: No configuration found for provider 'anthropic'. Set API key in <home>\providers.yaml or as an environment variable (ANTHROPIC_API_KEY, OPENAI_API_KEY, GOOGLE_API_KEY).

(Real — captured with an anthropic: block present in providers.yaml but with no api_key field, no $ANTHROPIC_API_KEY set, and no keyring entry stored.) Fix: gald3r providers set-key anthropic, a $ANTHROPIC_API_KEY environment variable, or a literal api_key: in the file.

Backend down / wrong base_url

gald3r run "hi" --model deadlocal
[error] Connection error.

(Real — captured with a deadlocal: provider whose base_url pointed at http://localhost:19999/v1, a port nothing was listening on.) This is the same message shape for both "the backend process isn't running" and "the base_url is simply wrong" — from gald3r's side they look identical (a failed TCP connection), so the fix is the same either way: confirm the backend is actually running (curl <base_url>/models, or just start it) and that base_url matches the port it's actually listening on.

Provider id not in providers.yaml at all

gald3r run "hi" --model totallyfake
[error] Could not resolve provider: No configuration found for provider 'totallyfake'. Set API key in <home>\providers.yaml or as an environment variable (ANTHROPIC_API_KEY, OPENAI_API_KEY, GOOGLE_API_KEY).

(Real — captured with no totallyfake: block anywhere in the file.) Note this is the same message text as the missing-key case above — today, gald3r's error path doesn't distinguish "this provider id doesn't exist in the file" from "this provider exists but has a config problem." If you see this and you're sure the provider IS in your providers.yaml, double-check its type/api_key/base_url fields rather than assuming the id itself is wrong — this is a known rough edge in the error message, not a sign your setup is broken.

Model-name mismatch (illustrative)

Not independently reproducible offline — a genuine model-name-mismatch response comes from the real backend's own API (e.g. Ollama/LM Studio returning an HTTP 404 for an unrecognized model id), and no local backend was available to capture this against while writing this page. The verified behavior instead: model resolution does not reject an unknown model id up front — a name that isn't in a provider's models: list is passed through as-is "as the user may have a brand-new local model," and the actual endpoint is left to return whatever error it returns for an unrecognized model (typically an HTTP 404 from an OpenAI-compatible server). If a run fails this way, the fix is to check the model id/alias against what the backend itself reports as loaded (ollama list, LM Studio's UI, or the endpoint's own /models route) rather than trust providers.yaml's list, since that list is not authoritative over what the backend actually has loaded.

Where next

  • concepts.md — the one-paragraph version of all this, if you just need the summary
  • verbs.md — every provider-related verb in the full command map
  • install.md — get gald3r itself installed before any of this matters
  • troubleshooting.mddoctor's providers line, and the general real-output-driven troubleshooting flow this page's Troubleshooting section follows

Managing providers.yaml from the CLI

Every command below was actually run against a scratch providers.yaml while writing this page. Output is trimmed for length but not altered in substance.

Why this exists

Hand-editing providers.yaml directly works, but has no validation and no feedback until something breaks at call time. gald3r providers adds a small verb family that makes hand-editing optional: list what's configured, add/ remove/edit providers and their models, assign role routing, and validate the whole file (schema, key presence, reachability) before you find out the hard way.

Every edit verb is round-trip safe: it preserves comments and the ordering of every block it doesn't touch, rather than a plain load-then-dump that would silently drop every comment in the file.

gald3r providers list

At-a-glance table: provider, type, base URL, key status, model count, and which roles are covered.

gald3r providers list
providers.yaml: C:\Users\you\.gald3r\providers.yaml

provider    type           base_url                      key        models  roles
----------  -------------  ----------------------------  ---------  ------  ------------------------------------------------
anthropic   anthropic      -                             env:unset  3       general_cheap, planning, planning_heavy
lmstudio    openai_compat  http://localhost:1234/v1      local      7       coding, coding_heavy, reasoning
ollama      openai_compat  http://localhost:11434/v1     local      7       coding, coding_heavy, general, reasoning, vision
openai      openai_compat  https://api.openai.com/v1     env:unset  2       general, general_cheap
openrouter  openai_compat  https://openrouter.ai/api/v1  env:unset  3       coding_cloud, general_cheap, planning
sakana      openai_compat  https://api.sakana.ai/v1      env:unset  2       general, planning_heavy

The key column is a classification, never the actual secret:

Value Meaning
keyring Resolved from the OS keyring (gald3r providers set-key) — takes precedence over anything in the file
env:set api_key is a $ENV_VAR reference and that variable is currently set
env:unset api_key is a $ENV_VAR reference, but that variable is not set right now
local A known keyless placeholder (ollama/lm-studio/local) — expected for local runtimes, not a real secret
plaintext A literal secret sitting in the file — works, but consider gald3r providers set-key instead
missing No key resolvable anywhere

gald3r providers add

gald3r providers add together --base-url https://api.together.xyz/v1 --model meta-llama/Llama-3.3-70B
Added provider 'together' to C:\Users\you\.gald3r\providers.yaml.

If no providers.yaml exists yet, add creates one from scratch (you don't have to run gald3r init-providers first).

Flags: --base-url URL, --type {openai_compat,anthropic} (default openai_compat), --model MODEL_ID (repeatable — adds bare model entries; use providers model add afterward to attach a role/alias/context window), --api-key $ENV_VAR_OR_PLACEHOLDER — a real-looking secret literal is refused (keys never go in the file in plaintext; use gald3r providers set-key for the OS keyring, a $ENV_VAR reference, or the local placeholders ollama/lm-studio/local) (prefer gald3r providers set-key to keep real secrets out of the file), --force (replace if the provider already exists).

gald3r providers remove

gald3r providers remove together --yes
Removed provider 'together' from C:\Users\you\.gald3r\providers.yaml.

--yes is required — this CLI never blocks on an interactive confirmation prompt (same convention as gald3r profile reset). Omitting it refuses with a clear message and makes no change.

If the provider you're removing sits immediately before a comment that documents a different provider, you'll see an extra warning first — the YAML round-trip editor attaches a "between blocks" comment to the end of the preceding block, not the "before" position of the one it visually describes, so removing the preceding provider can take an unrelated provider's documentation with it. The warning tells you before it happens so you can check the file afterward if that comment mattered.

gald3r providers set

Targeted field edits — no need to touch anything else in the block.

gald3r providers set ollama base_url=http://localhost:22222/v1
Updated 1 field(s) on provider 'ollama' in C:\Users\you\.gald3r\providers.yaml.

Multiple KEY=VALUE pairs in one call are fine. Values are type-coerced the way you'd expect: true/false become real YAML booleans, integers and floats parse as numbers, everything else stays a string.

gald3r providers model add / gald3r providers model remove

gald3r providers model add ollama gemma3:27b --role vision --context-window 32768
Added model 'gemma3:27b' to provider 'ollama' in C:\Users\you\.gald3r\providers.yaml.
gald3r providers model remove ollama gemma3:27b
Removed model 'gemma3:27b' from provider 'ollama' in C:\Users\you\.gald3r\providers.yaml.

model remove matches by either id or alias. --role is a single value (not a list) — the on-disk schema carries exactly one role: per model entry; a model that serves more than one purpose is expected to appear as more than one entry, or you just re-run providers role set to reassign it.

gald3r providers role set

gald3r providers role set vision ollama/qwen3:4b
Set role 'vision' for ollama/qwen3:4b in C:\Users\you\.gald3r\providers.yaml.

The spec is PROVIDER/MODEL, split on the first / only — this matters because LM Studio model ids are themselves filesystem-style paths containing / (e.g. lmstudio/Qwen2.5-Coder-14B-Instruct-GGUF/Qwen2.5-Coder-14B-Instruct-Q4_K_M.gguf), so a naive last-/ split would cut the model id in half.

gald3r providers validate

Schema check, key-presence check, and (unless --no-network) a reachability probe against {base_url}/models for every OpenAI-compatible provider.

gald3r providers validate --no-network
[OK  ] lmstudio
         ok: API key resolved via local
         skip: reachability probe disabled (--no-network)
[OK  ] ollama
         ok: API key resolved via local
         skip: reachability probe disabled (--no-network)
[WARN] openrouter
         warn: api_key references an unset environment variable
         skip: reachability probe disabled (--no-network)
6 provider(s): 2 ok, 4 warn, 0 fail.

Exit code is 1 only if any provider has a fail-level finding (a real schema defect, or no usable key at all for a provider type that requires one). An unreachable local runtime, an unset env var, or a plaintext key are all warnings — informational, not blocking (the runtime may simply not be started right now).

Every network probe is hard-capped at 3 seconds regardless of what --timeout you pass, and --no-network skips reachability checks entirely — validate never hangs waiting on a dead endpoint.

Keys still never leave the keyring path

None of these verbs change how secrets are stored: gald3r providers set-key remains the only way to put a real key in the OS keyring, and nothing here ever prints, logs, or writes a literal secret value — only classification labels like the key column above.

Can I edit providers.yaml while gald3r is already running?

Short answer: usually yes, already, with no extra step.

  • providers.yaml is re-read from disk on every single call that resolves a provider — there is no cache anywhere in the loader. A background autopilot loop or the ACP server's default provider factory both build a fresh registry per call, so an edit (via these verbs or by hand) is visible on the very next call, no restart needed.
  • The one exception is an already-open gald3r chat REPL: it resolves its provider once per session and reuses that client for every turn until you run /model <spec> or start a new session. If you edit providers.yaml while a chat session is open, run /model (or restart) to pick up the change in that session.

See also

  • quickstart.mdgald3r init-providers and the starter providers.yaml this addendum assumes you already have
  • verbs.md — the full verb catalog
  • gald3r providers --help / gald3r providers <subcommand> --help — always the authoritative source for exact flags