Running a Local AI Coding Agent with Ollama, Cline, and Claude Code
How I connected a local Ollama model to Cline and Claude Code to handle routine coding tasks without burning Claude API credits.
June 22, 2026
Running Claude Code for every task gets expensive fast. Local models have gotten good enough to handle most of it.
This post covers how I connected a local Ollama model to both Cline and Claude Code so each tool can delegate routine work to it.
Part 1 sets up Cline in VS Code pointing at a local Ollama model. Part 2 adds an MCP server so Claude Code can delegate to it too. Local models have gotten good enough to handle real coding tasks. Running one costs nothing per token. Use it for the routine work and reach for the Claude API when the task actually needs it. Less spend, same output.
Prerequisites
I'm on a MacBook Pro (M4 Pro, 24GB, macOS Sequoia 15.7.7).
Commands use $HOME instead of a hardcoded username. It maps to your home directory automatically. Confirm with echo $HOME.
- Ollama installed and running
- Cline installed in VS Code (search "Cline" in Extensions, install the one by Cline Bot Inc.)
- Claude Code CLI installed
- Python 3.12+
Part 1 — Cline + Local Ollama
Cline is an open-source coding agent for VS Code. It reads files, runs commands, and iterates on the output. Not just autocomplete. It also has a native Ollama provider, which means it connects to the local model directly rather than through a generic adapter. That matters for context window control, which is what Step 2 covers.
Step 1 — Clone the repo and pull the model
Clone the local-llm-mcp repo first. Everything in Part 1 and Part 2 lives here. $HOME/dev/local-llm-mcp is the path used throughout. Change it to wherever you keep projects and update CLAUDE.md in Part 2 Step 2 to match:
git clone https://github.com/danphillips-cloud/local-llm-mcp.git $HOME/dev/local-llm-mcp
cd $HOME/dev/local-llm-mcp
Pull your model. I'm using qwen3-coder:30b-a3b-q4_K_M but any Ollama model works:
ollama pull qwen3-coder:30b-a3b-q4_K_M
Run ollama list and copy the exact name from the NAME column, tag included. The tag matters. qwen3-coder:30b-a3b-q4_K_M and qwen3-coder are different entries. A mismatched tag is the most common reason a model silently fails to load.
Step 2 — Bump the context window to 16k
A Modelfile is the blueprint Ollama uses to build and configure a model variant. The repo includes one already. It points at qwen3-coder:30b-a3b-q4_K_M and sets num_ctx to 16384. If you're using a different model, open Modelfile and update the FROM line before running the next command.
Ollama's default context window is 2048 tokens. That's not enough for real coding tasks. File content gets truncated and the model loses earlier context mid-task. 16384 covers most real files and is well within what 24GB handles at 30B Q4.
Run this to build the model variant:
ollama create qwen3-coder-16k -f Modelfile
This builds qwen3-coder-16k:latest as a new layer on top of the existing weights. No re-download. From here on, Cline and the MCP server both use this model.
On 16GB unified memory, a 30B Q4 model likely won't load at all. The weights alone need around 16-18GB before macOS overhead. Dropping num_ctx won't help if the model can't fit in RAM. The qwen3-coder family only comes in 30B and 480B, so 16GB users need a different model family. qwen2.5-coder:14b is a solid alternative. Update the FROM line in the Modelfile and OLLAMA_MODEL in .env to match.
Step 3 — Configure Cline
Open VS Code and click the Cline icon in the left sidebar. Click the settings icon (⚙️) in the top right of the Cline panel to open API Configuration.
Cline supports cloud providers (Anthropic, OpenAI, OpenRouter) and local models via Ollama or LM Studio. This guide uses Ollama. Fill in the fields below.
| Field | Value |
|---|---|
| API Provider | Ollama |
| Use custom base URL | checked (set to http://localhost:11434) |
| Ollama API Key | leave empty |
| Model | qwen3-coder-16k:latest |
| Model Context Window | 16384 |
| Request Timeout (ms) | 120000 |
The default 30-second timeout isn't enough for a 30B model on a real task. Set it to 120000.
Click Done to return to the main Cline view.
Warnings after selecting Ollama: You may see "Does not support MCP and Focus Chain" and "Less capable models may not...". Both are safe to ignore. The first is about Cline's internal features, not Part 2's MCP server. The second is a blanket disclaimer for any non-Claude model.
One thing that trips people up: leave the Context Window field empty and Cline silently defaults to 32768, overriding the value you set in the Modelfile. Always set it explicitly to match.
Note: Cline's UI and configuration options change frequently. If these steps look different, check the Cline docs for the latest setup instructions.
Step 4 — Verify Cline reads file context
The repo includes utils.py with a slugify function. I'm using it to confirm Cline is reading actual code, not just answering prompts. In your own project, swap in any file.
Click utils.py in the Explorer to open it. In the Cline panel you'll see "What can I do for you?" with a "Type your task here..." input at the bottom.
Add the file as context by typing @ and selecting utils.py from the list, or clicking the + icon in the bottom bar. Then type:
@utils.py Write a failing pytest test for the `slugify` function that
checks it strips leading and trailing whitespace before slugifying.
In your own project, this prompt structure works for any function: @yourfile.py Write a failing test for [function name] that checks [behaviour].
Note: Make sure Act is selected in the bottom bar, not Plan. Plan mode only describes what Cline would do. Act mode actually does it.
Hit send. Cline reads the file first to understand the current implementation before writing anything.
Then it checks the environment. If pytest isn't installed, it asks for approval before running anything.
Click Resume Task. Cline installs pytest, writes the tests, and runs them.
It didn't just write the test. It spotted that the original implementation was incomplete and fixed it. That's the part I didn't expect.
If the output references functions or imports that don't exist in your file, Cline isn't reading it. Make sure you added it via @ or + and that the context window is large enough (Step 2).
Part 2 — Claude Code MCP Server
Part 1 got Cline talking to the local model directly. Part 2 lets Claude Code do the same thing. The difference is Claude Code stays in control. It decides when to call the local model, reviews the output, and integrates it into the broader task.
Key difference: The local model never sees the full conversation. It only gets the specific file and instruction passed to it.
The server has three tools:
| Tool | What it does |
|---|---|
generate_code |
Write new functions, classes, or files from a description |
write_tests |
Generate tests for a specific function or method |
refactor |
Targeted rewrites: extract, rename, simplify, add types |
Step 1 — Set up the Python environment
The repo is already cloned from Part 1. Set up the venv:
cd $HOME/dev/local-llm-mcp
python3.12 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
Package note:
requirements.txtpins two packages:mcp>=1.2.0(Anthropic's Python SDK, which bundles FastMCP) andhttpx>=0.27.0for async HTTP to Ollama. There's a separatefastmcppackage that uses a different import path. Don't mix the two.
Step 2 — Check CLAUDE.md
CLAUDE.md is the file Claude Code reads at the start of every session. It's already in the repo. If you cloned to a different path, update the paths inside.
Step 3 — Configure the model
The repo includes .env.example. Duplicate it in VS Code and rename the copy to .env. The defaults work as-is. The server calls Ollama's /api/chat endpoint and passes num_ctx on every request:
OLLAMA_HOST=http://localhost:11434
OLLAMA_MODEL=qwen3-coder:30b-a3b-q4_K_M
OLLAMA_NUM_CTX=16384
OLLAMA_TIMEOUT=120
To swap models, change OLLAMA_MODEL and restart the Claude Code session. No code changes needed.
Step 4 — Register with Claude Code
Run this once. It writes the server into your user-global config so it's available in every Claude Code session. (Claude Code MCP docs)
First confirm the venv Python exists. If it's missing, the command registers a broken path with no warning:
ls $HOME/dev/local-llm-mcp/.venv/bin/python
Then register:
claude mcp add --transport stdio ollama-coder \
--scope user \
-- $HOME/dev/local-llm-mcp/.venv/bin/python \
$HOME/dev/local-llm-mcp/server.py
Claude Code stores the expanded path, so the output will show /Users/yourname/... rather than $HOME. That's expected.
Successful registration:
Added stdio MCP server ollama-coder to user config
File modified: /Users/yourname/.claude.json
Claude Code stores MCP servers in ~/.claude.json. Not ~/.claude/mcp.json. Not ~/.claude/settings.json. Some older guides get this wrong. The official MCP docs have the correct scope table.
If you rename or move the local-llm-mcp directory, re-run the claude mcp add command. The path in ~/.claude.json won't update automatically.
Verify registration with claude mcp list, then open a Claude Code session and run /mcp to confirm it's connected:
VS Code popup: opening the repo in VS Code may trigger a notification about
.envterminal injection being disabled. Dismiss it. The server reads.envdirectly at startup.
Step 5 — Set up auto-start on Mac (launchd)
The MCP server starts on-demand when Claude Code needs it. What has to be running is ollama serve, and ideally the model is already loaded. Cold-loading a 30B model can take long enough to hit the timeout on the first call.
A launchd agent handles both at login. Per-user agents live in ~/Library/LaunchAgents/.
First, confirm where Ollama is installed:
which ollama
On Apple Silicon it's /opt/homebrew/bin/ollama. On Intel it's /usr/local/bin/ollama. The plist in the repo is already set for Apple Silicon. If you're on Intel, open $HOME/dev/local-llm-mcp/launchd/com.local.ollama-warmup.plist and update both path references.
Install and load the agent:
cp $HOME/dev/local-llm-mcp/launchd/com.local.ollama-warmup.plist \
~/Library/LaunchAgents/
launchctl load ~/Library/LaunchAgents/com.local.ollama-warmup.plist
Verify:
launchctl list | grep ollama-warmup
A working result:
15611 0 com.local.ollama-warmup
The PID will differ. 0 means the agent ran without errors. A - means it hasn't run yet and will at next login. Non-zero means something failed: check /tmp/ollama-warmup.err.log. Common causes are a wrong Ollama path (re-run which ollama) or incorrect line endings if the plist was edited on Windows.
To remove:
launchctl unload ~/Library/LaunchAgents/com.local.ollama-warmup.plist
rm ~/Library/LaunchAgents/com.local.ollama-warmup.plist
Step 6 — Test from a Claude Code session
utils.py from Part 1 is still in the repo. This time Claude Code reads the file and passes it to the local model via the MCP server. Swap in your own file and function for real project work.
Start a Claude Code session:
cd $HOME/dev/local-llm-mcp
claude
Then:
Use the ollama-coder write_tests tool to generate a pytest test for the
`slugify` function in utils.py.
The same structure works for the other tools:
Use the ollama-coder generate_code tool to write a Python function that
[description] in [filename].
Use the ollama-coder refactor tool to [specific change] in [filename].
Claude Code read the file, called the local tool, got the output, and flagged an edge case to revisit. No API call for the test generation itself. Point it at any function in any project and the same flow applies.
If something goes wrong, the server returns specific error messages:
Could not reach Ollama:ollama serveisn't runningCheck that model exists: runollama listand fixOLLAMA_MODELin.envtimed out after 120s: model is cold-loading. Check/tmp/ollama-warmup.out.logor runollama run qwen3-coder:30b-a3b-q4_K_M ""manually to pre-load it.
Troubleshooting
Cline shows empty responses
Context window is too small for the file. Confirm qwen3-coder-16k is selected and Context Window is set to 16384.
ollama list doesn't show qwen3-coder-16k
The ollama create step didn't run or failed. Re-run Part 1 Step 2. The base model has to be present first.
MCP tools don't appear in /mcp
If Claude Code opens with "1 setup issue: MCP", run /doctor. It identifies the cause and walks you through fixing it. Stale paths in ~/.claude.json are the most common culprit.
Otherwise, run claude mcp list first. If it shows disconnected, run the server manually to see the error:
$HOME/dev/local-llm-mcp/.venv/bin/python $HOME/dev/local-llm-mcp/server.py
First tool call times out
The model is still loading. Check /tmp/ollama-warmup.out.log, or run ollama run qwen3-coder:30b-a3b-q4_K_M "" to pre-load it manually.