Run Claude Code against a local llama-server instead of the Anthropic API. This is
an experimental setup for testing local models — the normal Anthropic subscription
(claude) is not affected.
- Prerequisites
- Installation
- First Launch (Onboarding)
- Recommended Configuration
- Usage
- Sandbox (Security)
- Important: What the Sandbox Does NOT Protect
- How the Wrapper Works
- File Structure
- Known Issues
- Updating
Before installing, make sure the following are available:
- Claude Code CLI (
claude) — install via the native installer (Ubuntu/Debian):After installation, runcurl -fsSL https://claude.ai/install.sh | shclaudeonce to complete the OAuth login with an Anthropic subscription (Max or Teams). This sets up the normal~/.claude/directory. The local instance does not use these credentials but Claude Code itself needs to be installed first. - bubblewrap and socat — required for sandboxing:
sudo apt install bubblewrap socat
~/binin PATH — if not already set up:echo 'export PATH="$HOME/bin:$PATH"' >> ~/.bashrc source ~/.bashrc
- A local inference server with Anthropic Messages API support on
localhost:8080. This setup assumes the llama.cpp Docker wrapper from this repository (start a model with./start.sh), but any server that exposes a compatible/v1/messagesendpoint should work (e.g. Ollama with an Anthropic API adapter). The server must be running before startingclaude-local.
Run the install script:
cd claude-local
./install.shThe script does the following:
| Step | What | Where | Why |
|---|---|---|---|
| 1 | Checks prerequisites | — | Verifies claude, bwrap, and socat are installed |
| 2 | Copies home/CLAUDE.md |
~/.claude-local/CLAUDE.md |
Global preferences for the local instance (writing style, communication rules, local model warning) |
| 3 | Copies home/settings.json |
~/.claude-local/settings.json |
Claude Code settings (telemetry off, timeouts, plans directory) |
| 4 | Copies home/skills/project-setup/SKILL.md |
~/.claude-local/skills/project-setup/SKILL.md |
/project-setup skill adapted for local paths |
| 5 | Creates IDE symlink | ~/.claude-local/ide/ → ~/.claude/ide/ |
VS Code extension writes lock files to ~/.claude/ide/ (hardcoded). Without this symlink, VS Code integration breaks. See issue #4739. |
| 6 | Copies bin/claude-local |
~/bin/claude-local |
Wrapper script — needs to be in PATH so claude-local works as a command from any directory |
The wrapper sets CLAUDE_CONFIG_DIR=~/.claude-local so Claude Code reads its config
from there instead of ~/.claude/. This keeps the local instance completely separate
from the normal Anthropic installation — no OAuth credentials are touched, no settings
are shared.
# Copy config files
mkdir -p ~/.claude-local/skills/project-setup
cp home/CLAUDE.md ~/.claude-local/CLAUDE.md
cp home/settings.json ~/.claude-local/settings.json
cp home/skills/project-setup/SKILL.md ~/.claude-local/skills/project-setup/SKILL.md
# Create IDE symlink for VS Code integration
mkdir -p ~/.claude/ide
ln -s ~/.claude/ide ~/.claude-local/ide
# Copy wrapper script to ~/bin (or another directory in PATH)
mkdir -p ~/bin
cp bin/claude-local ~/bin/claude-local
chmod +x ~/bin/claude-localOr use symlinks instead of copies if preferred (changes in the repo then apply immediately without re-running install):
ln -s "$(pwd)/home" ~/.claude-local
ln -s ~/.claude/ide ~/.claude-local/ide
mkdir -p ~/bin
ln -s "$(pwd)/bin/claude-local" ~/bin/claude-localThe first time claude-local starts, Claude Code runs its onboarding wizard because
~/.claude-local/ is a fresh config directory. This is normal and only happens once.
- Theme selection — choose dark mode or another theme
- Diagnostic warnings — a warning about
config install method is 'unknown'may appear. This is cosmetic and has no effect on functionality. Ignore it. - Ready — after onboarding, the session is fully functional
After the first launch, open /config and adjust these settings:
| Setting | Recommended | Why |
|---|---|---|
| Verbose output | true |
Shows thinking blocks and token usage — useful for seeing what the local model is doing |
| Thinking mode | true |
Enables thinking/reasoning blocks (should already be on via settings.json) |
| Auto-update channel | disabled |
Already disabled via CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC |
These settings are stored in ~/.claude-local/ and persist across sessions.
- Start a model — run
./start.shfrom the project root and pick a model - Start claude-local — from any project directory:
claude-local
- Enable sandbox — type
/sandboxin the session and choose option 2 ("Sandbox BashTool, with regular permissions") - Work — chat, read files, write code, use tools
The model name shown in the interface is local-llama regardless of which model
is actually loaded in llama-server. llama-server routes all requests to whatever
model is running — the name is only a label.
For VS Code integration (diffs shown in editor instead of terminal), start
claude-local from a VS Code integrated terminal. Then run /ide and select
Visual Studio Code.
The management API on port 8081 allows switching the loaded model without restarting the Claude Code session. This only works without sandbox (sandbox blocks bash network access).
curl -X POST http://localhost:8081/switch -H "Content-Type: application/json" -d '{"model":"glm-flash-q4"}'
Or ask the local model to run it. The switch takes ~15-30 seconds (container restart and model load). The session stays alive and the conversation history is preserved — the new model receives the full context from before the switch.
Available model IDs can be listed with:
curl http://localhost:8081/models
Or switch models via the dashboard (press m in the TUI).
| Scenario | Use | Why |
|---|---|---|
| Serious coding work, complex refactoring | claude |
Opus is significantly more capable for multi-step reasoning and agentic tasks |
| Experimenting with local models | claude-local |
Test how different models handle tasks, compare quality |
| Sensitive/private code | claude-local |
Nothing leaves the machine — all inference is local |
| Offline or no internet | claude-local |
Works without any network connection (except localhost) |
| Learning how models behave | claude-local |
Verbose output shows thinking blocks, useful for understanding model reasoning |
| Quick simple tasks | Either | Local models handle straightforward tasks fine |
- Slower than Opus for complex tasks — but faster response times for simple questions (no network latency)
- Less capable at multi-step reasoning — complex skills like
/project-setupmay produce errors or need manual intervention - Tool use works but is less reliable — the model may call tools with wrong parameters or misunderstand tool outputs
- Thinking/reasoning varies by model — some models produce useful thinking blocks, others do not
- Always review before approving — local models are more likely to misinterpret instructions than Opus
The sandbox (/sandbox) uses bubblewrap to restrict what bash commands can do.
Enable it after starting a session — especially important with local models that
are less capable than Claude Opus and may misinterpret instructions.
How to enable: Type /sandbox → select "Sandbox BashTool, with regular
permissions" → bash commands now run inside a bubblewrap container.
Persistent: The sandbox setting is saved — once enabled, it stays on for all future sessions. It does not need to be re-enabled each time.
| Action | Result |
|---|---|
| Bash: write files outside project workspace | Blocked |
Bash: sudo commands |
Blocked |
| Bash: network access (curl, wget, etc.) | Blocked |
| Bash: commands within project workspace | Allowed (with permission prompt) |
| Claude Code → llama-server API communication | Works (not routed through bash) |
| VS Code IDE integration | Works |
The sandbox only wraps bash commands. Claude Code's built-in tools (Read, Write, Edit, Glob) are not sandboxed — they can read and write files anywhere on the system, including outside the project workspace.
This means:
- If the model decides to use the Write tool to write to
/tmp/test.txtor~/some-other-project/file.py, the sandbox will not block it - If the model uses bash
echo > /tmp/test.txt, the sandbox will block it
How to stay safe:
- Always review what the model wants to do before approving
- Pay extra attention to Write/Edit tool actions — check the file path
- Local models are less capable than Opus and may misunderstand instructions
- When in doubt, deny the action and rephrase the instruction
- Use
/sandboxmode 2 (regular permissions) so every bash command requires explicit approval
This is a limitation of Claude Code's sandbox design, not specific to the local
setup. The same applies to the normal claude command.
The claude-local script sets environment variables and runs claude:
| Variable | Value | Why |
|---|---|---|
CLAUDE_CONFIG_DIR |
~/.claude-local |
Config isolation — reads settings, CLAUDE.md, and skills from here instead of ~/.claude/ |
ANTHROPIC_BASE_URL |
http://127.0.0.1:8080 |
Point to local llama-server |
ANTHROPIC_AUTH_TOKEN |
llamacpp |
Bypass OAuth (any non-empty string works) |
ANTHROPIC_API_KEY |
"" |
Prevent API key lookup |
ANTHROPIC_MODEL |
local-llama |
Generic model name (llama-server routes to whatever is loaded) |
ANTHROPIC_SMALL_FAST_MODEL |
local-llama |
Used for background requests (same model) |
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC |
1 |
No telemetry/update checks |
claude-local/
├── README.md # This file
├── install.sh # Copies files to ~/.claude-local/ and ~/bin/
├── bin/
│ └── claude-local # Wrapper script (→ ~/bin/claude-local)
└── home/ # Config files (→ ~/.claude-local/)
├── CLAUDE.md # Global preferences for the local instance
├── settings.json # Claude Code settings (telemetry, timeouts, etc.)
└── skills/
└── project-setup/
└── SKILL.md # /project-setup skill adapted for local instance
CLAUDE_CONFIG_DIRis not officially documented by Anthropic. It works in practice but could change in future Claude Code versions.- VS Code IDE detection requires the
ide/symlink workaround (handled by the install script). See issue #4739. config install method is 'unknown'warning appears in/statusdiagnostics. This is cosmetic — Claude Code does not find install metadata in the custom config directory. No effect on functionality.- Write/Edit tools not sandboxed — Claude Code's built-in file tools bypass the bubblewrap sandbox. See the security section.
- Sandbox is persistent — once enabled via
/sandbox, it stays on for all future sessions (stored in~/.claude-local/). This is desirable as a default, but be aware of the following consequences:- Temporary stub files appear in the working directory during a session (e.g.
.bashrc,.gitconfig,HEAD,.mcp.json,.vscode, etc.) — these are read-only, 0-byte files created by bubblewrap as part of the sandboxed environment. They are automatically cleaned up when the session ends. /project-setupPhase 0 will not work with sandbox active, because it tries to read/write files in~/.claude-local/which is outside the workspace. Disable sandbox first (/sandbox→ "No Sandbox"), run the skill, then re-enable sandbox.
- Temporary stub files appear in the working directory during a session (e.g.
/resumemay not work — resuming a previous session has been observed to fail with a serialization error (The "string" argument must be of type string...). Not yet clear if this is caused byCLAUDE_CONFIG_DIR, running two Claude Code instances simultaneously, or the test-project being inside an existing repo. Needs further testing in an isolated setup.- Local model limitations with skills — complex multi-step skills (like
/project-setup) may produce errors or unexpected behavior with local models. Common issues include: Write tool parameter type errors, difficulty reading certain directories, and incorrect agent creation. These are model capability limitations, not configuration problems. Review each action carefully before approving.
After changing files in this directory (e.g., updating CLAUDE.md or settings.json),
re-run ./install.sh or manually copy the changed files to ~/.claude-local/.