Use Claude Code with local Qwen3.8 served by Eole
This experimental recipe connects the Claude Code CLI to Eole's Anthropic-style Messages endpoint. The answering model is Qwen3.8-27B. Anthropic does not support routing Claude Code to non-Claude models through a gateway; this is an Eole compatibility workflow, not an official Anthropic integration. See the gateway documentation.
Run Eole commands from the repository root. First complete the
Qwen3.8 checkpoint and MTP setup. Use an INT4 checkpoint
retaining MTP weights for a 32 GB RTX 5090. The shared YAML fixes greedy decoding
with top_k: 1, single-sequence requests, and a conservative 32K context.
Start and verify Eole
export EOLE_MODEL_DIR=/path/to/models
export QWEN38_MODEL="$EOLE_MODEL_DIR/Qwen3.8-27B-INT4"
python recipes/qwen38/check_checkpoint.py "$QWEN38_MODEL"
eole serve -c recipes/qwen38/serve.yaml --host 127.0.0.1 --port 5000
In another terminal run the live API checks:
python recipes/claude-code/smoke_test.py --base-url http://127.0.0.1:5000 \
--model qwen3.8-27B
The script checks health, model discovery, token counting, a plain Messages
response, a tool-use/tool-result round trip, and typed text/tool-use SSE events. It executes
only a synthetic add tool locally; it does not run model-proposed shell
commands. A successful HTTP response alone is not a passing tool-use test.
The script fails on error responses, missing tool blocks, or an incorrect sum.
Verify that server logs contain MTP draft acceptance. A fallback warning means
MTP was not active. The script cannot prove speculation through API responses;
acceptance is a server-side diagnostic.
Configure the Claude Code CLI
Install Claude Code using its official instructions. Use a fresh terminal for the following variables so they do not change your normal Claude setup:
export ANTHROPIC_BASE_URL=http://127.0.0.1:5000
export ANTHROPIC_AUTH_TOKEN=eole-local
export ANTHROPIC_MODEL=qwen3.8-27B
export ANTHROPIC_DEFAULT_OPUS_MODEL=qwen3.8-27B
export ANTHROPIC_DEFAULT_SONNET_MODEL=qwen3.8-27B
export ANTHROPIC_DEFAULT_HAIKU_MODEL=qwen3.8-27B
export CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1
export CLAUDE_CODE_MAX_OUTPUT_TOKENS=2048
claude --model qwen3.8-27B
The placeholder token selects the client credential path; Eole does not
validate it or add authentication. Keep the server bound to loopback.
The default-model mappings keep client model aliases pointed at the same Eole
model. Existing Claude settings or provider variables can override this setup;
check /status for the actual URL and model before continuing.
The explicit 2048-token output budget leaves room for the client system prompt
and tool history within the server’s 32K context; the client’s default budget
for a custom model may otherwise be 32K. Increase server context and client
output budget together only after checking VRAM. See the
environment variable reference.
See gateway connection and
model configuration.
For a fully isolated client test, set CLAUDE_CONFIG_DIR to an empty writable
scratch directory before launching Claude. This also avoids read-only home
errors from the Bash tool's session files. The validation harness does this
automatically and does not modify your normal Claude configuration.
Try an isolated coding task
Start a session in a scratch directory, not your real project:
mkdir -p /tmp/eole-claude-demo
cd /tmp/eole-claude-demo
claude --model qwen3.8-27B
Ask:
Create palindrome.py with an is_palindrome function that ignores case and non-alphanumeric characters. Add a small unittest file, run it, and report the result.
Review and approve file/shell operations through the normal client permission flow. Check the files and test output; a convincing final message is not proof that tools ran. This deliberately small exercise tests repeated tool calls, results returning to the model, and an actual edit/test cycle.
Behavior and troubleshooting
- Response appears all at once: Anthropic SSE currently buffers the complete model output before emitting typed blocks. This is expected; it is not live token streaming. MTP can reduce generation time but does not remove buffering.
- MTP fallback: Check batch size, greedy selection, loaded MTP tensors,
text-only inputs, and decoding constraints. Client temperature does not undo
top_k: 1; this recipe intentionally sacrifices sampling diversity. - Unknown model: Use
qwen3.8-27B, the YAMLid, rather than the checkpoint directory or a Claude model name. Check/v1/modelsand/status. - Context or out-of-memory errors: Reduce context/generation length. Claude Code adds system instructions and tool definitions beyond your visible prompt. A custom model name does not necessarily tell the client the real context window; keep sessions short and verify the client's context configuration.
- Tool parsing fails: Run the smoke test first; confirm the checkpoint's chat template has tool support. Model-generated arguments can be malformed.
- Unsupported features: Extended thinking, prompt-cache accounting, beta request features, and structured output are not guaranteed. Unrecognized request fields may be ignored. Token usage is estimated.
Validation status
On 2026-10-07 the live API checks passed on an RTX 5090 with the converted Qwen3.8-27B INT4 checkpoint and native MTP: discovery, token counting, text, numeric tool-use/tool-result round trip, typed text SSE, and typed tool SSE. The run exposed an XML argument-type bug; the schema-aware server fix is covered by regression tests and passed live revalidation.
Claude Code 2.1.79 passed a sentinel-file Read check, created the palindrome implementation and unittest file through Write calls, and ran all three tests through Bash after its configuration directory was redirected to writable scratch storage. Independent test execution and additional cases also passed. The read/write and shell checks used separate isolated client sessions with explicit tool permissions. Pin and record the version used because protocol behavior can change.
Client system prompts and tool history increase prefill time; the short-prompt generation benchmark does not predict full coding-session latency. Typed SSE is still buffered, as described above. For measured MTP versus baseline results and output-parity limits see the benchmark recipe.