見出し画像

Claude Codeを無料で動かしたら別物になった。Opus蒸留GGUFで手触りを揃える方法

Claude Code を開いて `claude` と打つたびに、裏で課金が発生している。それが気になり出したら、この記事の出番です。手元の GPU に GGUF を載せて、Anthropic の API を一度も叩かずに Claude Code を動かす。そのための手順を、実際に自分の機械で通した順番のまま書きます。

ただ、この手の「無料で Claude Code」には落とし穴があって、そこを外すと 画面は Claude Code なのに、出てくる成果物は Opus で作ったものとまるで別物 になります。この記事でいちばん書きたいのは、実はその部分です。手順そのものは 20 分で終わります。

想定読者は、ローカル LLM を触ったことはあるがビルドは苦手、くらいの人です。コマンドは全部そのまま貼れる形で書きました。

「無料の Claude Code」が別物になる理由

この分野でいちばん star が集まっているのが `Alishahryar1/free-claude-code` です。2026 年 8 月時点で 43,589 star、MIT。ローカルに FastAPI のプロキシを立てて `ANTHROPIC_BASE_URL` をそこへ向け、31 のプロバイダに繋ぎ替えられるという作りで、設計は素直で丁寧です。名前が「free」ですが、無料 API を配ってくれるわけではなく、自分で取ったキーを Admin UI に入れて使います。無料枠のあるプロバイダも選べる、という意味の free です。

FCC のルーティング自体は決定論的です(`application/routing.py` を読みました。モデル名に `opus` / `sonnet` / `haiku` が含まれるかで振り分けるだけで、ランダムもラウンドロビンも入っていません)。問題はその外側にあります。

README が OpenRouter の例として挙げている `openrouter/free` は、OpenRouter 側が毎回ランダムに無料モデルを選ぶルーター です。OpenRouter の公式 API のモデル説明にそう書いてあります。「a router that selects free models at random」。つまりこの構成を使うと、さっきの応答を書いたモデルと、次の応答を書くモデルが違う。

さらに、ティア割り当ての例が `Opus → NVIDIA の Nemotron`、`Sonnet → openrouter/free`、`Haiku → LM Studio のローカルモデル` といった具合に散らばっています。Claude Code は内部で用途に応じて Opus / Sonnet / Haiku を呼び分けるので、1 つのタスクの中で 3 社のモデルが混ざることになります。

動きます。無料でも動きます。でも、その成果物は「Claude Code で作ったもの」ではなく「Claude Code の UI を被った何か」です。コードのスタイルも、ツールを呼ぶ判断も、途中で方針を変えるときの癖も、全部ばらばらになる。私が引っかかったのはここでした。

手触りを揃えるには

やることは 2 つだけです。

ひとつ、モデルを 1 つに固定する。ランダムルーターを使わない。フォールバックは持つけれど、それは「落ちたときの保険」であって「毎回どれかが当たる抽選」ではない。この記事の構成はそうなっています。

ふたつ、Opus の思考の型を持ったモデルを選ぶ。ここで出てくるのが Claude / Opus 蒸留の GGUF です。Hugging Face には Opus の推論トレースで追加学習した公開モデルが数十件あり、月間ダウンロードが 9 万件を超えるものもあります。何ができて何ができないかは後で数字つきで書きますが、少なくとも「Opus っぽい考え方の運び」は寄ります。

その 2 つを一貫して回すために、私は自作の CodeRouter を間に挟んでいます。

直結できるのに、なぜルーターを挟むのか

llama.cpp の `/v1/messages` は PR #17570 で入り、ggml-org の公式ブログで 2026 年 1 月 19 日に紹介されています。Ollama も v0.14.0 から Anthropic 互換を持っています。だから「Claude Code をローカルに向ける」だけなら、もうルーターは要りません。

問題は、その先で起きます。バックエンドが OOM で落ちればセッションはそこで終わり、長い会話でコンテキストが溢れれば 400 が返り、小さいモデルは tool call を平文の JSON として吐いて Claude Code 側で壊れます。どれも「動くか動かないか」ではなく「8 時間回るか」の話です。

CodeRouter がやっているのは、その隙間を埋める仕事です。壊れた tool call を Claude Code に届く前に tool_use ブロックへ復元し、バックエンドが落ちたら無料クラウドへ自動で切り替え、コンテキスト溢れと応答品質の劣化を検知して手当てする。加えて、この記事の主役でもある Launcher があります。ブラウザから GGUF を選んで `llama-server` を起動し、そのまま provider として登録するところまで面倒を見る UI です。

逆に言うと、短いセッションを直結で回して困っていないなら、ここから先は読まなくて大丈夫です。

全体の流れ

やることは 5 つです。llama.cpp をビルドして、GGUF を落として、CodeRouter を入れて、`providers.yaml` を自分の環境に合わせて直して、Launcher から起動する。

`llama-server` は手で叩いてもいいのですが、この記事では Launcher 経由で起動します。理由は後で書きますが、量子化やコンテキスト長を変えて試す回数が増えるほど、コマンドを手で組み直すのが事故のもとになるからです。

1. llama.cpp をビルドする(必要なものだけ)

最初にはっきりさせておきます。ビルドは1つで十分です。 自分の GPU に対応するものを1つ作れば、この記事の残りは全部通ります。

Mac なら素のビルドだけ(Metal は macOS で既定 ON なので、フラグを足す必要すらありません)。NVIDIA なら CUDA ビルドだけ。AMD なら ROCm か Vulkan のどちらか。それで終わりです。

複数作るのは、GPU が混在しているか、どのランタイムが速いか実測で比べたい場合だけ。あとで書きますが、私の環境では同じ GPU でもビルドによって結果が変わったので作り分けています。ただしこれは特殊な例で、最初の1回は 1 ビルドで始めてください。

まずリポジトリを取ってきます。置き場所は好みですが、この記事では `~/llm/apps/llama.cpp` に揃えます。

mkdir -p ~/llm/apps
git clone https://github.com/ggml-org/llama.cpp ~/llm/apps/llama.cpp
cd ~/llm/apps/llama.cpp

リポジトリは 2025 年 2 月に `ggerganov/llama.cpp` から `ggml-org/llama.cpp` へ移管されています。古い URL は GitHub のリダイレクトで今も通りますが、新しい方を使ってください。

いきなりハマるポイントを3つ

ビルドコマンドを書く前に、ネットに転がっている手順のうち 今は間違っているもの を先に潰しておきます。私も古い自分のドキュメントを直しました。自分に関係ないバックエンドの項目は読み飛ばして構いません。

`-DLLAMA_CURL=ON` は、もう効きません。libcurl は PR #18828 で削除され、HTTP スタックは cpp-httplib + OpenSSL に置き換わりました。現在のフラグは `-DLLAMA_OPENSSL`(既定 ON)で、Linux なら `libssl-dev` 系を先に入れておく必要があります。入っていないと `-hf` でのモデル取得が `'https' scheme is not supported` で落ちます。

RTX 5090 の CUDA アーキテクチャは 120(sm_120) です。100 ではありません。100 はデータセンター向けの B200 / GB200 系で、GeForce とは別物です。NVIDIA の CUDA GPUs 表で RTX 5090 / 5080 は Compute Capability 12.0、llama.cpp 側の `ggml/src/ggml-cuda/CMakeLists.txt` にも「120 == Blackwell, needs CUDA v12.8」とコメントが入っています。CUDA Toolkit 12.8 以上が要ります。

`--no-mmap` は deprecated になり、`-lm / --load-mode`(`none` / `mmap` / `mlock` / `mmap+mlock` / `dio`)に移りました。「Vulkan では `--no-mmap` が必須」という話を見かけたら疑ってください。Issue #18317 では build 7516 以降で Vulkan + `--no-mmap` がロード失敗する報告があり、回避策はむしろ mmap を使うことでした。

ビルドスクリプト

手で `cmake` を叩いてもいいのですが、あとで作り足したくなったとき用にスクリプトにしておきます。`~/llm/apps/llama.cpp/build-backends.sh` として置いて、`chmod +x` してください。必要な関数だけ残して、あとは消してしまって構いません。

#!/bin/bash
set -euo pipefail

JOBS=$(command -v nproc >/dev/null && nproc || sysctl -n hw.ncpu)
GENERATOR="Ninja"
BUILD_TYPE="Release"

# RTX 3090 = 86 / RTX 5090 (Blackwell) = 120。CUDA Toolkit 12.8+ が必要。
# 自動検出に任せるなら空文字にする。
CUDA_ARCHS="-DCMAKE_CUDA_ARCHITECTURES=86;120"

# 空 = GPU_TARGETS 未指定(自動検出)。gfx1100 / gfx1151 等を直接指定も可。
ROCM_GPU_TARGETS=""

COMMON_FLAGS=(
  -G "${GENERATOR}"
  -DCMAKE_BUILD_TYPE="${BUILD_TYPE}"
  -DLLAMA_BUILD_TESTS=OFF
  -DLLAMA_BUILD_EXAMPLES=OFF
)

build_base() {
  # 素のビルド。macOS では Metal が既定 ON なのでこれが Metal ビルドになる。
  cmake -S . -B build "${COMMON_FLAGS[@]}" "$@"
  cmake --build build --config "${BUILD_TYPE}" -j"${JOBS}"
}

build_cuda() {
  local arch=()
  [[ -n "${CUDA_ARCHS}" ]] && arch=(${CUDA_ARCHS})
  cmake -S . -B build-cuda "${COMMON_FLAGS[@]}" -DGGML_CUDA=ON "${arch[@]}" "$@"
  cmake --build build-cuda --config "${BUILD_TYPE}" -j"${JOBS}"
}

build_vulkan() {
  cmake -S . -B build-vulkan "${COMMON_FLAGS[@]}" -DGGML_VULKAN=ON "$@"
  cmake --build build-vulkan --config "${BUILD_TYPE}" -j"${JOBS}"
}

build_rocm() {
  command -v hipconfig >/dev/null || { echo "hipconfig が無い。ROCm を入れてください"; exit 1; }
  export HIPCXX="$(hipconfig -l)/clang"
  export HIP_PATH="$(hipconfig -R)"
  local targets=()
  [[ -n "${ROCM_GPU_TARGETS}" ]] && targets=(-DGPU_TARGETS="${ROCM_GPU_TARGETS}")
  cmake -S . -B build-rocm "${COMMON_FLAGS[@]}" -DGGML_HIP=ON "${targets[@]}" "$@"
  cmake --build build-rocm --config "${BUILD_TYPE}" -j"${JOBS}"
}

呼び出し側は引数で `base` / `cuda` / `vulkan` / `rocm` を受けて、`--clean` なら該当ディレクトリを消してから、`--pull` なら `git pull --ff-only` してから走らせる、という素直な作りにしてあります。引数を省略したときは `base` だけ。`all` を明示したときだけ 4 つ全部です。

./build-backends.sh              # 素のビルドだけ(Mac はこれで Metal)
./build-backends.sh cuda         # CUDA だけ
./build-backends.sh rocm         # ROCm だけ
./build-backends.sh --pull cuda  # git pull してから CUDA を作り直す

できあがるディレクトリは、素のビルドが `build/`、以下 `build-cuda/`、`build-vulkan/`、`build-rocm/`。実行ファイルはそれぞれ `bin/llama-server` に出ます。`-DLLAMA_BUILD_EXAMPLES=OFF` を付けていますが、`llama-server` は `tools/` 配下なので消えません。

ビルドが通ったら `./build-cuda/bin/llama-server --version` で確認してください。ここまで来れば山は越えです。

複数作るのは、比べたいときだけ

ここは飛ばして構わない話ですが、なぜ作り分けの仕組みを用意しているかだけ書いておきます。

同じ GPU でも、ビルドによって速い遅いが変わるからです。私の手元(Ryzen AI Max+ 395 の箱に RTX 5090 と RTX 3090 を足した 3 GPU 構成)で条件を揃えて測ったところ、5090 では CUDA が最速で Vulkan がその 89%、3090 では逆に Vulkan の方がわずかに速く、内蔵 Radeon では ROCm と Vulkan がほぼ横並びでした。「NVIDIA なら CUDA 一択」でも「Vulkan は遅い」でもありません。

そしてもう一つ厄介なのが、デバイス ID の名前空間がビルドごとに別だということ。同じ RTX 3090 が CUDA ビルドでは `CUDA1`、Vulkan ビルドでは `Vulkan0` になります。GPU が 1 枚なら気にしなくていい話です。

2. GGUF を落とす

コマンド名が変わっています

`huggingface-cli download ...` と書いてある記事は全部古いです。huggingface_hub v1.0.0(2025 年 10 月 27 日)で `huggingface-cli` は機能を削除され、実行しても「`huggingface-cli` is deprecated and no longer works. Use `hf` instead.」と出て終わります。実行ファイル自体は残っているので、余計にたちが悪い。

uv tool install huggingface_hub
# → hf / huggingface-cli / tiny-agents が入るが、使うのは hf だけ

どのモデルを選ぶか

VRAM(統合メモリなら空きメモリ)から逆算します。Q4 系なら、モデルのファイルサイズ + KV キャッシュ + OS と IDE の分、で見積もってください。ファイルサイズぴったりに詰めると必ずスワップします。

16〜24GB クラスなら `unsloth/Qwen3-Coder-30B-A3B-Instruct-GGUF` が現実解です。MoE で総 30B / 活性 3B、`UD-Q4_K_XL` が 17.7GB。Hugging Face の月間ダウンロードが 380 万件と、この用途では群を抜いて実績があります。

もう少し積めるなら `unsloth/Qwen3.6-35B-A3B-GGUF`(`UD-Q4_K_XL` で 22.4GB)。ネイティブ 262K コンテキストで、モデルカードは「思考能力を保つため最低 128K」を推奨しています。同系列の dense 版 `unsloth/Qwen3.6-27B-GGUF`(17.6GB)は MoE を避けたいときに。

`unsloth/Devstral-Small-2-24B-Instruct-2512-GGUF`(14.5GB、Apache 2.0、SWE-bench Verified 68.0%)と `unsloth/gemma-4-26B-A4B-it-GGUF`(17.0GB)も候補です。10GB そこそこしか割けないなら `unsloth/gpt-oss-20b-GGUF`(11.9GB)。これは Ollama の公式ブログが Claude Code 用として名指しで挙げているモデルでもあります。

「UD-」で始まるのは Unsloth Dynamic Quant で、モデルごとに量子化スキームを設計し直したもの。同じビット幅の素の量子化より精度が出るというのが公式の主張です。同じリポジトリに `UD-Q4_K_M` と `UD-Q4_K_XL` が並んでいることがありますが、Qwen3.6-35B-A3B で実測した差は 0.3GB 程度でした。載るなら XL でいいと思います。

Opus 蒸留 GGUF という選択肢

冒頭の「手触りを揃える」に戻ります。Hugging Face には Claude / Opus の推論トレースで追加学習した公開モデルが数十件あります。ダウンロード数が大きいものから並べると、こうなります。

`Jackrong/Qwen3.5-27B-Claude-4.6-Opus-Reasoning-Distilled-GGUF` が月間 93,280 件で頭ひとつ抜けています。本体(非 GGUF)も 73,316 件、likes 2,926。Qwen3.5-27B をベースに Claude 4.6 Opus の思考トレースで学習したもので、Claude Code や OpenCode が送る `developer` ロールで公式モデルが落ちる問題を、Jinja テンプレート側で直してあるのが実務的にありがたい点です。コミュニティ報告では Q4_K_M で約 16.5GB、262K コンテキストがそのまま通るとされています(RTX 3090 での投稿者報告で、再現手順は非公開)。

新しいベースを使いたいなら `hesamation/Qwen3.6-35B-A3B-Claude-4.6-Opus-Reasoning-Distilled-GGUF`(月間 39,997 件)や `lordx64/Qwen3.6-35B-A3B-Claude-4.7-Opus-Reasoning-Distilled`(Opus 4.7 由来、7,595 件)。Gemma 系が好みなら `TeichAI/gemma-4-31B-it-Claude-Opus-Distill-v2-GGUF`、GLM 系なら `TeichAI/GLM-4.7-Flash-Claude-Opus-4.5-High-Reasoning-Distill-GGUF`(likes 510)もあります。

ただし、期待の置きどころを間違えないこと

ここは正直に書きます。この界隈で言う「蒸留」は、logits を使った本来の知識蒸留ではありません。 数十ドル分の Claude API を叩いて思考文を数千件集め、それで LoRA-SFT しているだけです。

数字で見ると分かりやすい。lordx64 のモデルカードは、学習可能パラメータが 35.1B 中 3.44M(0.01%)、LoRA は attention のみ、と正直に書いています。Jackrong 版でも 1.31%。そして同じカードにこう書いてあります。「Reasoning ≠ knowledge. Distillation transfers how to reason, not new facts.」ベースの Qwen が知らないことは、蒸留しても知らないままです。

私が調べた範囲で、SWE-bench や Terminal-Bench といったエージェント系コーディングのスコアを載せている Claude 蒸留モデルは 1 件もありませんでした。 載っているのは MMLU-Pro(しかもある版は 70 問)や GSM8K の自己申告です。hesamation のカードに至っては、自分の測定値ではなくベースの Qwen3.6-35B-A3B のベンチ表(SWE-bench Verified 73.4 など)を転載したうえで、目的は「Qwen3.6 の強いエージェント性能を保ちつつ、Opus 風の構造化された推論トレースに寄せること」だと書いています。

つまり、エージェントとしての実力はベースモデルが持っていて、蒸留が足すのは思考の書式と語り口。ここを取り違えなければ、蒸留モデルは有効な選択です。私の使い方も「ベースは agentic coding が強いものを選び、そのうえで Opus 蒸留版があればそちらを使う」で落ち着いています。

もう 1 点、触れておくべきことがあります。Anthropic の Usage Policy(2025 年 9 月 15 日発効)は、"Do Not Abuse our Platform" の項で「Utilization of inputs and outputs to train an AI model (e.g., "model scraping" or "model distillation") without prior authorization from Anthropic」を挙げています。Commercial Terms の D.4 と Consumer Terms にも同趣旨の条項があります。公開済みの重みを個人が動かすことと、蒸留データを作ることは別の行為ですが、このエコシステムがそういう土台の上にあることは知っておいてください。実際、調べた中でこの点に自分から言及していたモデルカードは lordx64 の 1 件だけでした。

なお、エージェント特化を謳う `LocoreMind/LocoOperator-4B` も見かけますが、コンテキストが 16,384 トークンしかなく、後述する Claude Code の要求量に届きません。

落とす

# エージェント性能を優先する場合
hf download unsloth/Qwen3-Coder-30B-A3B-Instruct-GGUF \
  --include "*UD-Q4_K_XL*" "*tokenizer*" \
  --local-dir ~/llm/models/qwen3-coder-30b-a3b

# Opus 蒸留版を試す場合(Claude Code の developer ロール対応込み)
hf download Jackrong/Qwen3.5-27B-Claude-4.6-Opus-Reasoning-Distilled-GGUF \
  --include "*Q4_K_M*" \
  --local-dir ~/llm/models/qwen3.5-27b-opus-distill

両方落として、同じタスクを投げて比べるのがいちばん早いです。Launcher を使えばモデルの切り替えはドロップダウン 1 つなので、この比較のコストはかなり低くなります。

CodeRouter 同梱の `gguf_dl.py` を使うと、Hugging Face のページ URL をそのまま貼るだけで済みます。`hf download` は repo_id 形式しか受け付けないので、ブラウザから持ってくるときはこちらが楽です。

python gguf_dl.py https://huggingface.co/unsloth/Qwen3-Coder-30B-A3B-Instruct-GGUF -p "*UD-Q4_K_XL*"
python gguf_dl.py <repo_id> --list    # 中身を見るだけ
python gguf_dl.py                     # 引数なしで対話モード

3. CodeRouter を入れる

mkdir -p ~/.coderouter
curl -fsSL https://raw.githubusercontent.com/zephel01/CodeRouter/main/examples/providers.llamacpp-vllm.yaml \
  > ~/.coderouter/providers.yaml

uvx --from coderouter-cli coderouter serve --port 8088

Python 3.12 以上が要ります。毎回 `uvx` を通すのが煩わしければ `uv tool install coderouter-cli` で恒久インストールしてください。

`examples/providers.yaml` ではなく `examples/providers.llamacpp-vllm.yaml` を落としているのが今回のポイントです。こちらは Ollama を前提にしない、llama.cpp / vLLM + Launcher 用の最小構成になっています。

この `curl` の 1 行が、実は今回いちばん事故を減らします。設定ファイルはゼロから書かず、動く状態のものをコピーしてきて必要な箇所だけ直す。次の節はその「必要な箇所」の話です。

4. providers.yaml を直す(ゼロから書かない)

ここで一番言いたいのは、`providers.yaml` は手書きしないでください ということです。さっき `examples/providers.llamacpp-vllm.yaml` をコピーしたのは、まさにそのためでした。

YAML はインデント 1 つで壊れますし、`capabilities` の書き忘れや `kind` のスペルミスは、起動時ではなく実際にリクエストが飛んだときに変な形で出てきます。同梱の example には、動く状態の provider 定義とプロファイルとコメントが全部入っています。やることは、コピーしたファイルの必要な行を書き換えるか、コメントを外すか、それだけです。

編集するのは 2 か所です。まず `launcher.model_dirs` を自分の GGUF 置き場に。

launcher:
  model_dirs:
    - ~/llm/models          # .gguf を再帰スキャン

次に `backends`。example には最初からこう書いてあります。

  backends:
    llama.cpp:
      binary: null          # null = PATH の llama-server を使用
      # binary: ~/llama.cpp/build/bin/llama-server   # ソースビルド例

ソースからビルドしたので、`binary` を自分のパスに直します。ここだけです。

    llama.cpp:
      binary: ~/llm/apps/llama.cpp/build/bin/llama-server

複数ビルドを作った人だけ、コメントを外す

example の少し下に、こんなブロックがコメントアウトされて入っています。

    # llama.cpp-cuda:
    #   binary: ~/llm/apps/llama.cpp/build-cuda/bin/llama-server
    # llama.cpp-vulkan:
    #   binary: ~/llm/apps/llama.cpp/build-vulkan/bin/llama-server
    # llama.cpp-rocm:
    #   binary: ~/llm/apps/llama.cpp/build-rocm/bin/llama-server

`llama.cpp-cuda` のような「基底名 + バリアント」のキーが v2.11.0 で入った機能です。実際にビルドした行のコメントだけ外してください。 ここに書いたビルドが Launcher の「バックエンド」セレクトに増え、起動のたびにどれを使うか選べます。何も外さなければセレクトは従来どおりで、余計な選択肢は出ません。

バリアントには `binary` が必須です。省略できてしまうと、CUDA ビルドを選んだつもりで PATH の素の `llama-server` が動く——この記事で一番気づきにくい事故——が起きるので、設定ロード時にエラーにしてあります。同じ理由で、キーのスペルミス(`llamacpp:` など)も v2.11.0 から起動時エラーになります。手書きしないほうがいい理由の一つがこれです。

ビルドを切り替えるとデバイス選択は自動でクリアされます。`CUDA0` と `Vulkan0` は同じ GPU ではないからです。存在しないデバイス ID を投げた場合も 400 で弾きます。

オプションプロファイルは、そのまま使える

example の `option_profiles` には「GPU フル活用」「VRAM 節約」「CPU のみ」「Apple Silicon M-series」「長コンテキスト (128K)」などが最初から並んでいます。Launcher の起動フォームでドロップダウンから選ぶだけなので、ここも基本は触りません。

  option_profiles:
    llama.cpp:
      - name: "GPU フル活用"
        args:
          "-ngl": 99
          "--ctx-size": 65536
          "--batch-size": 512

VRAM に合わせて `--ctx-size` の数字をいじる、くらいの編集で足ります。基底名 `llama.cpp` に書いたプロファイルは全バリアントに継承されるので、ビルドを増やしても同じ内容をコピペする必要はありません。

`--device` と `--tensor-split` はプロファイルに書かないでください。デバイスは UI の「🔍 検出」で選ぶのが正しい流れで、両方から指定すると argv に `--device` が二重に載ります。

`--ctx-size` の話をさせてください

ここが初心者が最初に踏む地雷です。Claude Code は毎ターン、かなり大きな system prompt を送ります。Ollama の公式ブログは「最低 32K トークンのコンテキスト長を持つモデルで動かすこと」を推奨していますし、Claude Code の GitHub Issue #52979 には、空のフォルダで「hi」と打っただけで約 31,000 トークン消費したというユーザー報告が上がっています(Anthropic からの公式回答は付いていません)。

`--ctx-size` が足りないと `llama-server` が 400 を返し、CodeRouter からは provider-failed → 502 に見えます。だから同梱プロファイルは既定を 32768 以上にしてあります。4096 では Claude Code の system prompt がそもそも入りません。

そして `--ctx-size` は 全スロットの合計 です。`--parallel 4` を付けたら 1 スロットあたりは 4 分の 1 になります。ベンチのつもりで並列数だけ変えると、実効コンテキストが変わって比較が成立しなくなります。

5. Launcher から起動する

coderouter serve --port 8088

ブラウザで `http://localhost:8088/launcher` を開きます。あとは、モデルを選ぶ、バックエンド(`llama.cpp-cuda` など)を選ぶ、オプションプロファイルを選ぶ、「▶ 起動」。それだけです。

起動したバックエンドは `launcher-llamacpp-8085` のような名前で provider として自動登録されます(v2.7.4 以降、メモリ内のみ)。`providers.yaml` を編集し直す必要はありません。GGUF を差し替えても、`model: ""` の provider は `/v1/models` が上流のロード済みモデル ID をそのまま返すので、設定はそのままで通ります。

ブラウザを開きたくなければデスクトップ GUI 版もあります。リポジトリ直下で `uv run python launcher_gui.py`。CodeRouter 自体もそこから起動できて、接続文字列がウィンドウ上部に出ます。

手で `llama-server` を叩きたい人のために、等価なコマンドも置いておきます。

~/llm/apps/llama.cpp/build-cuda/bin/llama-server \
  --model ~/llm/models/qwen3-coder-30b-a3b/Qwen3-Coder-30B-A3B-Instruct-UD-Q4_K_XL.gguf \
  --host 127.0.0.1 \
  --port 8080 \
  --ctx-size 32768 \
  --n-predict 4096 \
  -ngl 99

`--jinja` を書いていないことに気づいた方へ。現行の master では `llama-server` の jinja は 既定で有効 です(`common/common.h` の `use_jinja = true`)。無効にするフラグの方が `--no-jinja` として存在します。ただし公式ドキュメントの文面は今も「`--jinja` flag が必要」のままなので、明示的に付けておいても害はありません。付けてはいけないのは `--no-jinja` の方で、これを付けると `tools` パラメータが「tools param requires --jinja flag」で例外になります。

6. Claude Code をつなぐ

export ANTHROPIC_BASE_URL=http://localhost:8088
export ANTHROPIC_AUTH_TOKEN=dummy
claude

これで Claude Code が立ち上がり、裏でローカルの GGUF が答えます。VSCode の統合ターミナルから使うなら、プロジェクトルートで `coderouter vscode-init` を一度叩くと `.vscode/settings.json` に環境変数がマージ書き込みされるので、以後は `claude` と打つだけになります。

動いているか確かめる

雰囲気で「動いた気がする」と判断しないための道具が 2 つあります。

coderouter doctor --check-model <provider名>

7 つのプローブが走ります。見るべきは 3 番の `tool_calls` が `[OK]` になるかどうか。ここが `[NEEDS TUNING]` なら、Claude Code でファイル編集を頼んでも高確率で空振りします。

もう一つが `http://localhost:8088/dashboard` です。今どの provider に流れているか、ガードが何回発火したか、コストがいくら乗っているかがリアルタイムで見えます。開きっぱなしにしておくと、大抵の不調は 10 秒で原因が分かります。

curl で直接叩いて確かめたいなら、`tools` を含むリクエストを投げて `finish_reason: "tool_calls"` が返るかを見るのが確実です。

完全に 0 円で回すためのフォールバック設計

ローカルだけだと、GPU が埋まっている間や OOM で落ちた瞬間に手が止まります。かといって有料 API に落とすと 0 円ではなくなる。そこで、ローカル → 無料クラウド、の 2 段にします。

ここでもゼロから書きません。フル版の `examples/providers.yaml` に `openrouter-free` の provider 定義がそのまま入っているので、そのブロックを自分の `~/.coderouter/providers.yaml` に貼り付けて、プロファイルの `providers:` リストに名前を足すだけです。

profiles:
  - name: claude-code
    providers: [llama-cpp-local, openrouter-free]   # ← 名前を足すだけ

貼り付けたあとに 1 か所だけ直してください。`model:` の行です。

以前の私の記事にも同梱の example にも出てくる `qwen/qwen3-coder:free` は、2026 年 8 月 2 日時点でもう使えません。OpenRouter の API を叩くとモデルのメタデータは残っているのに `endpoints` が空、つまり稼働プロバイダがゼロです。無料モデル一覧(現在 14 件)にも入っていません。同じ理由で `openai/gpt-oss-120b:free` も現在の一覧に無く、生きているのは 20B 版のほうです。

    model: openai/gpt-oss-20b:free   # qwen/qwen3-coder:free から差し替え

無料枠の顔ぶれは半年で入れ替わります。設定例の slug が生きているかどうかは、`https://openrouter.ai/api/v1/models` を一度自分の目で確認するのが確実です。

同日時点で tool calling に対応した `:free` モデルは、`openai/gpt-oss-20b:free`(131K)、`cohere/north-mini-code:free`(256K)、`google/gemma-4-26b-a4b-it:free`(262K)、`poolside/laguna-s-2.1:free`(262K)、NVIDIA の Nemotron 3 系(256K〜1M)などです。Qwen 系の `:free` は 1 件も残っていません。

レート制限は、無料モデル共通で 20 リクエスト/分。加えて購入クレジットが 10 未満なら 50 リクエスト/日、10 以上なら 1,000 リクエスト/日です。「1 円も払わない」なら 1 日 50 リクエストが天井になるので、フォールバックはあくまで保険と考えてください。主戦場はローカルです。

有料 provider は、明示的に `paid: true` を書いて opt-in しない限り使われません。ここは事故ると財布に直撃するので、CodeRouter は既定で無料のみに倒してあります。

つまずいたら見るところ

`-ngl` を確認してください。バックエンドに ROCm や CUDA を選んでいても、`-ngl 0` ならモデルは GPU に載りません。私はこれで「ROCm は Vulkan より遅い」という嘘の結論を一度出しました。実際には CPU と GPU を比べていただけです。

返答が空、または意味不明なら、コンテキスト長を疑ってください。前述の 32K 未満問題か、`--parallel` で 1 スロットあたりが削られているかのどちらかであることが多いです。

`<think>` タグが本文に漏れてくるなら、provider に `output_filters: [strip_thinking]` を足します。thinking 系モデルではほぼ必須です。

Launcher の起動ボタンがグレーアウトしているときは、`backends.<name>.binary` のパスが解決できていません。バリアントは `binary` 必須なので、ビルドしていないバックエンドの行は消してしまうのが早いです。

結局いくらかかるのか

Claude Code 本体、CodeRouter、llama.cpp、GGUF、ここまで全部無料です。Anthropic の API キーは使いません。かかるのは電気代と、GPU を買った過去の自分への支払いだけ。

そのうえで、正直に書いておきたいことが 2 つあります。ひとつは、ローカルの 30B クラスは Claude Opus の代わりにはならないということ。Opus 蒸留を挟んでも、長い設計判断やアーキテクチャの相談で差が消えるわけではありません。蒸留が寄せてくれるのは考え方の運びであって、知らないことは知らないままです。

もうひとつは、それでも「決まった形の編集を大量に回す」「深夜に無人で流す」「機密で外に出せないコードを触る」といった用途では、十分すぎるほど実用になるということ。そしてそこで効いてくるのが、冒頭に書いた一貫性です。毎回違うモデルが答える環境では、この 3 つはどれも成立しません。

私の使い分けは、考える仕事はクラウド、手を動かす仕事はローカル、に落ち着きました。CodeRouter の言語税トラッキングを入れてからは、日本語比率の高いターンを自動でローカルへ逃がしています。日本語はクラウドのトークナイザだと英語の 1.6〜2.0 倍のトークンを食うので、ここを削るだけでも効きます。

次にやること

まず自分の VRAM に合う GGUF を 1 つ落として、`coderouter doctor --check-model` で `tool_calls [OK]` を出すところまで。ここが通れば残りは設定の話です。

そのあと、同じ VRAM 帯の「素のコーディングモデル」と「Opus 蒸留モデル」を 1 本ずつ落として、同じタスクを投げてみてください。速度ではなく、返ってくる文章の運びと、ツールを呼ぶ判断の順番を見比べる。私が「揃った」と感じたのはそこでした。

複数ビルドを作った人は、Launcher の「⚙ ビルド横断」スイープも一度回してみてください。同じモデルを CUDA / Vulkan / ROCm で順に起動して比較してくれます。手持ちのモデルとハードの組み合わせで、どれが速いかは事前には分かりません。

みなさんの環境ではどうなるか、特に「この蒸留モデルは Claude Code の癖に合った」「この量子化で tool calling が壊れた」といった話があれば、コメントで教えてください。蒸留モデルはベンチが出そろっていない領域なので、実際に使った人の感触がいちばんの情報になります。

GitHub: https://github.com/zephel01/CodeRouter

#ローカルLLM #llamacpp #ClaudeCode #CodeRouter #GGUF #蒸留モデル #Qwen3 #Unsloth #OpenRouter #個人開発 #生成AI

いいなと思ったら応援しよう!

zephel01 サーバー代とコーヒー代になります☕ 役に立ったら応援よろしくお願いします!