OpenCode DesktopでローカルLLMとチャットする環境を構築する方法
今回は、ゲーミングPCで動かしているローカルLLMのQwen3.8-27Bを、OpenCode Desktopからチャット形式で使えるようにした手順を紹介し ます。
前回の記事で紹介した Qwenの導入構成は、Claude Codeなどがオーケストレーターとしてが裏で呼び出すAPIに近い構造でした。
ただ、ClaudeやCodexが5時間制限などで使えない間は Qwenも使えない依存関係になってしまうため、ちょっとした調査や、既存コードの読解や簡単なリファクタリングといった、利用枠を消費するのがもったいない類の作業は直接実行したくなります。
そこで、ちょっとした小間使い的なタスクを直接実行できるよう、チャット形式で対話的に動かせるように環境構築をやってみた、という自由研究です。
なお、このブログの筆者の本業はプロダクトデザイナーで、ローカルLLMの運用については素人です。設定の大半はClaudeやCodexに調査と実装をさせながら進めたもので、2026年9月時点の情報である点にご留意ください。
この記事のターゲット
ローカルLLMに興味があり、チャットの画面から使いたい方
Claude CodeやCodexの利用枠を、調べ物や下書きで消費したくない方
実際ローカルLLMはどのくらいの実用性があるか知りたい方
なぜOpenCode Desktopなのか
ローカルLLMとチャットする、という手段に関しては選択肢はいくつかありますが、今回はコードの編集やテストの実行までさせたかったので、コーディングエージェントとしての機能を持つデスクトップアプリに絞って、以下の4つを公式情報のカタログスペックと、技術者のSNSやコミュニティの報告をソースにFable5に比較させました。
Qwen Code Desktop
Qwen公式のデスクトップ版です。27Bクラスのローカルモデルでツール呼び出しが不安定になるという報告がGitHubのissueに複数あり
Claude Desktop
接続先をローカルに向ける環境変数をデスクトップ側が上書きしてしまうという報告あり
Codex app
Codexは2026年2月にChat Completions形式を廃止してResponses形式のみになりましたが、llama-serverはResponses形式に未対応。
OpenCode Desktop
ターミナル版のOpenCodeと設定ファイルを共有します。OpenAI互換のサーバーであれば何でもつなげるので、llama-serverもそのまま使える
ただし、上記は8月末時点の調査状況のため、現在は解消・改善しているものもあると思います。
既存のClaude Codeから呼び出す裏方の仕組みでは、すでにOpenCodeのターミナル版をハーネスとして使っていました。同じ設定を流用できるという点で、OpenCode Desktopを使用することにしました。
構成の全体像は以下の通りです。

OpenCode Desktopをインストールする
macOSであればHomebrewで入ります。
執筆時点ではベータ版で、バージョンは1.18.27でした。Electron製のアプリで、中にターミナル版と同じサーバー本体を同梱しています。
設定ファイルにllama-serverを登録する
設定ファイルは ~/.config/opencode/opencode.json です。ターミナル版のOpenCodeを使っている場合は同じファイルを読みます。ローカルのQwenをつなぐ最小の設定は以下の通りです。
気をつけるポイント
まず、npm にはOpenAI互換のプロバイダーを指定します。llama-serverはOpenAI互換のAPIを持っているので、これで接続できます。
次に、接続先とAPIキーは {env:変数名} の形で書きます。設定ファイルに値を直接書かず、起動時の環境変数から読ませるためです。この書き方には落とし穴があるので、次項で説明します。
最後に、文脈長の上限はサーバー側より少し小さく書きます。私のllama-serverは64Kトークンで動かしていますが、設定では61,440にしています。上限ぴったりにすると、システムプロンプトの分で溢れるので、そのバッファです。
permission はファイル編集・コマンド実行・Web取得のそれぞれを「毎回確認する」に設定しています。ローカルとはいえ、得体の知れないモデルに黙ってファイルを書き換えさせるの はまだ怖いので、最初はすべて確認にしておくのが無難です。
起動はDockからではなくスクリプトから行う
ここが一番はまった箇所です。
設定ファイルの {env:QWEN_ENDPOINT} は、環境変数が未設定のときは空文字に置き換えられます。これはOpenCodeの公式ドキュメントに書いてある仕様です。
問題は、Dockやアプリケーションフォルダから起動したデスクトップアプリには、ターミナルで設定した環境変数が渡らないことです。つまり普通に起動すると、接続先が /v1 だけになって何もつながらずエラーになります。
実際、Dockから起動して ps で環境変数を見ると、Qwen関連の変数は0件でした。モデル選択の画面には設定ファイルどおり「Qwen3.8-27B Q4_K_M (local)」が表示されるので、一見動きそうに見えるのがたちが悪いですね。
対策として、環境変数を注入してからアプリ本体を起動するスクリプトで対応しました。要点だけ書くと以下の形です。
APIキーはmacOSのキーチェーンに入れておき、起動時に security コマンドで取り出しています。
私の環境では、このスクリプトに「すでにDockから起動済みなら止める」「キーチェーンに登録がなければ止めて登録コマンドを表示」といった確認を足して、1コマンドで立ち上がるようにしています。
Claude Code用の設定を読ませない
OpenCodeには、Claude Codeなどの設定ファイルをそのまま読む互換機能があります。~/.claude/CLAUDE.md やスキルの置き場所を自動で探して読み込んでくれるのですが、今回はこれを止めました。
理由は単純で、~/.claude/CLAUDE.md にはClaude のモデルに最適化した設定や、Qwenをサブエージェントとして利用する想定で「実装作業はローカルのQwenに委譲すること」と書いてあるためです。
Claude Code向けの規則の大半はQwenには関係のないものなので、64Kのただでさえ少ないコンテキストウィンドウを無駄な文脈で消費してしまいます。
止め方は環境変数で、起動スクリプトに以下を足します。
代わりに、Qwen専用の短い行動規範を AGENTS.md に書きます。変更前にファイルを読む、小さな差分で進める、テストを先に書く、外部にデータを送る操作は確認する、といった内容で、50行に収まる程度です。
スキルも同じ考えで絞りました。Claude Code側には数十のスキルがありますが、Qwenには「テスト駆動での実装」「出典付きの調査」などのシンプルなものだけ用意しています。
Web検索をつなぐ
OpenCodeに組み込みのWeb検索は、特定のサービスに限定されています。ローカルモデルで使うには、MCP(Model Context Protocol)サーバーとして検索ツールを足すのが手軽です。
検索はTavilyを使っています。従来のGoogle検索などの検索エンジンAPI(人間向けにURLや短いスニペットを返すもの)とは異なり、AIがそのままコンテキストとして利用しやすい形式でWeb上の情報を収集・整形して提供するので、少ないコンテキストウィンドウで余計なノイズを最小化しやすいのと、設定が最小で済むのですぐに導入できます。
キーの登録がないときはデフォルトのMCPに自動で切り替わるようにして、検索そのものは常に使える状態にしました。しばらくは、検索結果のページを読む webfetch は前述の permission で毎回確認にしています。
使ってみた結果
調べ物では、OpenCodeの公式ドキュメントに載っている設定項目の取りうる値を、出典のURL付きで答えさせました。検索して、該当ページを読み、値の一覧を返す、という流れがそのまま動きます。
また、このサイトのブログをユーザーの情報は伏せて批評させてみました。

プロンプトと応答は以下の通りです。実行時間は2分47秒でした。
wentz-design.comというブログについて調査して。特にその筆者の情報と特徴、記事の内容の傾向について調査し、ブログの総評と品質について批判的にレビューしてください。
実行後のセッションの詳細は以下の通りで、64Kに対して51K(約84%)消費しているので、1回打ち返したら多少やり取りしたら /compact などを利用してコンテキストウィンドウを圧縮するなどが必要です。

一定の実用は可能ですが、有料モデルのような返答の速さと賢さには及びませんし、OpenCodeでは無償で公開されているコンテキストウィンドウが1Mに匹敵するモデルを利用することもできるので、それらと比べるとどうしてももっさりします。
メリットがあるとすれば、どこの馬の骨ともわからないサーバに情報を送信しなくて良い精神衛生上の安心や、地味にLLMを実行している間のGPUのファンと独特な機械音(マイルドなダイアルアップみたいな音)がしていて頑張って考えている様子を見てると、なんだかんだ愛着が湧きます。
ただし、連続使用すると排熱がすごいので夏は冷房必須です。逆に冬は暖房代が浮きそう。電気代やいかに。
おまけ:Qwenの実装をCodexにレビューさせる
Claude Code経由の構成では、Qwenの実装をCodexがレビューする形にしていました。この形をチャット側にも持ち込んで、Qwenが書いたコードを、 QwenがCodexにサブエージェントチックにレビューを委託して受ける、というところまで構築しました。
仕組みは、OpenCodeのカスタムツールとして codex_review を1つ定義し、中身は codex exec を固定の引数で呼ぶだけです。レビューに使うモデルや思考の深さはツールの引数に出していないので、Qwenが勝手に変えることはできません。念の為、1セッションあたりの呼び出し回数にも上限を付けています。
以下はこの作業で起きた注意点です。
公式ドキュメントのカスタムツールの例はBunというランタイム前提で書かれていますが、デスクトップ版はNode.jsで動くのでそのままでは動きません。標準の
child_processに置き換えたら動きました子プロセスとして起動した
codex execに標準入力のパイプを開いたまま渡すと、いつまでも応答を返しません。標準入力を明示的に閉じる必要があります
また、カスタムツールは permission の対象外で、確認ダイアログが出ません。今回のツールは対象リポジトリのテストを手元で実行するので、これはQwenが勝手にテストを走らせられるということでもあります。
注意点
Claude Codeからの裏方の呼び出しと共存させる場合の注意点です。
llama-serverは、投機的デコードを有効にすると推論を並列にできず、同時に受け付けるリクエストは1本になります。この状態でデスクトップ側とClaude Code側が同時に投げると、後から来たほうは拒否されずに待たされます。
実測では、2本目は1本目の完了直後に開始しました。困るのは、待たされていることが呼び出し側から分からないことです。ヘルスチェック用のエンドポイントは、生成中でも正常を返します。
私の環境では、両方の呼び出しを一度通す中継サーバーをMac側に置いて、「いま誰が使っているか」を参照できるようにしましたが、これは個人で使う分にはあると便利、くらいなものだと思います。まずはデスクトップ側とClaude Code側を同時に走らせないようにするだけで十分です。






