Claude Code + llama.cpp + Qwen3.6 128K 直连部署教程
这篇不是原理介绍,也不是使用说明,而是一篇真正可以照着手动部署的教程。
默认前提只有三个:
llama.cpp已经编译完成Qwen3.6-35B-A3B-UD-Q4_K_M.gguf已经放好Claude Code已经安装
在这个前提下,我们通过手动创建几个脚本,把这套直连方案跑起来:
Claude Code -> llama-server /v1/messages -> Qwen3.6 128K
这套方案的目标是:
- 步骤尽量少
- 成功率高
- 不依赖 LiteLLM
- 保留
llama.cpp的参数控制能力
一、最终要创建哪些文件
建议在 llama.cpp 目录下新建一个专门的脚本目录:
mkdir -p ~/llama.cpp/scripts/qwen36-128k-direct
本教程会创建 4 个脚本:
start_qwen36_128k.shensure_qwen36_128k_direct_service.shclaude-qwen36-128k-direct.shstart_claude_qwen36_128k_direct_stack.sh
建议目录结构如下:
~/llama.cpp/
├── build/bin/llama-server
├── models/Qwen3.6-35B-A3B-UD-Q4_K_M.gguf
└── scripts/qwen36-128k-direct/
├── start_qwen36_128k.sh
├── ensure_qwen36_128k_direct_service.sh
├── claude-qwen36-128k-direct.sh
└── start_claude_qwen36_128k_direct_stack.sh
二、先确认 3 个关键路径
先把你自己环境里的这 3 个路径确认好,后面的脚本会用到。
1. llama-server 路径
通常是:
~/llama.cpp/build/bin/llama-server
2. 模型文件路径
通常是:
~/llama.cpp/models/Qwen3.6-35B-A3B-UD-Q4_K_M.gguf
3. Claude Code 可执行文件路径
你可以执行下面的命令查:
which claude
如果输出类似:
/Users/你的用户名/Documents/.npm-global/bin/claude
那后面脚本里就填这个路径。
如果你机器上的 claude 路径不一样,一定要改成你自己的。
三、创建第一个脚本:启动 Qwen3.6 128K
这个脚本负责启动 llama-server 本体。
进入脚本目录:
cd ~/llama.cpp/scripts/qwen36-128k-direct
创建文件:
cat << 'EOF' > start_qwen36_128k.sh
#!/bin/bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
LLAMA_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)"
SERVER="$LLAMA_DIR/build/bin/llama-server"
MODEL="$LLAMA_DIR/models/Qwen3.6-35B-A3B-UD-Q4_K_M.gguf"
if [ ! -x "$SERVER" ]; then
echo "llama-server not found: $SERVER" >&2
exit 1
fi
if [ ! -f "$MODEL" ]; then
echo "model not found: $MODEL" >&2
exit 1
fi
echo "Starting Qwen3.6-35B-A3B 128K on http://127.0.0.1:8080 ..."
exec "$SERVER" \
-m "$MODEL" \
-ngl 99 \
-c 131072 \
-fa on \
-b 2048 \
-t 16 \
--port 8080 \
--host 127.0.0.1 \
--reasoning-budget 0 \
--temp 0.6 \
--top-p 0.95 \
--top-k 20 \
--min-p 0.05 \
--alias qwen3.6-35b-128k
EOF
加执行权限:
chmod +x start_qwen36_128k.sh
这个脚本里,哪些地方按环境修改
一般只需要关注这几项:
MODEL=...
如果你的模型文件名不同,要改这里--port 8080
如果你的8080已被别的服务长期占用,可以改成其他端口--alias qwen3.6-35b-128k
这是暴露给 Claude Code 的模型名,后面脚本必须保持一致
这组参数里最重要的两项
-c 131072
代表128K上下文--reasoning-budget 0
这是关键稳定性参数,建议保留
四、创建第二个脚本:确保模型服务在线
这个脚本是整套方案的核心兜底。
它负责:
- 检查
8080是否已经有正确模型在运行 - 如果没有,就后台启动模型
- 等待服务端口真正打开
- 等待
/v1/models里真正出现目标模型别名
创建文件:
cat << 'EOF' > ensure_qwen36_128k_direct_service.sh
#!/bin/bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
MODEL_PORT=8080
EXPECTED_MODEL="qwen3.6-35b-128k"
RUNTIME_DIR="$HOME/.qwen36-128k-direct"
LOG_DIR="$RUNTIME_DIR/logs"
MODEL_LOG="$LOG_DIR/qwen36-128k-direct-model.log"
mkdir -p "$LOG_DIR"
is_listening() {
local port="$1"
lsof -nP -iTCP:"$port" -sTCP:LISTEN >/dev/null 2>&1
}
port_contains() {
local url="$1"
local expected="$2"
local body
body="$(curl -s --max-time 3 "$url" 2>/dev/null || true)"
if [ -z "$body" ]; then
return 1
fi
echo "$body" | grep -q "$expected"
}
wait_for_port() {
local port="$1"
local name="$2"
local attempts="${3:-120}"
local pid="${4:-}"
local log_file="${5:-}"
for attempt in $(seq 1 "$attempts"); do
if is_listening "$port"; then
return 0
fi
if [ -n "$pid" ] && ! kill -0 "$pid" 2>/dev/null; then
echo "$name exited before opening port $port" >&2
if [ -n "$log_file" ] && [ -f "$log_file" ]; then
echo "--- $name log tail ---" >&2
tail -n 40 "$log_file" >&2 || true
fi
return 1
fi
if [ $((attempt % 5)) -eq 0 ]; then
echo "$name is still starting... ($attempt/$attempts)"
fi
sleep 2
done
echo "$name failed to start on port $port" >&2
if [ -n "$log_file" ] && [ -f "$log_file" ]; then
echo "--- $name log tail ---" >&2
tail -n 40 "$log_file" >&2 || true
fi
return 1
}
wait_for_model_signature() {
local attempts="${1:-60}"
for attempt in $(seq 1 "$attempts"); do
if port_contains "http://127.0.0.1:${MODEL_PORT}/v1/models" "$EXPECTED_MODEL"; then
return 0
fi
if [ $((attempt % 5)) -eq 0 ]; then
echo "Qwen3.6 128K direct server is up but still initializing... ($attempt/$attempts)"
fi
sleep 2
done
echo "Qwen3.6 128K direct server did not report the expected model in time" >&2
return 1
}
if is_listening "$MODEL_PORT"; then
if port_contains "http://127.0.0.1:${MODEL_PORT}/v1/models" "$EXPECTED_MODEL"; then
echo "Qwen3.6 128K direct server already running on 127.0.0.1:$MODEL_PORT"
exit 0
fi
echo "Port $MODEL_PORT is already occupied by another model/service." >&2
echo "Please stop the current 8080 service before starting direct Claude Code mode." >&2
exit 1
fi
echo "Starting Qwen3.6 128K direct server on 127.0.0.1:$MODEL_PORT ..."
nohup "$SCRIPT_DIR/start_qwen36_128k.sh" >"$MODEL_LOG" 2>&1 &
pid=$!
wait_for_port "$MODEL_PORT" "Qwen3.6 128K direct server" 180 "$pid" "$MODEL_LOG"
wait_for_model_signature 60
echo "Qwen3.6 128K direct server is ready"
EOF
加执行权限:
chmod +x ensure_qwen36_128k_direct_service.sh
这个脚本里,哪些地方按环境修改
MODEL_PORT=8080
如果你前面改了端口,这里必须同步改EXPECTED_MODEL="qwen3.6-35b-128k"
如果你前面改了--alias,这里也要改成一样RUNTIME_DIR="$HOME/.qwen36-128k-direct"
日志目录,通常不用改
这里为什么要用 nohup
因为这个脚本需要在后台拉起模型服务,否则执行完脚本后终端关闭,模型也会跟着退出。
五、创建第三个脚本:让 Claude Code 直连本地模型
这个脚本负责把 Claude Code 的接口指到本地 llama-server。
创建文件:
cat << 'EOF' > claude-qwen36-128k-direct.sh
#!/bin/bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
if [ "${CLAUDE_QWEN36_128K_DIRECT_SKIP_ENSURE:-0}" != "1" ]; then
"$SCRIPT_DIR/ensure_qwen36_128k_direct_service.sh"
fi
export ANTHROPIC_BASE_URL="http://127.0.0.1:8080"
export ANTHROPIC_API_KEY="sk-local"
export ANTHROPIC_MODEL="qwen3.6-35b-128k"
export ANTHROPIC_CUSTOM_MODEL_OPTION="qwen3.6-35b-128k"
export ANTHROPIC_CUSTOM_MODEL_OPTION_NAME="Qwen3.6 128K Direct"
export ANTHROPIC_CUSTOM_MODEL_OPTION_DESCRIPTION="Qwen3.6-35B-A3B Q4 128K via llama-server /v1/messages"
exec /Users/你的用户名/Documents/.npm-global/bin/claude "$@"
EOF
加执行权限:
chmod +x claude-qwen36-128k-direct.sh
这个脚本里,哪些地方按环境修改
ANTHROPIC_BASE_URL="http://127.0.0.1:8080"
如果你前面换了端口,这里要同步改ANTHROPIC_MODEL="qwen3.6-35b-128k"
必须和前面的--alias完全一致exec /Users/你的用户名/Documents/.npm-global/bin/claude "$@"
这里必须改成你自己的claude可执行文件路径
ANTHROPIC_API_KEY 为什么写 sk-local
这里只是给 Claude Code 一个本地占位值,不是去调用官方 API,所以不需要真实密钥。
六、创建第四个脚本:一键启动整套
这个脚本是你以后最常用的入口。
创建文件:
cat << 'EOF' > start_claude_qwen36_128k_direct_stack.sh
#!/bin/bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
"$SCRIPT_DIR/ensure_qwen36_128k_direct_service.sh"
export CLAUDE_QWEN36_128K_DIRECT_SKIP_ENSURE=1
exec "$SCRIPT_DIR/claude-qwen36-128k-direct.sh" "$@"
EOF
加执行权限:
chmod +x start_claude_qwen36_128k_direct_stack.sh
这个脚本本身一般不需要改。
七、先做一轮语法检查
建议把 4 个脚本都先检查一遍:
bash -n ~/llama.cpp/scripts/qwen36-128k-direct/start_qwen36_128k.sh
bash -n ~/llama.cpp/scripts/qwen36-128k-direct/ensure_qwen36_128k_direct_service.sh
bash -n ~/llama.cpp/scripts/qwen36-128k-direct/claude-qwen36-128k-direct.sh
bash -n ~/llama.cpp/scripts/qwen36-128k-direct/start_claude_qwen36_128k_direct_stack.sh
如果没有输出,说明脚本语法正常。
八、正式启动
推荐做法:先进入一个干净目录
不要直接在 ~ 主目录启动 Claude Code。
建议:
mkdir -p ~/claude-workspace/qwen36-128k
cd ~/claude-workspace/qwen36-128k
然后一键启动
~/llama.cpp/scripts/qwen36-128k-direct/start_claude_qwen36_128k_direct_stack.sh
如果一切正常,这个脚本会:
- 检查
8080上是否已经有qwen3.6-35b-128k - 如果没有,就自动后台启动模型
- 等模型初始化完成
- 自动把 Claude Code 指向本地
llama-server
九、如何验证是否成功
方法一:直接看 Claude Code 顶部
如果成功,通常会看到当前模型名已经变成:
qwen3.6-35b-128k
方法二:用非交互命令测试
执行:
~/llama.cpp/scripts/qwen36-128k-direct/claude-qwen36-128k-direct.sh --print 'Reply with exactly: ok'
如果返回:
ok
说明链路已经跑通。
方法三:直接测 llama-server
执行:
curl -s http://127.0.0.1:8080/v1/messages \
-H 'content-type: application/json' \
-H 'x-api-key: sk-local' \
-H 'anthropic-version: 2023-06-01' \
-d '{
"model": "qwen3.6-35b-128k",
"max_tokens": 16,
"messages": [{"role": "user", "content": "Reply with exactly: ok"}]
}'
如果 JSON 里有:
"text":"ok"
说明 llama-server /v1/messages 本身已经正常。
十、Claude Code 上下文显示修正方案(可选)
如果你已经按上面的步骤把 Qwen3.6 128K 跑起来了,但在 Claude Code 里执行:
/context
看到的仍然是类似:
qwen3.6-35b-128k · 3k / 200k tokens
不要慌,这不代表你的模型真的在按 200K 运行。
为什么会这样
llama-server 的真实上下文上限,由启动参数决定:
-c 131072
也就是 128K。
但 Claude Code 2.1.81 在本地自定义模型场景下,/context 面板不会准确读取 llama.cpp 当前运行时的上下文窗口,而是会回退到它自己的默认估算逻辑,所以经常显示成 200K。
换句话说:
- 模型真实上限:
128K - Claude Code 界面显示:
200K - 出错的是显示,不是模型
如果你不在意这个显示偏差,其实可以直接继续用,真正的硬限制仍然由 llama-server 决定。
如果你想让 Claude Code 也显示成 128K
可以做一个本地 patch。
先说明两点:
- 这是对 Claude Code 本地安装文件的修改
- Claude Code 升级后,这个 patch 很可能会失效,需要重新打一遍
第一步:备份 Claude Code 的 cli.js
cp /Users/你的用户名/Documents/.npm-global/lib/node_modules/@anthropic-ai/claude-code/cli.js \
/Users/你的用户名/Documents/.npm-global/lib/node_modules/@anthropic-ai/claude-code/cli.js.bak-qwen128k-context
如果你的 Claude Code 安装路径不一样,请先执行:
which claude
再顺着找到对应的 @anthropic-ai/claude-code/cli.js。
第二步:打开 Claude Code 的模型能力识别开关
执行:
python3 - <<'PY'
from pathlib import Path
p = Path('/Users/你的用户名/Documents/.npm-global/lib/node_modules/@anthropic-ai/claude-code/cli.js')
text = p.read_text()
old = 'function VC7(){return!1}'
new = 'function VC7(){return!0}'
if old not in text:
raise SystemExit('target snippet not found')
text = text.replace(old, new, 1)
p.write_text(text)
print('patched VC7')
PY
这一步的作用是:让 Claude Code 不再完全跳过本地模型能力逻辑。
第三步:给本地模型加一个上下文 override
继续执行:
python3 - <<'PY'
from pathlib import Path
p = Path('/Users/你的用户名/Documents/.npm-global/lib/node_modules/@anthropic-ai/claude-code/cli.js')
text = p.read_text()
old = 'function JX1(A){if(!VC7())return;'
new = 'function JX1(A){let qwenLocal=A?.toLowerCase?.();if(qwenLocal&&qwenLocal.includes("qwen3.6-35b-128k"))return{id:"qwen3.6-35b-128k",max_input_tokens:131072,max_tokens:16384};if(!VC7())return;'
if old not in text:
raise SystemExit('target snippet not found for JX1')
text = text.replace(old, new, 1)
p.write_text(text)
print('patched JX1 qwen override')
PY
这一步的作用是:
当 Claude Code 当前模型名里包含:
qwen3.6-35b-128k
就直接返回:
max_input_tokens: 131072max_tokens: 16384
也就是把你的本地 Qwen3.6 128K 能力硬告诉它。
第四步:重新启动 Claude Code
重新运行你原来的直连脚本:
~/llama.cpp/scripts/qwen36-128k-direct/claude-qwen36-128k-direct.sh
然后再执行:
/context
如果 patch 生效,你会看到类似:
qwen3.6-35b-128k · 22.3k / 131.1k tokens
这就说明 Claude Code 的上下文显示已经和 llama-server -c 131072 对齐了。
第五步:如何恢复原版
如果你不想继续保留这个 patch,可以直接恢复备份:
cp /Users/你的用户名/Documents/.npm-global/lib/node_modules/@anthropic-ai/claude-code/cli.js.bak-qwen128k-context \
/Users/你的用户名/Documents/.npm-global/lib/node_modules/@anthropic-ai/claude-code/cli.js
这个 patch 的适用范围
这套 patch 只适用于你当前这套模型名和上下文配置:
- 模型别名:
qwen3.6-35b-128k - 上下文:
131072
如果你后面改成别的模型,比如:
qwen3.6-35b-64kqwen3.6-35b-128k-q5- 其他自定义别名
那就要同步修改上面 JX1() 那段里的模型名和上下文参数。
一句话结论
如果你只是想“能用”,其实可以不 patch。因为真正的上下文上限本来就以 llama-server -c 131072 为准。
但如果你想让 Claude Code 的 /context 面板也正确显示 128K,那这套本地 patch 是目前最直接、最有效的办法。
十一、常见需要改的地方汇总
如果你不是完全复制这套环境,最常改的是下面这些值。
1. claude 命令路径
当前教程默认写的是:
/Users/你的用户名/Documents/.npm-global/bin/claude
你自己的机器要改成:
which claude
查出来的实际路径。
2. 模型文件名
如果你的模型不是:
Qwen3.6-35B-A3B-UD-Q4_K_M.gguf
要改 start_qwen36_128k.sh 里的:
MODEL=...
3. 端口号
默认端口是:
8080
如果机器上已有别的服务占用了 8080,那你必须同步修改这 3 个地方:
start_qwen36_128k.sh里的--portensure_qwen36_128k_direct_service.sh里的MODEL_PORTclaude-qwen36-128k-direct.sh里的ANTHROPIC_BASE_URL
4. 模型别名
默认别名是:
qwen3.6-35b-128k
如果你想改名,那这 3 个地方也必须一起改:
start_qwen36_128k.sh里的--aliasensure_qwen36_128k_direct_service.sh里的EXPECTED_MODELclaude-qwen36-128k-direct.sh里的ANTHROPIC_MODEL
十二、最常见报错和处理方式
1. Port 8080 is already occupied
说明端口被别的程序占了。
先查:
lsof -nP -iTCP:8080 -sTCP:LISTEN
如果确认要停掉当前占用,再执行:
kill $(lsof -ti:8080)
2. model not found
说明模型文件路径不对。
检查:
ls ~/llama.cpp/models
然后改 start_qwen36_128k.sh 里的 MODEL=...
3. llama-server not found
说明 llama.cpp 没编好,或者路径不对。
检查:
ls ~/llama.cpp/build/bin
4. Claude Code 能打开,但不是本地模型
优先检查:
claude-qwen36-128k-direct.sh里的claude路径是否正确ANTHROPIC_BASE_URL是否指向了正确端口ANTHROPIC_MODEL是否和--alias一致
5. Claude Code 提示在 home 目录运行
这不是致命错误,但建议处理。
先进入一个干净目录:
mkdir -p ~/claude-workspace/qwen36-128k
cd ~/claude-workspace/qwen36-128k
再启动。
十三、日常怎么用
以后最推荐记住的其实只有一条命令:
~/llama.cpp/scripts/qwen36-128k-direct/start_claude_qwen36_128k_direct_stack.sh
如果模型已经在跑,想直接进入 Claude Code,用:
~/llama.cpp/scripts/qwen36-128k-direct/claude-qwen36-128k-direct.sh
十四、一句话总结
这套部署的关键,不是“装很多东西”,而是把 4 个脚本配对好:
- 一个脚本启动
llama-server - 一个脚本保证模型服务在线
- 一个脚本把 Claude Code 指到本地
- 一个脚本把前面三步串起来
只要这 4 个脚本里的路径、端口、模型别名保持一致,这套 Claude Code + llama.cpp + Qwen3.6 128K 的直连方案就能稳定跑起来。