Skip to main content

Launchers

These launchers make local llama.cpp models usable from Codex, Cursor, OpenCode, and Claude Code without repeating provider flags every time. Each wrapper solves a different harness-specific problem: Codex needs local model metadata plus provider routing, Cursor needs its OpenAI-compatible agent-cli-local flavor, OpenCode needs model ids qualified to its configured provider, and Claude Code needs a llama.cpp-scoped settings file.

All four launchers acquire a shared router lease. They join an existing router, or start a loopback router when none is reachable. After the last managed consumer exits, the auto-started instance stays resident for a 10-minute grace period so the next harness can reuse its loaded model; run ,llama-cpp stop to end it earlier or set LLAMA_CPP_GRACE_SECONDS=0 for immediate shutdown. Running ,llama-cpp serve first remains supported, and that manually started process is left running.

Mental model

Codex has two layers. The transparent ,codex wrapper supplies catalog metadata for the llama.cpp router ids, while ,codex-llama-cpp supplies the provider routing flags that point Codex at llama-server.

OpenCode reads providers from ~/.config/opencode/opencode.jsonc, so its launcher only normalizes model selection and passes the rest through.

Cursor's cloud build rejects local provider flags. ,cursor-llama-cpp therefore runs the version-matched agent-cli-local flavor, pins its provider environment to llama.cpp, and rewrites -m to Cursor's --model flag.

Claude Code has one global autoCompactWindow, but cloud opus[1m], 262144-token local models, and work Qwen3.8 need different values. The llama.cpp launcher picks a model-scoped additive settings file: base local models use 200000, work Qwen3.8 uses 100000, and plain cloud Claude sessions stay untouched.

Using it

No separate server command is required for these launchers. Start any harness directly; use ,llama-cpp serve only when you want the router to remain available independently of harness sessions.

Codex launcher metadata

Codex only has first-class model metadata for slugs present in its model catalog; unknown local slugs use fallback metadata and emit a warning. This repo ships a transparent ,codex wrapper plus a small local catalog for the llama.cpp models.

The wrapper injects -c model_catalog_json="$HOME/.codex/llama-cpp-model-catalog.json" when the selected model is one of the llama.cpp router ids, in either --model <id> or --model=<id> form.

Other Codex invocations execute the real Codex binary directly. Hosted MCP authentication is owned by the per-request stdio bridges declared in ~/.codex/config.toml, not by this launcher.

Codex launcher (,codex-llama-cpp)

The ,codex shim above only supplies catalog metadata; Codex still needs the provider routing flags to reach llama-server. ,codex-llama-cpp bakes those in so you don't type them every time.

The wrapper injects:

Codex config keyValue
model_providers.llama-cpp.base_urlhttp://${LLAMA_CPP_HOST}:${LLAMA_CPP_PORT}/v1
model_providers.llama-cpp.namellama.cpp
model_providerllama-cpp

The ~/bin/,codex shim still injects catalog metadata. Pass --model / -m nemotron-3.5 to pick the model.

The wrapper adds its default --model $CODEX_LLAMA_CPP_MODEL only when you did not pass one, so there is no duplicate flag.

,codex-llama-cpp # default model nemotron-3.5
,codex-llama-cpp --model qwen3.5-9b # Unsloth Qwen3.5 9B
,codex-llama-cpp -m qwen3.5-9b exec "..." # one-shot

Cursor launcher (,cursor-llama-cpp)

The launcher uses the same version-matched agent-cli-local installation as ,cursor-openrouter. If that flavor is absent after a Cursor update, the existing ~/lib/,cursor-agent-local/install.sh installer restores it before launch.

It routes Cursor through a loopback metadata proxy to http://${LLAMA_CPP_HOST}:${LLAMA_CPP_PORT}/v1, maps LLAMA_CPP_API_KEY to the local provider key, and keeps Cursor's delegated model band on the selected local id. The proxy supplies profile-specific model context capabilities from the deployed local catalog and forwards inference requests unchanged. Inherited endpoint and provider credentials cannot redirect the session.

,cursor-llama-cpp # default model nemotron-3.5
,cursor-llama-cpp --model qwen3.5-9b # Unsloth Qwen3.5 9B
,cursor-llama-cpp -p "summarize README.md" # one-shot

OpenCode launcher (,opencode-llama-cpp)

OpenCode reads providers from ~/.config/opencode/opencode.jsonc; there is no per-invocation provider override.

The llama-cpp provider is declared in both profile sources and flows through the merge hook unchanged:

FieldValue
Provider idllama-cpp
Base URLhttp://127.0.0.1:8080/v1
Modelsllama.cpp router ids

Each model declares limit.context matching the router: 262144 normally, or 131072 for work Qwen3.8 models. limit.output=32000 preserves OpenCode's native output allowance and enables automatic compaction before the context fills.

The provider id avoids a dot (llama-cpp, not llama.cpp) because OpenCode's SDK derives an incorrect lookup key from dotted ids.

Pass --model/-m with a bare router id — the wrapper qualifies it to llama-cpp/<id> — or the full llama-cpp/<id>. With no --model, it defaults to llama-cpp/$OPENCODE_LLAMA_CPP_MODEL (nemotron-3.5).

Any subcommand/args pass through.

,opencode-llama-cpp # interactive TUI, default model nemotron-3.5
,opencode-llama-cpp --model qwen3.5-9b run "…" # Unsloth Qwen3.5 9B

Claude Code launcher (,claude-llama-cpp)

Claude Code compacts conversation history at autoCompactWindow tokens.

ContextDesired value
Cloud opus[1m]leave default around 1M
Local llama.cppcompact below server context so llama.cpp does not reject the prompt

Those needs conflict on a single global setting.

Solution: a dedicated llama.cpp-scoped settings file loaded via claude --settings <file> (layers additively on top of ~/.claude/settings.json), wired through a thin wrapper.

The wrapper:

  • exports ANTHROPIC_BASE_URL=http://${LLAMA_CPP_HOST:-127.0.0.1}:${LLAMA_CPP_PORT:-8080}.
  • sets ANTHROPIC_API_KEY=$LLAMA_CPP_API_KEY.
  • defaults the key to sk-no-key-required because llama.cpp accepts unauthenticated local requests unless started with --api-key.
  • invokes claude --settings ~/.claude/settings.llama-cpp*.json "$@".

Pass --model / -m nemotron-3.5 to pick the model.

The wrapper injects its default --model $CLAUDE_LLAMA_CPP_MODEL only when you did not pass one, so there is no duplicate flag.

VariableDefaultPurpose
LLAMA_CPP_HOST127.0.0.1Same as ,llama-cpp
LLAMA_CPP_PORT8080Same as ,llama-cpp
LLAMA_CPP_API_KEYsk-no-key-requiredSent as ANTHROPIC_API_KEY (Claude Code uses this for bearer auth)
CLAUDE_LLAMA_CPP_MODELnemotron-3.5Default model; overridden by a caller --model/-m, empty to skip
CLAUDE_LLAMA_CPP_SETTINGSmodel-derivedPoint at an alternate llama.cpp settings file

The wrapper clears inherited CLAUDE_CODE_AUTO_COMPACT_WINDOW and CLAUDE_CODE_MAX_CONTEXT_TOKENS so an outer hosted session cannot override the local budget. It derives the settings file from the effective model before --. nemotron-3.5 and qwen3.5-9b use ~/.claude/settings.llama-cpp.json with autoCompactWindow=200000; qwen3.8-27b and qwen3.8-27b-instruct use ~/.claude/settings.llama-cpp.qwen3.8.json, which renders 100000 on work and 200000 on personal.

autoCompactWindow=100000 leaves a ~31k token buffer under the work Qwen3.8 131072-token server context. 200000 leaves a ~62k token buffer under the 262144-token server context.

env.CLAUDE_CODE_ATTRIBUTION_HEADER=0 stops Claude Code from prepending a per-request x-anthropic-billing-header that would miss the llama.cpp KV cache. Claude Code 2.1.220 copies --settings env into process.env and treats "0" as off.

,claude-llama-cpp # interactive session, default model nemotron-3.5
,claude-llama-cpp --model qwen3.5-9b # Unsloth Qwen3.5 9B
,claude-llama-cpp -p "summarize README.md" # one-shot prompt

Cloud Claude sessions are unaffected — plain claude ... still reads only ~/.claude/settings.json, where autoCompactWindow stays unset so the default for opus[1m] applies.

Sources and verification