contenox

OpenCode with local models: Ollama, LM Studio, llama.cpp, vLLM

Updated

TUTORIALS OpenCode with local models

Yes, you can use OpenCode with a local model. Run the model in Ollama, LM Studio, llama.cpp or vLLM, then add it to opencode.json as a custom provider with @ai-sdk/openai-compatible and the server’s /v1 address. With Ollama there’s a shortcut: ollama launch opencode sets it up for you.

What breaks it is almost never the config. It’s the context size: Ollama gives a model only 4k tokens on GPUs under 24 GB, and OpenCode needs 64k.

The config for each runtime

RuntimebaseURLStart it withWhere the context size is set
Ollamahttp://localhost:11434/v1Runs in the background after installOLLAMA_CONTEXT_LENGTH, the app’s slider, or a Modelfile
LM Studiohttp://127.0.0.1:1234/v1lms server start, or Developer → Start serverlms load <model> --context-length 65536
llama.cpphttp://127.0.0.1:9931/v1llama-server-c 65536
vLLMhttp://gpu-host:8000/v1vllm serve with tool-call flags--max-model-len 65536

Every runtime uses the same opencode.json shape. Put it in your project, or in ~/.config/opencode/opencode.json for all projects. Project settings win over global ones; the files are merged, not replaced.

The limit block isn’t optional in practice. OpenCode reads context sizes for hosted models from models.dev, but it knows nothing about your local server. Without limit.context, it can’t tell when the session is full, so automatic compaction can’t kick in at the right time.

Ollama

The quickest way:

ollama pull qwen3-coder:30b
ollama launch opencode

ollama launch opencode passes an inline config for the model you pick and leaves your opencode.json alone. Add --config to set it up without starting a session.

To set it up by hand, add a provider to opencode.json:

{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "ollama": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "Ollama (local)",
      "options": { "baseURL": "http://localhost:11434/v1" },
      "models": {
        "qwen3-coder:30b": {
          "name": "Qwen3 Coder 30B",
          "limit": { "context": 65536, "output": 8192 }
        }
      }
    }
  },
  "model": "ollama/qwen3-coder:30b"
}

The key under models must be the exact Ollama tag, as ollama list shows it. The top-level model is <provider key>/<model key>, so OpenCode starts on it; otherwise pick it with /models.

The launch-picker gotcha: models you define only in opencode.json don’t show up in the ollama launch model picker, and the launcher’s inline config doesn’t add your limit block. Pick one way and stick with it.

Why does OpenCode forget my request with Ollama?

Because Ollama cut the prompt. Its default context depends on your GPU memory:

GPU memoryOllama’s default context
Under 24 GB4k tokens
24 to 48 GB32k tokens
48 GB or more256k tokens

OpenCode’s system prompt and tool definitions alone take a large share of 4k. When the prompt doesn’t fit, Ollama drops part of it without an error. The model then answers without your instructions or without the tool list, and it looks like the model is stupid.

The num_ctx trap: OpenCode’s providers page says to raise num_ctx if tool calls fail. But OpenCode talks to Ollama’s OpenAI-compatible endpoint, and Ollama’s docs say that API has no way to set the context size. Putting num_ctx in opencode.json does nothing. Set it on the Ollama side instead, one of three ways:

  1. The Ollama app: move the context length slider in Settings to 64k or more.

  2. The server setting, for every model. On Windows, quit Ollama from the system tray, then in PowerShell:

    setx OLLAMA_CONTEXT_LENGTH 65536

    Start Ollama again from the Start menu. On macOS or Linux:

    OLLAMA_CONTEXT_LENGTH=65536 ollama serve
  3. A Modelfile, for one model. Create a file named Modelfile:

    FROM qwen3-coder:30b
    PARAMETER num_ctx 65536

    Then build a new name and use that name as the model key in opencode.json:

    ollama create qwen3-coder-64k -f Modelfile

OpenCode’s docs suggest starting at 16k to 32k; Ollama’s OpenCode page says OpenCode needs 64k or more. Go with 64k. A long session in a real repo passes 32k quickly.

Then check it worked. Send one message in OpenCode and run:

ollama ps

CONTEXT should show the size you set, and PROCESSOR should say 100% GPU. If part of it runs on the CPU, the model plus its context doesn’t fit in GPU memory, and every turn gets slow. Use a smaller model, a shorter context, or a quantized KV cache (OLLAMA_KV_CACHE_TYPE=q8_0 halves its memory, per Ollama’s FAQ). The KV cache guide explains why context costs memory.

Keep limit.context in opencode.json equal to what you set in Ollama. If OpenCode thinks it has 256k but Ollama gives it 64k, compaction starts too late and Ollama trims the prompt first.

LM Studio

Load the model with a context size, then start the server:

lms load qwen/qwen3-coder-30b --context-length 65536
lms server start

The model key is whatever LM Studio shows for your download; lms ls lists them. Then in opencode.json:

{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "lmstudio": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "LM Studio (local)",
      "options": { "baseURL": "http://127.0.0.1:1234/v1" },
      "models": {
        "qwen/qwen3-coder-30b": {
          "name": "Qwen3 Coder 30B (LM Studio)",
          "limit": { "context": 65536, "output": 8192 }
        }
      }
    }
  }
}

If you load models from the LM Studio window instead, set the context length in the load settings there. The same trap applies: the model gets only what you set at load time.

llama.cpp

llama-server can download a GGUF from Hugging Face and serve it. The -hf flag picks the Q4_K_M file by default:

llama-server -hf unsloth/Qwen3-Coder-30B-A3B-Instruct-GGUF -c 65536 --alias qwen3-coder

--alias gives the model a short name for the API. Tool calls work through the model’s chat template; llama.cpp’s Jinja template engine is on by default, so you don’t need extra flags for most models.

{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "llama.cpp": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "llama-server (local)",
      "options": { "baseURL": "http://127.0.0.1:9931/v1" },
      "models": {
        "qwen3-coder": {
          "name": "Qwen3 Coder 30B (llama.cpp)",
          "limit": { "context": 65536, "output": 8192 }
        }
      }
    }
  }
}

The port gotcha: current llama-server listens on port 9931 by default. OpenCode’s docs and many older guides use 8080, which was the old default. If you get “connection refused”, either change baseURL or start the server with --port 8080.

vLLM, on your own or a rented GPU

“Local” doesn’t have to mean your laptop. A GPU you rent by the hour runs vLLM the same way, and your code still goes only to a machine you control. Start vLLM with tool calls on, or the agent can’t act:

vllm serve Qwen/Qwen3-Coder-30B-A3B-Instruct \
  --served-model-name qwen3-coder \
  --enable-auto-tool-choice \
  --tool-call-parser qwen3_xml \
  --max-model-len 65536 \
  --api-key YOUR_KEY
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "vllm": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "vLLM",
      "options": {
        "baseURL": "http://gpu-host:8000/v1",
        "apiKey": "{env:VLLM_API_KEY}"
      },
      "models": {
        "qwen3-coder": {
          "name": "Qwen3 Coder (vLLM)",
          "limit": { "context": 65536, "output": 8192 }
        }
      }
    }
  }
}

Set limit.context to the --max-model-len you started with. The parser per model family, and the errors you’ll meet, are on the vLLM page.

Ollama Cloud, when the model doesn’t fit

If your GPU can’t run a model good enough for agent work, Ollama Cloud runs bigger open models on Ollama’s servers. Your code then leaves your machine. In OpenCode:

  1. Create a key at ollama.com/settings/keys.
  2. Run /connect, search for Ollama Cloud and paste the key.
  3. Pull the cloud model’s stub once: ollama pull gpt-oss:20b-cloud
  4. Pick it with /models.

Or skip the key: ollama launch opencode --model kimi-k2.7-code:cloud runs through your signed-in local Ollama. Cloud models get their full context length, so the 4k trap doesn’t apply. Plans and limits are on Ollama’s pricing page. Which cloud and local models are worth it: best Ollama models for coding.

Does my local model support tool calls?

OpenCode reads files, edits code and runs commands through tool calls. A model without them can chat but can’t do anything.

  • Ollama: look for the tools tag on the model page, or filter the library to tools. Older coding models such as deepseek-coder and codellama don’t have it.
  • LM Studio and llama.cpp: tool calls depend on the model’s chat template. LM Studio’s model page lists “Trained for tool use” under capabilities; for llama.cpp, check the model card.
  • vLLM: off until you pass --enable-auto-tool-choice and the right --tool-call-parser.

A quick test: in a new session, ask “list the files in this folder”. A working setup calls a tool and shows the result. A broken one prints a JSON blob, or a made-up file list.

OpenCode not working with Ollama: the fixes

  • It ignores your request, forgets tools or loops: the context is too small. Raise it on the Ollama side as above, and check CONTEXT in ollama ps.
  • “does not support tools”: the model has no tool support in Ollama. Switch to a model tagged tools.
  • It prints tool calls as text instead of running them: the model’s tool-call output didn’t parse. This has been reported with Gemma 4 in OpenCode issue 20995; the reporter switched to qwen3.5:9b. Update both Ollama and OpenCode first, then try another model.
  • “model not found”: the key under models doesn’t match the Ollama tag. Copy it from ollama list, including the part after the colon.
  • Connection refused: Ollama isn’t running, or baseURL is missing /v1. Test it with curl http://localhost:11434/v1/models.
  • Your local models don’t appear in /models: OpenCode doesn’t list them until they’re in a provider block. Add the block above, or use ollama launch opencode.
  • Every answer takes minutes: ollama ps shows a CPU share. The model and context don’t fit in GPU memory.
  • Ollama runs on another machine: it listens only on 127.0.0.1 by default. Set OLLAMA_HOST to 0.0.0.0:11434 on that machine, restart Ollama, and use its address in baseURL. Anyone on that network can then use it.

Claude Code and Codex with Ollama

The same Ollama server works for the other two big agents. The context rule is the same: 64k or more.

Claude Code talks to Ollama’s Anthropic-compatible API:

ollama launch claude --model qwen3-coder:30b

By hand, in PowerShell:

$env:ANTHROPIC_AUTH_TOKEN = "ollama"
$env:ANTHROPIC_API_KEY = ""
$env:ANTHROPIC_BASE_URL = "http://localhost:11434"
claude --model qwen3-coder:30b

On macOS or Linux, use export with the same three variables. The settings gotcha: a base URL or key in Claude Code’s settings files overrides your shell variables. If it still talks to Anthropic, run /status and fix the settings file. Anthropic doesn’t support Claude Code with non-Claude models, and Ollama’s Anthropic API lacks prompt caching, token counting and tool_choice, so some features won’t work.

Codex CLI uses Ollama’s Responses API:

ollama launch codex

Or codex --oss -m qwen3-coder:30b. --oss covers Ollama and LM Studio; set oss_provider = "ollama" in ~/.codex/config.toml so it stops asking which one. ollama launch codex --restore removes the profile the launcher created.

The full setup for all three agents is on the Ollama page. Which of them suits small local models best: best Ollama harness.

Contenox

If you’d rather not edit JSON per runtime: in the Contenox desktop app, open Backends → Providers, choose Ollama / Ollama Cloud, keep http://127.0.0.1:11434 and select Connect. Your pulled models appear in the Model chip next to any hosted providers, so you can switch per session, and Token Limit sets the session’s context budget. vLLM and other OpenAI-compatible servers connect the same way. Download Contenox.

Related

Esc to close