Skip to main content

Sync opencode config with models served by a vLLM/llama.cpp server

Project description

opencode-sync

Keep opencode's model list in sync with your local vLLM or llama.cpp server.

When you swap models on your inference server, opencode-sync queries /v1/models and updates opencode.jsonc in place. Run it once manually, or install the shell wrapper so it happens automatically every time you start opencode.

It edits only the model list of the providers it syncs. Your comments, formatting, and every other setting in the file are left byte-for-byte alone.

Requirements

  • Python 3.8+
  • No runtime dependencies (pure stdlib)

Install

pip install opencode-sync

Or from source:

git clone https://github.com/ozskywalker/opencode-sync
cd opencode-sync
pip install -e .

Usage

Sync against the URL already in your config (never changes the stored URL — safe to run any time):

opencode-sync

Point at a specific server and update the stored URL:

opencode-sync --host llm-server.local --port 8080

Preview changes without writing anything:

opencode-sync --dry-run

Auto-sync on every opencode launch

Install a shell wrapper once:

opencode-sync install

This writes ~/.local/bin/opencode — a small script that runs opencode-sync silently, then execs the real opencode binary. opencode always starts with a fresh model list, and still launches normally if the inference server is unreachable.

Make sure ~/.local/bin is earlier in your $PATH than the real opencode binary. The installer warns you if it isn't.

opencode-sync install [--wrapper PATH] [--opencode-bin PATH] [--force] [--dry-run]

How it works

On each run, opencode-sync:

  1. Works out which providers to sync (see Which providers get synced)
  2. Fetches each one's live model list from GET /v1/models
  3. Rebuilds that provider's models — surviving IDs keep their entry exactly as you wrote it; new IDs get a generated name from the model ID
  4. If model or small_model points at this provider and its model is gone, repoints it to the first available one
  5. Rewrites only those parts of the file

The model/small_model fields are written in opencode's expected provider/model-id format (e.g. vllm/org/model-name), so opencode resolves them correctly.

What it won't touch

Everything outside the model lists it syncs. Concretely:

  • Comments and formatting. The file is edited by splicing text, not by re-serializing it, so your // notes, indentation, and blank lines survive exactly.
  • Other providers. Syncing one provider never modifies another — including model/small_model when they point somewhere else.
  • Everything else. $schema, agent, mcp, keybinds, and any other key stay byte-identical.
  • The file itself, when nothing changed. A no-op sync doesn't rewrite it at all.

Before writing, it re-parses the result and checks it means exactly what was intended. If that check fails it writes nothing and tells you — it never falls back to reformatting your file. Writes are atomic (temp file + rename), and a .bak is kept whenever content actually changes.

Which providers get synced

Invocation Providers synced
opencode-sync Every provider with a baseURL, each against its own URL
opencode-sync --provider ID Just ID
opencode-sync --host X The one matching http://X:8080/v1

With no arguments it syncs everything, which is what the wrapper does. If one server is down, the others still sync; the exit code is non-zero only if every one failed. A server that's up but serving no models is skipped — your model list is never wiped because an inference server was mid-restart.

When a server renames a model

If a server starts reporting a different ID for what is really the same model, a naive sync would drop your old entry and everything you'd tuned on it. So:

opencode-sync --provider vllm --rename aeon=qwen3.5-122B-A10B

This moves the entry — display name, context limits, sampling options, comments and all — to the new ID.

A sync that removes exactly one model and adds exactly one is assumed to be a rename, but only when the old entry has settings worth keeping. It'll tell you when it does this:

~ Renamed: aeon -> qwen3.5-122B-A10B (kept limit, options, reasoning, temperature, tool_call)

That's a guess, and a genuine model swap would inherit the wrong settings — use --no-infer-renames to turn it off and drop the old entry instead.

URL behaviour

Invocation Server queried baseURL in config
opencode-sync Existing baseURL (fallback: localhost:8080) Unchanged
LLAMA_ARG_HOST=X opencode-sync http://X:8080/v1 Updated
LLAMA_ARG_HOST=X LLAMA_ARG_PORT=9000 opencode-sync http://X:9000/v1 Updated
opencode-sync --host X http://X:8080/v1 Updated
opencode-sync --host X --no-url-update http://X:8080/v1 Unchanged

CLI --host/--port values override LLAMA_ARG_HOST/LLAMA_ARG_PORT.

Your customisations are preserved

Anything you've written on a model entry survives a sync, as long as the server still reports that model ID:

"models": {
  "org/Qwen3-27B": {
    "name": "My Qwen label",       // kept
    "limit": { "context": 229376 }, // kept
    // Even this comment is kept.
    "options": { "temperature": 0.6 }
  }
}

All options

opencode-sync [--host HOST] [--port PORT] [--provider ID] [--config PATH]
              [--rename OLD=NEW] [--no-infer-renames] [--dry-run]
              [--no-url-update] [--no-model-update] [--timeout SECONDS]
Flag Default Description
--host HOST env, config, else localhost vLLM server hostname
--port PORT env, config, else 8080 vLLM server port
--provider ID all providers Provider key to update
--config PATH auto-detect Path to opencode.jsonc
--rename OLD=NEW Move a model entry to a new ID, keeping its settings (repeatable)
--no-infer-renames off Don't treat a 1-in/1-out sync as a rename; drop the old entry
--dry-run off Print a diff of the planned changes without writing
--no-url-update off Don't update baseURL even when --host/--port is given
--no-model-update off Don't update model/small_model if the active model is removed
--timeout SECONDS 10 HTTP request timeout

Config file locations

opencode uses xdg-basedir on every platform, so the search order is the same everywhere:

  1. $XDG_CONFIG_HOME/opencode/opencode.jsonc (if XDG_CONFIG_HOME is set)
  2. ~/.config/opencode/opencode.jsonc

Override with --config PATH.

Development

pip install -e ".[dev]"
python -m pytest                      # 205 tests
python -m pytest --cov=opencode_sync  # with coverage

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

opencode_sync-0.4.0.tar.gz (43.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

opencode_sync-0.4.0-py3-none-any.whl (24.2 kB view details)

Uploaded Python 3

File details

Details for the file opencode_sync-0.4.0.tar.gz.

File metadata

  • Download URL: opencode_sync-0.4.0.tar.gz
  • Upload date:
  • Size: 43.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for opencode_sync-0.4.0.tar.gz
Algorithm Hash digest
SHA256 9d862a37767f23f7d41cca0dc48375416310c8bc0090b460146b6719bc1be894
MD5 1e19638c3da80d6c50cbeecacc16d72d
BLAKE2b-256 5fb39f0e22e8e038148c4681a001003490a209896329c3d2b149f5d7516fd8cc

See more details on using hashes here.

Provenance

The following attestation bundles were made for opencode_sync-0.4.0.tar.gz:

Publisher: release.yml on ozskywalker/opencode-sync

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file opencode_sync-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: opencode_sync-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 24.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for opencode_sync-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a0cdcda3670e216d123f1988c96e182629a01c882d5937b0a21e3bf0d106d2ca
MD5 9c83cf27ae28824c10352e3e68239deb
BLAKE2b-256 b31a83000433950d571c50b8176b1819dbd216db4118dd842003d3bba84737c2

See more details on using hashes here.

Provenance

The following attestation bundles were made for opencode_sync-0.4.0-py3-none-any.whl:

Publisher: release.yml on ozskywalker/opencode-sync

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page