Observed since 20 Oct, 23:05 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
OpenCode plugin that adds a 'local' provider with auto-detection for Ollama, LMStudio, llama.cpp, vLLM, Exo, llama-swap, oMLX, MLX-VLM, and other OpenAI-compatible servers, with optional per-server API keys
Fork of goniz/opencode-local-provider, published as
@0xdon0/opencode-local-provider. It adds optional per-server API keys, adding servers from/connect, listing every llama-swap model, and a fallback for any OpenAI-compatible server. Don't install it alongside the original package.
OpenCode plugin that adds a single local provider with runtime model detection for local OpenAI-compatible servers.
It currently supports the following local backends:
/v1/models endpoint (openai, used when nothing more specific matches)Instead of creating one provider per server, this plugin keeps one local provider and lets you register multiple named targets. Each target is probed at runtime, and its models are exposed automatically.
local provider to OpenCode127.0.0.1 targets automaticallyAuthorization: Bearer <key>https://github.com/user-attachments/assets/8693fd22-c311-4cb4-913b-93d5a531b23c
opencode plugin --global @0xdon0/opencode-local-provider
On OpenCode v2:
opencode plugin add @0xdon0/opencode-local-provider
OpenCode will install the package and update the config for you. Upgrading from v1? See Migrating from v1 to v2.
Default targets are enabled automatically for these backends and ports:
http://127.0.0.1:11434http://127.0.0.1:1234http://127.0.0.1:8080http://127.0.0.1:8000http://127.0.0.1:52415http://127.0.0.1:8080http://127.0.0.1:8000http://127.0.0.1:8080If your local servers run on these ports and do not need an API key, you can start using the local provider immediately.
Note: oMLX with API authentication enabled needs a custom target with its API key set (see below).
Add a server on another host or port, or one that needs an API key, with Add Custom Target. Run it from the TUI with /connect → Local LLM Provider, or from the CLI:
opencode auth login --provider local --method "Add Custom Target"
It asks for:
studio or remote-ollama/v1{env:VAR_NAME} to store a reference to an environment variable instead of the key itselfThe plugin checks that the server answers before it saves anything, then adds the target to your OpenCode global config. Run it again to add more servers.
/connect only lists Local LLM Provider once the provider has at least one model. If none of your servers are reachable yet, add the first target from the CLI.
You can also add targets manually in config:
{
"provider": {
"local": {
"options": {
"includeDefaults": true,
"targets": {
"studio": {
"url": "http://192.168.1.10:1234/v1",
"kind": "lmstudio"
},
"swap": {
"url": "https://llama-swap.example.com/v1",
"kind": "llamaswap",
"apiKey": "{env:LLAMA_SWAP_API_KEY}",
"includeUnloaded": true
}
}
}
}
}
}
Target fields:
url (required): the server URLkind (optional): one of ollama, lmstudio, llamacpp, vllm, exo, llamaswap, omlx, mlxvlm, openai. If you leave it out, the backend is detected. openai treats any server as a plain OpenAI-compatible endpointapiKey (optional): sent as Authorization: Bearer <key> when probing the server and with every chat request to its models. Use {env:VAR_NAME} to keep the key out of the config fileincludeUnloaded (optional, llama-swap only): list every model llama-swap offers, not only the loaded ones. The plugin reads their details from /v1/models and does not load themExplicit targets override the built-in defaults when they use the same ID. A key set in provider.local.options.apiKey applies to every target that has no apiKey of its own.
With includeDefaults: true, the built-in default 127.0.0.1 targets are also checked at runtime even though they are not written into config. Set it to false if you only use custom targets.
The same package works with OpenCode v2. Setup differs in a few places:
Adding a server: run /connect → Local LLM Servers → Add Custom Target. It asks the same questions and checks the server the same way. Each target is saved as one of that integration's connections, with its API key kept in OpenCode's credential store, so you remove a target by removing its connection there.
Config targets: v2 has no provider.local.options. Put targets, includeDefaults and a shared apiKey in the plugin's own entry instead:
{
"plugins": [
{
"package": "@0xdon0/opencode-local-provider",
"options": {
"includeDefaults": true,
"targets": {
"studio": { "url": "http://192.168.1.10:1234/v1", "kind": "lmstudio" }
}
}
}
]
}
Refreshing: the plugin probes again every minute and whenever a target is added or removed, so you don't need to restart OpenCode to see newly loaded models. Remembered llama-swap context sizes are kept in the plugin's own storage instead of ~/.cache.
Model overrides: they go under providers.local.models (note providers), keyed by <target>/<model>, and use v2's model fields. OpenCode applies them on top of what the plugin detected:
{
"providers": {
"local": {
"models": {
"swap/qwen3.6-35b-a3b": {
"name": "Qwen 3.6 (swap)",
"limit": { "context": 262144, "output": 32000 },
"capabilities": { "tools": true, "input": ["text", "image"] }
}
}
}
}
}
Useful fields are name, limit (context, input, output), capabilities (tools, input, output), variants and disabled. The v1 fields modalities, tool_call and attachment don't exist in v2.
Each target's key comes from its own config entry or /connect connection. A key saved for the local provider itself is ignored.
v2 doesn't read v1's plugin or provider config keys, so after upgrading the local provider shows no models until you move your settings. Your old config stays in the file; v2 just ignores it.
plugin to plugins and turn the plugin's entry into an object.provider.local.options (targets, includeDefaults, apiKey) into that entry's options.provider.local.models to providers.local.models and switch them to v2's fields (see above).v1:
{
"plugin": ["@0xdon0/opencode-local-provider"],
"provider": {
"local": {
"options": {
"targets": {
"swap": {
"url": "https://llama-swap.example.com/v1",
"kind": "llamaswap",
"apiKey": "{env:LLAMA_SWAP_API_KEY}",
"includeUnloaded": true
}
}
}
}
}
}
v2:
{
"plugins": [
{
"package": "@0xdon0/opencode-local-provider",
"options": {
"targets": {
"swap": {
"url": "https://llama-swap.example.com/v1",
"kind": "llamaswap",
"apiKey": "{env:LLAMA_SWAP_API_KEY}",
"includeUnloaded": true
}
}
}
}
]
}
Instead of editing config, you can also add each server again with /connect → Local LLM Servers → Add Custom Target.
If chats fail with Missing auth credential: apiKey, update the plugin to 0.3.1 or later. v1's Add Custom Target saved an empty key for the local provider, v2 copies it over on upgrade, and earlier versions of the plugin let it replace every target's key.
Models are discovered dynamically from each configured target. By default, only loaded models are listed.
To avoid collisions, model IDs are prefixed with the target ID:
ollama/llama3.2studio/qwen2.5-coderEach generated model keeps its own target URL and API key internally, so requests go to the correct backend.
Models that don't chat in text, such as speech-to-text, rerankers, or embeddings, are skipped when the server's listing says so.
OpenCode compacts a conversation once it nears the model's context size, so each model needs the right one. The plugin uses the first of these that it finds:
/v1/models listing (context_length, context_window, max_model_len or meta.n_ctx)~/.cache/opencode-local-provider/models.jsonThe output limit is a quarter of the context, capped at 32,000 tokens. Sizes are read when OpenCode starts, so restart it to pick up changes.
llama-swap only reports a model's context size while the model is loaded. To advertise every model's size, the server admin can add a capabilities block to each model in the llama-swap config (v225 or later). The listing then includes the context size, tool support and input types:
models:
qwen3.6-35b-a3b:
cmd: llama-server --port ${PORT} -m /models/Qwen3.6-35B-A3B.gguf --mmproj /models/mmproj.gguf -c 262144
capabilities:
context: 262144 # the -c value from cmd
tools: true
in: [text, image] # image only when cmd loads an --mmproj
out: [text]
whisper:
cmd: whisper-server --port ${PORT} -m /models/ggml-large-v3.bin
capabilities:
in: [audio] # not a chat model, so the plugin skips it
out: [text]
Set context to the -c value in cmd. Without -c, llama-server chooses the size when it loads the model, and may reduce it to fit in memory.
Settings under provider.local.models, keyed by <target>/<model>, replace what the plugin detected (v1 format; for v2 see OpenCode v2):
{
"provider": {
"local": {
"models": {
"swap/qwen3.6-35b-a3b": {
"limit": { "context": 262144, "output": 32000 },
"modalities": { "input": ["text", "image"] }
}
}
}
}
}
This works for any OpenCode model field, such as name, limit, modalities, attachment, tool_call, reasoning, options or variants. OpenCode requires both context and output when limit is set.
127.0.0.1 targets are enabled unless you set includeDefaults to falseHTTP 401 for a wrong key) is written to the OpenCode logBuild the plugin:
bun run build
Run the provider integration suite:
bun run test:providers
Run a single provider suite:
PROVIDER_SUITE=ollama bun run test:providers
Notes:
ollama, lmstudio, llamacpp, vllm, exo, llamaswap, omlx, and mlxvlm from tests/docker/compose.providers.yml..github/workflows/provider-tests.yml.tests/docker/compose.providers.yml and the Bun orchestration helpers in tests/docker/ instead of duplicating those details here.Install it locally in OpenCode with a file path plugin entry, for example:
opencode plugin $PWD
MIT
Download counts and popularity will appear here as the collector receives them.
This describes our collected data; it is not a security assessment.
Shared repository data · GitHub
Observed since 20 Oct, 23:05 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:25184e30270c3bfef2fa8127bb04323be951ff79415e5695d354fed9bda6b8cc