Qwen Code ローカル運用実践記 — Mac Studio M3 Ultra で Ollama + qwen3-coder:30b を動かして分かったこと
Qwen Code(Alibaba Cloud Qwen チームが開発したオープンソース CLI コーディングエージェント)を Mac Studio M3 Ultra(96GB)上で Ollama と組み合わせてローカル運用を試みた実践記録です。環境構築からツール呼び出しの限界まで、実際に手を動かして検証した結果をまとめます。
背景と目的
Claude Code は強力ですが、コードがクラウドに送信されるためプライバシーの懸念があります。Qwen Code は Apache 2.0 ライセンスのオープンソースで、Ollama と組み合わせれば完全ローカルで動作するため、機密コードベースでの利用が期待されます。
本記事の検証環境:
| 項目 | スペック |
|---|---|
| マシン | Mac Studio M3 Ultra |
| メモリ | 96GB ユニファイドメモリ |
| メモリ帯域 | 800 GB/s |
| Ollama | v0.15.6 |
| Qwen Code | v0.12.0(Fork からローカルビルド) |
| モデル | qwen3-coder:30b (18GB) |
ステップ1: リポジトリの Fork と Clone
調査・改造を前提に、まず QwenLM/qwen-code を Fork しました。
| |
ブランチ戦略:
upstream/main ──sync──→ fork/main ──merge──→ fork/devel(作業用)
main を upstream と同期させ、devel で自由に作業する構成です。
ステップ2: Ollama のモデルダウンロード
Ollama は導入済みだったため、Qwen モデルのダウンロードのみ実行しました。
| |
メモリ別の推奨モデル
| Mac | メモリ | 推奨モデル | 推論速度 |
|---|---|---|---|
| M4 | 16GB | qwen3:8b | 28-35 tok/s |
| M4 Pro | 24GB | qwen3-coder:14b | 25-30 tok/s |
| M4 Pro | 48GB | qwen3-coder:30b | 12-18 tok/s |
| M3 Ultra | 96GB | qwen3-coder:30b | 25-35 tok/s |
M3 Ultra の 800 GB/s メモリ帯域は LLM 推論に大きなアドバンテージがあり、M4 Pro(273 GB/s)の約3倍の速度が出ます。
動作確認
| |
正常にコードが生成されることを確認しました。
ステップ3: Qwen Code のビルド
| |
トラブル: Xcode ライセンス
make install 実行時に以下のエラーが発生しました:
You have not agreed to the Xcode license agreements.
Please run 'sudo xcodebuild -license' from within a Terminal window
sudo xcodebuild -license を実行してライセンスに同意した後、再度 make install で解決しました。
ステップ4: settings.json の設定 — 3回の試行錯誤
ここが最も苦労した部分です。Qwen Code の設定ファイル形式はドキュメントが不十分で、ソースコードを読んで正しい形式を特定する必要がありました。
試行1: 失敗 — 設定形式が不正
| |
エラー: TypeError: Cannot read properties of undefined (reading 'model')
原因: providers というキーは存在せず、modelProviders が正しいキー名。selectedType の値も openai-compatible ではなく openai。
試行2: 失敗 — ログインを求められる
| |
問題: 起動時に Qwen OAuth のログイン画面が表示される。selectedType が外部プロセスによって削除される現象も発生。
試行3: 失敗 — envKey 不足
ヘッドレスモードで --auth-type openai を明示的に指定しても:
Missing credentials for modelProviders model 'qwen3-coder:30b'.
Configure modelProviders.openai[].envKey and set that environment variable.
最終的な正解の設定
ソースコード(packages/cli/src/config/settingsSchema.ts、packages/core/src/models/modelConfigResolver.ts)を読み解いた結果、以下の設定に到達しました。
| |
設定のポイント
| キー | 正しい値 | 間違いやすい値 |
|---|---|---|
modelProviders | authType をキーにした配列 | providers は不正 |
security.auth.selectedType | openai(AuthType enum 値) | openai-compatible は不正 |
modelProviders[].envKey | OPENAI_API_KEY(必須) | 省略するとエラー |
env.OPENAI_API_KEY | EMPTY(Ollama はキー不要だがフィールドは必須) | 省略するとエラー |
ソースコードから読み解いた設定の優先順位
modelProvider > CLI引数 > 環境変数 > settings.json > デフォルト値
API キーの解決順序(packages/cli/src/utils/modelConfigUtils.ts):
argv.openaiApiKey > env[modelProvider.envKey] > OPENAI_API_KEY > settings.security.auth.apiKey
ステップ5: 起動と動作確認
エイリアスの設定
毎回 OPENAI_API_KEY=EMPTY を付けるのは面倒なので、.zshrc にエイリアスを追加しました。
| |
グローバルに OPENAI_API_KEY=EMPTY を設定すると、将来 OpenAI API を使う際に影響するため、エイリアス方式を選択しました。
動作確認
| |
日本語の指示理解、コード生成ともに問題なく動作しました。
ステップ6: 複雑なタスクでの限界 — ツール呼び出しの問題
PRレビューを依頼した結果
対話モードで以下を指示しました:
gh pr diff 8891 の内容を取得して、コードをレビューしてください
期待した動作: Qwen Code の shell ツールで gh pr diff 8891 を実行し、差分を取得してレビュー
実際の動作: モデルが XML テキストを出力
| |
モデルがツール呼び出し API を使わず、Claude のツール呼び出し形式をテキストとして模倣してしまいました。
原因の調査
Ollama の API レベルではツール呼び出しが正常に動作することを確認済みです:
| |
API レベルでは問題ないのに、Qwen Code 上では XML テキストが出力される。
根本原因
30B モデルの推論能力の限界です。
| タスクの複雑度 | 30B ローカル | Claude Code |
|---|---|---|
| 単純なコード生成 | 正常にツール使用 | 正常 |
| ファイル編集 | 正常にツール使用 | 正常 |
| 「PRを取得してレビュー」 | ツール呼び出しに失敗(XML模倣) | 正常 |
| マルチステップの調査 | 困難 | 正常 |
単純なタスクではツール呼び出し API を正しく使えますが、「PRを取得 → diff を解析 → レビューコメントを生成」のようなマルチステップのエージェントタスクになると、30B モデルではツール呼び出しのチェーンを正確に制御できません。
Qwen Code と Claude Code — 実用上の比較
ベンチマーク(SWE-bench)
| 構成 | スコア |
|---|---|
| Claude Sonnet 4 + Claude Code | 70.4% |
| Qwen3-Coder + OpenHands(500ターン) | 69.6% |
| Qwen3-Coder(標準) | 67.0% |
ベンチマークスコアは近いですが、実際のエージェントタスクでの体験は大きく異なります。
実用比較
| タスク | Qwen Code(ローカル30B) | Claude Code |
|---|---|---|
| 関数の生成・編集 | 実用的 | 優秀 |
| テスト作成 | 実用的 | 優秀 |
| 日本語での指示理解 | 良好 | 優秀 |
| バグ修正 | 簡単なものは可能 | 複雑なものも対応 |
| PR レビュー(gh連携) | 不可(ツール呼び出し失敗) | 正常動作 |
| 複数ファイルの横断調査 | 不安定 | 安定 |
| MCP サーバー連携 | 未検証 | 安定 |
使い分けの指針
タスクの複雑度
│
├── 単純(コード生成、ファイル編集、テスト作成)
│ └── Qwen Code(ローカル)で十分
│ メリット: 無料、プライバシー、オフライン対応
│
└── 複雑(PR レビュー、マルチステップ調査、大規模リファクタ)
└── Claude Code を使用
メリット: 高い推論能力、安定したツール呼び出し
まとめ
- Mac Studio M3 Ultra(96GB)で Qwen Code + Ollama のローカル運用環境を構築: Fork → ローカルビルド → Ollama 接続まで約1時間で完了
- settings.json の設定が最大のハードル: ドキュメントが不十分で、ソースコード(settingsSchema.ts、modelConfigResolver.ts)を読み解く必要があった。
modelProviders(providersではない)、selectedType: "openai"(openai-compatibleではない)、envKey必須がポイント - 単純なコード生成は実用的: 日本語指示の理解、Python/TypeScript のコード生成は問題なく動作
- 複雑なエージェントタスクは30Bモデルの限界: PR レビューのようなマルチステップタスクでは、ツール呼び出しに失敗しテキストで XML を模倣する現象が発生
- API レベルではツール呼び出しは正常: Ollama の
/v1エンドポイントでの tool_calls は正しく動作しており、問題はモデルの推論能力 - Claude Code との使い分けが現実的: 単純タスク(プライバシー重視)→ Qwen Code ローカル、複雑タスク → Claude Code
今後の検証予定
- Qwen OAuth(クラウドの大規模モデル)での PR レビュー動作確認
- MCP サーバー(GitHub)追加によるツール能力の補完
- qwen3-coder の更新版での改善確認
- Qwen-Agent フレームワークでのカスタムエージェント構築