Skip to content

1.10.0 — one config file

Choose a tag to compare

@szarkans szarkans released this 04 Sep 16:59
· 4 commits to main since this release
  • One config file: ~/.claude/multi/config.toml. Backends, their models, endpoints, per-backend timeouts and named profiles all live there, with comments; providers.env keeps only keys. Read by scripts/config.py (stdlib tomllib, with a vendored tomli for python < 3.11). No file means the built-in default — codex, opencode, openrouter — and setup.sh init writes it out to edit.
    • Any number of Anthropic-compatible endpoints, each its own backend: [backends.zcode] with type = "claude-headless", its own base_url, models and key variable, next to openrouter instead of replacing it. Before, one endpoint could be pointed away from OpenRouter and that was all.
    • Profiles: [profiles] normal = ["openrouter:x-ai/grok-4.5", "zcode", "codex"], picked with ask.sh --backend normal; no --backend runs default_profile. code-review, check-if-done and ask stop hard-coding a backend list, so the config actually decides who reviews — a knob the skills bypass changes nothing. adhd keeps its fixed two external frames on purpose: its frames are distinct engines, not a reviewer roster.
    • backend:model pins exactly that model with no fallback. Asking for a paid model and silently getting a free one is worse than a marker saying it failed.
    • Per-backend timeout; ask.sh --timeout N is a floor (every backend gets at least N, the review skill passes 2400), never a cut — the same rule codex already had with its 600s.
    • A broken config stops every run before anything launches, naming the file and the key: unknown type, unknown key, a profile naming a backend that does not exist or sharing a backend's name, a claude-headless without models or base_url, a non-https endpoint (plain http only when the parsed host is the loopback), a model name with whitespace, a key variable or backend name that is not a plain identifier, more than one model on codex or gemini — those two do not walk a chain yet, and the config says so instead of ignoring the rest.
  • Removed, not aliased: the models file, MULTI_OPENROUTER_MODEL, MULTI_OPENROUTER_MODELS, MULTI_OPENROUTER_FALLBACKS, MULTI_OPENROUTER_BASE_URL, MULTI_OPENCODE_MODEL, MULTI_GEMINI_MODEL, MULTI_BACKEND_TIMEOUT, MULTI_CODEX_TIMEOUT, MULTI_OPENCODE_STALL, and the --or-model / --gemini-model flags (name:model does it, and a by-type flag picks the wrong backend once two share a type). Reading the old variables "just in case" would be a third config. While providers.env still sets any of them nothing runs: the old MULTI_OPENROUTER_BASE_URL chose where the key goes, and a config that ignored it would send a z.ai key to openrouter.ai. setup.sh init still works in that state, the probe says models-config: LEGACY while the old file exists, and setup.sh set MULTI_* explains where the value went. setup.sh set accepts exactly the key variables the config's backends read.
    • Upgrading: move MULTI_OPENROUTER_* values into [backends.openrouter] (base_url, models) and the models file's list into [backends.opencode]; timeouts become timeout = N per backend. Keys need no change.
  • config.example.toml and providers.example.env in the repo show every backend type, every field, a second endpoint with its own key, and several profiles; a test keeps the example valid.
  • python3 is now required to run anything: bash cannot read TOML. It was already needed to read OpenCode answers.