Appendix D — Reference
Claude Code with Open Source & Local Models
Run Claude Code against Ollama, LM Studio, and any OpenAI-compatible endpoint. Full privacy, no API costs, no internet required.
Why Use Local or Open Source Models?
Before: You're a chef who only has access to one gourmet kitchen in Paris — incredible food, but expensive to rent and you need a passport every time.
Pain: Sometimes you just need to test a new recipe at midnight, want complete control over your ingredients, or have a client with a strict "no cloud" policy.
Mapping: Running Claude Code against a local model is like having a fully-equipped kitchen at home. The output might not be Michelin-star quality every time, but it's available 24/7, costs nothing per use, and no one outside your house ever sees what you're cooking.
There are three compelling reasons to connect Claude Code to a model other than the Anthropic-hosted Claude:
- Cost control — Development and experimentation loops can burn through tokens fast. Running a local model for the "inner loop" (small edits, formatting, boilerplate) and reserving the real Claude for final review cuts API costs by 80–95% in practice.
- Data privacy — Healthcare, financial services, and government projects often have hard requirements: code and data must never leave the local machine or the private network. Local models satisfy those requirements without any waivers.
- Offline and air-gapped environments — Planes, submarines, secure facilities, or simply a flaky hotel Wi-Fi connection. Once the model weights are downloaded, the whole workflow runs without internet.
Local open source models are powerful, but they are not Claude. At the time of writing, even the best 70B parameter models running locally lag behind Claude Sonnet on complex reasoning, multi-step tool use, and code generation quality. Use them deliberately: for scaffolding, boilerplate, and exploration — not for the critical production logic you'd normally review carefully.
How Claude Code Connects to Models
Claude Code speaks one language: the Anthropic Messages APIThe HTTP API at api.anthropic.com/v1/messages. It accepts a JSON payload with model, messages, max_tokens, and optional tools. Every request Claude Code makes is in this format.. By default it sends every request to https://api.anthropic.com. Changing two environment variables redirects those requests anywhere you want.
ANTHROPIC_BASE_URL — overrides the base URL that Claude Code sends requests to. Set this to your local proxy address (e.g., http://localhost:4000) and Claude Code will call http://localhost:4000/v1/messages instead of Anthropic's servers.
ANTHROPIC_API_KEY — the key sent in the x-api-key header. For local models you can set it to any non-empty string; the local server ignores it. You must set it to something non-empty or Claude Code will error before making the request.
Environment Variable Configuration
These variables can be set three ways, in increasing order of permanence:
1. Per-session (shell export):
export ANTHROPIC_API_KEY="local-placeholder"
# Now launch Claude Code in the same shell session
claude
2. Inline (single command):
3. Persistent (Claude Code settings):
{
"env": {
"ANTHROPIC_BASE_URL": "http://localhost:4000",
"ANTHROPIC_API_KEY": "local-placeholder"
}
}
Put project-specific settings in .claude/settings.json (inside your project repo). This lets different projects point to different endpoints without changing global settings. Add .claude/settings.json to .gitignore if you don't want to share local endpoint URLs with teammates.
Ollama — The Easiest Local Setup
OllamaAn open source tool (ollama.com) that packages model weights, a runtime, and an HTTP API into a single cross-platform application. It handles GPU/CPU detection automatically. is the simplest way to run a large language model locally. It provides a Docker-like CLI for pulling and running models, and exposes an HTTP API.
Ollama's native API (/api/generate, /api/chat) is not compatible with the Anthropic Messages API format. Ollama also provides an OpenAI-compatible endpoint at /v1/chat/completions, but that's still not Anthropic format. You need LiteLLM as a bridge (covered in the next section). The setup below shows how to run Ollama; the connection to Claude Code comes via the LiteLLM section.
Step 1: Install and Run Ollama
# WHAT: Download a model and start its server
# WHY: The pull step caches weights locally (~4GB for a 7B model)
# GOTCHA: First pull can take 5-20 minutes depending on your connection
# Start the Ollama daemon (if not already running as a background service)
ollama serve &
# Pull a model (choose based on your available RAM)
ollama pull llama3.2 # 3.2B params — needs ~2GB RAM
ollama pull llama3.2:latest # same thing — :latest is implicit
ollama pull qwen2.5-coder:7b # 7B params — strong coder, needs ~5GB RAM
ollama pull qwen2.5-coder:32b # 32B params — best quality, needs ~20GB RAM
# Verify the model is available
ollama list
# Quick smoke test — interactive chat
ollama run llama3.2 "Write a Python function to reverse a string"
If you have 8GB RAM or less, start with llama3.2 (3.2B). If you have 16GB, try qwen2.5-coder:7b — it punches above its weight for code generation specifically. If you have 32GB+, qwen2.5-coder:32b or deepseek-coder-v2:16b will produce noticeably better results for complex coding tasks.
Step 2: Connect via LiteLLM
See the LiteLLM section below for the full bridge setup. The short version:
# Install LiteLLM proxy
pip install 'litellm[proxy]'
# Start the proxy pointed at your Ollama instance
litellm --model ollama/qwen2.5-coder:7b --port 4000
# In another terminal — launch Claude Code through the proxy
export ANTHROPIC_BASE_URL="http://localhost:4000"
export ANTHROPIC_API_KEY="local"
claude
LM Studio — GUI-Based Local Models
LM StudioA desktop application (lmstudio.ai) that provides a graphical interface for downloading, running, and managing local LLM models. Includes a built-in chat UI and an OpenAI-compatible local server. is the choice for users who prefer a graphical interface over a CLI. It handles model discovery, downloading, quantization selection, and GPU offloading through a polished UI.
Visit lmstudio.ai and download the installer for your OS. Available for macOS (Apple Silicon and Intel), Windows, and Linux.
Open LM Studio → click "Discover" → search for a model (e.g., Qwen2.5-Coder-7B-Instruct) → select a quantization level (Q4_K_M is a good balance of size and quality) → click Download.
In the left sidebar, click the "Local Server" icon (⇅). Load the model you downloaded, then click "Start Server". LM Studio starts an OpenAI-compatible server at http://localhost:1234.
LM Studio's server speaks OpenAI format at /v1/chat/completions, not Anthropic format. You need LiteLLM to translate.
# LM Studio exposes OpenAI format at port 1234
# Tell LiteLLM where to find it using the openai/ prefix
litellm --model openai/your-model-name \
--api_base http://localhost:1234/v1 \
--api_key lm-studio \
--port 4000
# Your-model-name must match what LM Studio is serving
# Check: curl http://localhost:1234/v1/models
# Then in another terminal:
export ANTHROPIC_BASE_URL="http://localhost:4000"
export ANTHROPIC_API_KEY="local"
claude
Claude Code sends Anthropic-format JSON to LiteLLM on port 4000. LiteLLM re-encodes it as OpenAI-format JSON and sends it to LM Studio on port 1234. LM Studio runs inference through the local model weights and sends back a response. LiteLLM converts that response back to Anthropic format before returning it to Claude Code. Claude Code never knows it isn't talking to Anthropic's servers.
LiteLLM Proxy — The Universal Bridge
LiteLLMAn open source Python library and proxy server that translates between different LLM API formats. It supports 100+ models and providers, acting as a universal adapter. GitHub: BerriAI/litellm is the glue that makes this all work. It acts as a translation layer between Claude Code (which speaks Anthropic format) and virtually any other model API (which typically speaks OpenAI format).
Basic Single-Model Setup
# WHAT: Start LiteLLM proxy forwarding to Ollama
# WHY: Translates Anthropic API format → Ollama format
# GOTCHA: ollama serve must be running first (check: ollama list)
pip install 'litellm[proxy]'
# Start proxy — ollama/ prefix tells LiteLLM to use Ollama's native API
litellm --model ollama/qwen2.5-coder:7b \
--port 4000 \
--host 0.0.0.0
# Verify it's running
curl http://localhost:4000/health
# Launch Claude Code
export ANTHROPIC_BASE_URL="http://localhost:4000"
export ANTHROPIC_API_KEY="local-key"
claude --model ollama/qwen2.5-coder:7b
# WHAT: Start LiteLLM proxy forwarding to LM Studio's OpenAI server
# WHY: LM Studio speaks OpenAI format; LiteLLM converts to/from Anthropic format
# GOTCHA: The model name must match what LM Studio shows in its server UI
pip install 'litellm[proxy]'
# Check what LM Studio is serving:
# curl http://localhost:1234/v1/models
# Start proxy — openai/ prefix + api_base points to LM Studio
litellm --model openai/Qwen2.5-Coder-7B-Instruct \
--api_base http://localhost:1234/v1 \
--api_key lm-studio \
--port 4000
# Launch Claude Code
export ANTHROPIC_BASE_URL="http://localhost:4000"
export ANTHROPIC_API_KEY="local"
claude
# WHAT: Route through OpenRouter for cloud-hosted open source models
# WHY: Access Llama, Mistral, Qwen etc. with no local hardware requirements
# GOTCHA: OpenRouter charges per token — check their pricing at openrouter.ai/models
pip install 'litellm[proxy]'
# Get a key at openrouter.ai
export OPENROUTER_API_KEY="sk-or-..."
litellm --model openrouter/meta-llama/llama-3.3-70b-instruct \
--port 4000
# Launch Claude Code
export ANTHROPIC_BASE_URL="http://localhost:4000"
export ANTHROPIC_API_KEY="any-non-empty-string"
claude
# WHAT: Use Groq for extremely fast inference on open source models
# WHY: Groq's LPU hardware runs Llama 3 at ~800 tokens/second
# GOTCHA: Groq has a free tier with rate limits; check groq.com for current limits
pip install 'litellm[proxy]'
# Get a key at console.groq.com
export GROQ_API_KEY="gsk_..."
litellm --model groq/llama-3.3-70b-versatile \
--port 4000
# Launch Claude Code
export ANTHROPIC_BASE_URL="http://localhost:4000"
export ANTHROPIC_API_KEY="any-non-empty-string"
claude
Advanced: Config File with Multiple Models
The CLI flags are fine for quick experiments, but a config file is better for daily use. It lets you define multiple models and switch between them without restarting the proxy.
# WHAT: LiteLLM config defining a routing table of models
# WHY: Lets you alias multiple backends under names Claude Code can request
# GOTCHA: model_name values here are what you pass to --model in Claude Code
model_list:
# Fast local model for boilerplate and quick edits
- model_name: local-fast
litellm_params:
model: ollama/llama3.2
api_base: http://localhost:11434
# Better quality local model for code-heavy tasks
- model_name: local-coder
litellm_params:
model: ollama/qwen2.5-coder:7b
api_base: http://localhost:11434
# Cloud fallback when local isn't good enough
- model_name: cloud-open
litellm_params:
model: openrouter/meta-llama/llama-3.3-70b-instruct
api_key: "os.environ/OPENROUTER_API_KEY"
# High-speed inference for interactive use
- model_name: groq-fast
litellm_params:
model: groq/llama-3.3-70b-versatile
api_key: "os.environ/GROQ_API_KEY"
litellm_settings:
# Drop unsupported params (like temperature when using Ollama with some models)
drop_params: true
# Return full error messages for easier debugging
set_verbose: false
general_settings:
master_key: "local-master-key" # Set any non-empty value for local use
# Start proxy using config file
litellm --config litellm-config.yaml --port 4000
# Now Claude Code can request any model by its model_name alias
export ANTHROPIC_BASE_URL="http://localhost:4000"
export ANTHROPIC_API_KEY="local-master-key"
# Use the fast local model for a quick task
claude --model local-fast "Add type annotations to all functions in utils.py"
# Switch to the better coder model for a harder task
claude --model local-coder "Refactor this class to use async/await throughout"
# Fall back to cloud when you need more horsepower
claude --model cloud-open "Design the architecture for a distributed rate limiter"
On macOS/Linux you can run litellm --config config.yaml --port 4000 & in your shell profile, or create a systemd service. Then set ANTHROPIC_BASE_URL in your ~/.bashrc / ~/.zshrc and every Claude Code session will automatically use your local proxy without any extra setup.
Cloud Alternatives (Not Local, But Not Anthropic)
Sometimes you need better-than-local quality without sending data to Anthropic. These cloud providers host open source models and expose API endpoints you can reach through LiteLLM.
Cloud alternatives still send your prompts and code to third-party servers. They are cheaper than Anthropic (or free-tier) but they are not a local solution. For genuine data privacy requirements (HIPAA, SOC 2, air-gap), you must use a local setup (Ollama or LM Studio) with no cloud routing at any layer.
vLLM — For Self-Hosted Production Deployments
vLLMAn open source, high-throughput inference engine for LLMs. It uses PagedAttention for efficient KV cache management, achieving 2-4x higher throughput than naive implementations. Used to self-host models on your own GPU servers. is the right choice when you need to serve a local model to a team, not just yourself. It provides an OpenAI-compatible API and handles concurrent requests efficiently.
# WHAT: Launch a production-grade local inference server
# WHY: vLLM handles concurrent requests efficiently using PagedAttention
# GOTCHA: Requires an NVIDIA GPU with CUDA; minimum ~16GB VRAM for 7B models
pip install vllm
# Start the server (downloads model from HuggingFace on first run)
python -m vllm.entrypoints.openai.api_server \
--model Qwen/Qwen2.5-Coder-7B-Instruct \
--port 8000 \
--host 0.0.0.0
# Route Claude Code through LiteLLM → vLLM
litellm --model openai/Qwen2.5-Coder-7B-Instruct \
--api_base http://localhost:8000/v1 \
--api_key vllm \
--port 4000
# Connect Claude Code
export ANTHROPIC_BASE_URL="http://localhost:4000"
export ANTHROPIC_API_KEY="local"
claude
Feature Compatibility Matrix
Not every Claude Code feature works identically with all models. This table shows what to expect when using a local or third-party model instead of Claude.
| Claude Code Feature | Claude (Anthropic) | Qwen2.5-Coder 32B | Llama 3.3 70B | Small Models (<8B) |
|---|---|---|---|---|
|
Basic code editing
Read, write, edit files via conversation
|
✓ Full | ✓ Full | ✓ Full | ~ Partial |
|
Tool use / function calling
Bash, Read, Write, Edit tools
|
✓ Full | ✓ Full | ~ Partial | ✗ Unreliable |
|
Multi-step agentic tasks
Complex plans, multiple tool calls per turn
|
✓ Full | ~ Partial | ~ Partial | ✗ Not reliable |
|
MCP server integration
Custom tools via Model Context Protocol
|
✓ Full | ? Depends on model | ? Depends on model | ✗ Rarely works |
|
Long context (>32K tokens)
Large codebases, long conversations
|
✓ 200K tokens | ~ 32K typical | ~ 128K (degrades) | ✗ Usually <8K |
|
Extended thinking / reasoning
Claude's visible chain-of-thought feature
|
✓ Full | ✗ N/A | ✗ N/A | ✗ N/A |
|
Prompt caching
Cost/speed optimization for repeated prefixes
|
✓ Full | ✗ N/A | ✗ N/A | ✗ N/A |
|
Subagent spawning (Agent SDK)
Claude Code spawning child Claude Code processes
|
✓ Full | ~ Works if proxy is configured | ~ Works if proxy is configured | ✗ Not recommended |
|
Streaming responses
Live token output in the terminal
|
✓ Full | ✓ Full | ✓ Full | ✓ Full |
Claude Code's core value comes from tool use — reading files, running bash commands, editing code. Models below ~7B parameters have limited ability to reliably call tools in the right format. You'll see Claude Code complete simple tasks but stall or produce malformed tool calls on anything complex. This isn't a proxy or configuration issue — it's a model capability ceiling. The fix is to use a larger or better-tuned model.
Recommended Models for Claude Code Workflows
These are tested combinations that produce reasonable results with Claude Code's tool-use workflow. "Coding score" is a relative assessment based on HumanEval, MBPP, and observed Claude Code behavior — not a scientific benchmark.
Local Models (Ollama / LM Studio)
Best overall local coding model. Alibaba's code-specialized variant. Excellent tool-use compliance.
ollama pull qwen2.5-coder:32b
Best value for limited hardware. Handles most Claude Code tasks reliably. Sweet spot for 16GB machines.
ollama pull qwen2.5-coder:7b
Strong alternative with different training data. Good at algorithm implementation and code explanation.
ollama pull deepseek-coder-v2:16b
Entry point for very limited hardware (<8GB RAM). Good enough for simple edits, formatting, and boilerplate.
ollama pull llama3.2
Cloud-Hosted Open Source Models
Meta's flagship open model. Available on Groq (very fast) and OpenRouter. Good for complex tasks when local hardware isn't enough.
groq/llama-3.3-70b-versatile
The cloud-scale version. Available on OpenRouter and Together AI. Closest open alternative to Claude for pure coding tasks.
openrouter/qwen/qwen-2.5-coder-32b-instruct
Troubleshooting Common Issues
Connection & Startup Problems
# 1. Is Ollama running?
ollama list # should list downloaded models
curl http://localhost:11434/api/tags # should return JSON
# 2. Is LiteLLM proxy running?
curl http://localhost:4000/health # should return {"status":"healthy"}
# 3. Can LiteLLM reach Ollama?
curl http://localhost:4000/v1/models # should list available models
# 4. Is the Anthropic API format being accepted?
curl -X POST http://localhost:4000/v1/messages \
-H "Content-Type: application/json" \
-H "x-api-key: local-key" \
-d '{
"model": "ollama/llama3.2",
"max_tokens": 64,
"messages": [{"role": "user", "content": "Say hello"}]
}'
# Should return a response in Anthropic format
Common Errors and Fixes
Cause: ANTHROPIC_BASE_URL is not set, so Claude Code is trying to reach Anthropic's servers (possibly while offline).
Fix: Set the environment variable in the same terminal session where you launch Claude Code: export ANTHROPIC_BASE_URL="http://localhost:4000"
Cause: ANTHROPIC_API_KEY doesn't match the master_key in your LiteLLM config.
Fix: Set ANTHROPIC_API_KEY to the same value as general_settings.master_key in litellm-config.yaml. For the default CLI usage (no config file), any non-empty string works.
Cause 1: The model name you passed to --model doesn't match the model_name in your LiteLLM config.
Cause 2: The model doesn't support function/tool calling well.
Fix: Run curl http://localhost:4000/v1/models to see what model names LiteLLM actually recognizes. Switch to a code-specialized model like Qwen2.5-Coder which has better tool-use support.
Cause: The model is running on CPU instead of GPU, or GPU memory is insufficient and it's offloading to RAM.
Fix: Check ollama ps to see GPU utilization. If the model shows "100% CPU", either switch to a smaller model that fits in VRAM or add num_gpu: -1 to your Ollama model settings to force full GPU offload.
Cause: Claude Code sends Anthropic-specific parameters (like stop_sequences or thinking) that the local model doesn't understand.
Fix: Add drop_params: true to litellm_settings in your config file. This silently drops unsupported parameters instead of raising an error.
Knowledge Check
6 questions to confirm your understanding of the local model setup.
1. Which environment variable tells Claude Code to send API requests to a local proxy instead of Anthropic's servers?
ANTHROPIC_BASE_URL redirects Claude Code's API calls from Anthropic's servers to any URL you specify — typically your LiteLLM proxy at http://localhost:4000.ANTHROPIC_BASE_URL is the correct variable. Claude Code appends /v1/messages to this URL for every request.2. Why can't Claude Code connect directly to Ollama's native API without a bridge layer?
/api/chat) and its OpenAI-compatible endpoint (/v1/chat/completions) both use different request/response formats than the Anthropic Messages API. LiteLLM translates between them.3. You set ANTHROPIC_BASE_URL="http://localhost:4000" but Claude Code throws an error before making any network request. What's most likely missing?
ANTHROPIC_API_KEY is present and non-empty before sending any request. For local setups the value can be any non-empty string — it just can't be missing or blank.ANTHROPIC_API_KEY. Claude Code checks this locally before attempting a connection. Set it to any non-empty string for local model usage.4. Which LiteLLM configuration option prevents the proxy from crashing when Claude Code sends Anthropic-specific parameters that the local model doesn't understand?
drop_params: true in litellm_settings silently discards parameters that the target model doesn't support (like thinking or Anthropic-specific stop_sequences formatting) instead of raising a 400 error.drop_params: true under litellm_settings in your config YAML. It silently drops unsupported parameters rather than crashing.5. You're on a machine with 8GB RAM. Which model is the most practical choice for getting Claude Code to work reliably?
6. Which Claude Code feature is NOT available when using any local or third-party model?
thinking API parameter that enables Claude's explicit reasoning mode.