※ 記事中にプロモーション広告(アフィリエイトリンク)が含まれます。
先に注意:この記事のユーザー名、IPアドレス、ファイルパスは構成例です。ご自身の環境に合わせて変更してください。また、Manjaro LinuxのVM内で35Bモデルを動かした話ではありません。モデルを動かすのは別VMのVM300(Ubuntu Server)で、Manjaro側はOpenCodeのクライアントとして使います。
管理人の小職さん
ロボ小職
この記事の主題は、Manjaro LinuxへOpenCodeをインストールし、別VMであるVM300のUbuntu Server上で動作するFreeToken-Pascalへ、SSHトンネル経由で接続することです。Qwen3.6 35B A3B NVFP4をローカルAIコーディングモデルとして使い、権限制御、AGENTS.md、WebFetch、WebSearch、Compactionを含む実用環境までを扱います。
役割分担:2台に分けることの結論
最初に整理しておきます。Manjaro側は「使う側」、VM300側は「動かす側」です。この分担を混ぜると、どの数値がどのマシンのものか分からなくなります。
| 項目 | Manjaro Linux側 | VM300(Ubuntu Server)側 |
|---|---|---|
| OpenCode | クライアントとして実行 | 実行しない |
| 推論エンジン | なし | FreeToken-Pascal |
| GPU | なし(クライアントのみ) | GTX 1070 8GB(PCIパススルー) |
| モデル | なし | Qwen3.6 35B A3B NVFP4(qwen3.6-35b-a3b-nvfp4-candidate) |
| 作業リポジトリ | OpenCodeが読み書きする | なし |
| SSH | SSHクライアント | SSHサーバー |
| AGENTS.md | プロジェクトルートで管理 | なし |
| WebFetch / WebSearch | OpenCodeのエージェント機能 | なし |
| API | 127.0.0.1:8082(トンネル側) |
127.0.0.1:8082(実際の待ち受け) |
この記事で作る構成
Manjaro Linux(クライアント)
├─ OpenCode
├─ 作業リポジトリ
├─ AGENTS.md
├─ WebFetch / WebSearch
└─ 127.0.0.1:8082
│
│ SSHトンネル
▼
Ubuntu Server VM300(推論)
├─ FreeToken-Pascal
├─ freetoken-qwen36.service
├─ Qwen3.6 35B A3B NVFP4
├─ GTX 1070 8GB
└─ 0.0.0.0:8082(待ち受け)
VM300のAPIポートをLANへ直接公開するのではなく、SSHトンネルで127.0.0.1:8082へ引き込みます。OpenCodeから見える接続先は、Manjaro自身の127.0.0.1:8082です。
確認レベルの見分け方
この記事では、確認できた度合いを3段階で書き分けます。
| 区分 | 内容 |
|---|---|
| 確定事項 | 公式文書で確認した、実機で実行した、API応答やログ、設定ファイル、Gitコミットで裏付けが取れた |
| 高確率 | 実動作から可能性が高いと判断できるが、内部実装までは確認していない |
| 未確認 | 実行していない手順、未測定の性能、未確認のOpenCode機能、未確認のLSP、未確認のマルチエージェント動作 |
OpenCodeとは何か
OpenCodeは、公式ドキュメントで「オープンソースのAIコーディングエージェント」と説明されているツールです。ターミナル中心のインターフェースに加えて、Desktop版とIDE拡張も提供されています。
- モデルはプロバイダ設定で切り替える。OpenAI互換のエンドポイントも指定できる
/initでプロジェクトを解析し、AGENTS.mdを作成・更新できる- PlanモードとBuildモードをTabキーで切り替えられる。Planは変更を行わず提案に留める
- プロジェクトの
AGENTS.mdはGitへコミットすることが推奨されている - グローバルな指示は
~/.config/opencode/AGENTS.md、設定は~/.config/opencode/opencode.jsonに置ける
公式ドキュメントでは、インストール手段としてインストールスクリプト、npm、Bun、pnpm、Yarn、Homebrew、Arch Linuxのパッケージ、WindowsはWSL推奨などが案内されています。ローカルLLMだけでなく、クラウドのプロバイダも設定次第で使えます。
ターミナル上でファイルを読み、編集し、コマンドを実行する流れが基本です。今回のように推論先を別マシンへ置くと、クライアント側のスペックは軽くて済みます。
Manjaro LinuxへOpenCodeを導入
Step 1:環境確認
クライアント側の環境です。モデルはVM300が担当するため、このマシンにGPUは必要ありません。
| 項目 | 値 |
|---|---|
| OS | Manjaro Linux(カーネル6.18系) |
| CPU | 8コア |
| RAM | 8GB |
| SSD | 120GB |
| Node.js | v26.8.1 |
| npm | 12.0.2 |
クライアント専用なら、RAM 8GBでも作業はできます。ただし長いセッションや大きなリポジトリでは、RAMとストレージの余裕が効いてきます。メモリは足りなくなってから増やすと作業が中断するので、先に確認しておくのがおすすめです。
増設時は、マザーボードが対応する規格(DDR4かDDR5か)とスロット数を確認してください。世代が違うと物理的に挿さりません。
Step 2:OpenCodeをインストール
公式で案内されているインストールスクリプトか、npmで導入します。Manjaro/Arch Linuxならパッケージも選べます。
# インストールスクリプト(公式の案内)
curl -fsSL https://opencode.ai/install | bash
# npmでグローバルインストール
npm install -g opencode-ai
# Arch Linux / Manjaro のパッケージ
sudo pacman -S opencode
paru -S opencode-bin
curlでスクリプトを直接実行する方法は手軽ですが、配布元と内容を確認してから実行してください。npm版はNode.jsのバージョンに影響されるため、事前にnode -vとnpm -vを確認しておくと安全です。
Step 3:プロジェクトを初期化
作業したいリポジトリへ移動してOpenCodeを起動し、/initを実行すると、プロジェクトを解析してAGENTS.mdを作成・更新します。
cd ~/work/your-project
opencode
# 起動後にTUIで /init を実行
作成されたAGENTS.mdはGitへコミットしておきます。プロジェクト固有のビルド手順や規約を書いておくと、セッションをまたいでも同じ前提で作業してくれます。
VM300のFreeToken-Pascal準備
VM300の構成
推論側は、Proxmox VE上のUbuntu Server VM300です。GTX 1070 8GBをPCIパススルーし、FreeToken-PascalでQwen3.6 35B A3B NVFP4を動かしています。
| 項目 | 値 |
|---|---|
| 仮想化基盤 | Proxmox VE(ホストの物理メモリ64GB) |
| VM | Ubuntu Server(VM300) |
| GPU | GTX 1070 8GB(PCIパススルー) |
| 推論エンジン | FreeToken-Pascal |
| モデル | Qwen3.6 35B A3B NVFP4 |
| API | 127.0.0.1:8082(構成例) |
起動設定と起動確認
FreeToken-Pascalはsystemdのユーザーサービスとして常駐させています。主要な設定は次のとおりです。
| 設定項目 | 値 |
|---|---|
| コンテキスト長 | 32,768 |
| 最大出力トークン | 1,024 |
| Prefill分割長 | 2,048 |
| キャッシュ方式 | radix |
| tool-call parser | qwen3_coder |
| reasoning parser | qwen3 |
| MoE CPUスレッド数 | 10 |
| MoEキャッシュサイズ | 0 |
# サービスの状態確認
systemctl --user status freetoken-qwen36.service
# 起動ログの確認例
Prefill warmup complete
Scheduler is idle, waiting for new reqs...
API server is ready to serve on 0.0.0.0:8082
モデルのロードとPrefillのウォームアップを含めて、API Readyまで約6分30秒かかりました。起動直後にアクセスして失敗する場合は、この待ち時間を疑ってください。
なお、本家FreeTokenのCLIはLinux x86_64、NVIDIA GPU、ドライバーr580以降(CUDA 13)が公式要件です。GTX 1070のようなPascal世代はそのままでは対象外で、今回はPascal向けのfork(FreeToken-Pascal)を使っています。
新しくGPUサーバーを組む場合は、VRAM容量を基準にカードを選び、量子化形式の選択肢とあわせて考えることになります。
カードを選ぶときは、Compute Capabilityと必要なドライバーのバージョンも確認してください。世代が古いと、動かせる量子化形式が限られます。
SSHトンネルでVM300へ接続
Manjaro側から専用のSSH鍵を作り、ポートフォワードでVM300のAPIを手元の127.0.0.1:8082へ引き込みます。
(PR)
# 専用鍵の作成(例)
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_vm300_tunnel -C "vm300-tunnel"
# 公開鍵をVM300へ登録
ssh-copy-id -i ~/.ssh/id_ed25519_vm300_tunnel.pub <Ubuntuユーザー名>@<VM300_IP>
# ~/.ssh/config の例
Host vm300
HostName <VM300_IP>
User <Ubuntuユーザー名>
IdentityFile ~/.ssh/id_ed25519_vm300_tunnel
IdentitiesOnly yes
ServerAliveInterval 30
ServerAliveCountMax 3
ExitOnForwardFailure yes
# トンネルを張る(-Nはコマンド実行なし)
ssh -N -L 8082:127.0.0.1:8082 vm300
# 別ターミナルから確認
curl http://127.0.0.1:8082/v1/models
<VM300_IP>や<Ubuntuユーザー名>は各自の環境に置き換えてください。ExitOnForwardFailure yesを付けておくと、ポート転送に失敗したときに接続が残らず、原因を切り分けやすくなります。
127.0.0.1へ引き込む構成にしているトンネルはSSHセッションが切れると消えます。自動再接続の常駐化(autosshやsystemdユーザーサービスなど)は選択肢がありますが、本記事の確認範囲では運用検証まで行っていないため、未確認として扱います。
.gitignoreへ追加し、誤ってpushした場合は履歴からの削除とキーの再発行を行ってください。OpenCodeからVM300のモデルを使う
OpenCodeの設定ファイルで、プロバイダとしてVM300のOpenAI互換エンドポイントを指定します。
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"vm300": {
"npm": "@ai-sdk/openai-compatible",
"options": {
"baseURL": "http://127.0.0.1:8082/v1"
},
"models": {
"qwen3.6-35b-a3b-nvfp4-candidate": {}
}
}
}
}
設定はプロジェクトのopencode.jsonか、グローバルの~/.config/opencode/opencode.jsonへ置きます。baseURLがトンネル側の127.0.0.1:8082になっている点が重要です。ローカル推論のため、クラウドのAPIキーは不要です。
/v1/modelsで返るモデルIDと、設定のmodelsのキーを一致させてください。model欄が食い違うと、リクエストが通っても意図しないモデルへ当たったり、エラーになったりします。
tool-callとreasoningの設定
OpenAI互換APIから文章が返るだけでは、コーディングエージェントとしては不十分です。OpenCodeがツールを実行するには、応答が構造化されたtool_callsになっている必要があります。
初期状態では、tool callがXML風の文字列として本文に残り、ツール呼び出しとして認識されませんでした。tool-call parserをqwen3_coderへ変更したうえで、直接APIで次を確認しています。
finish_reason = tool_calls- tool name:
list_directory - arguments:
{"path":"."}
reasoning側はqwen3を指定し、内部推論をreasoning_contentへ分離しています。これにより、通常の本文へ</think>のような文字列が混入しにくくなります。
権限とAGENTS.mdで操作範囲を制御
ローカルLLMだからといって、プロジェクト全体を無制限に調査・変更させる構成にはしていません。プロジェクトルートのAGENTS.mdで操作規則を定め、Gitで管理しています。
- 作業対象は現在のプロジェクト内に限定する
- 無制限の全体走査を禁止し、一度に読むファイルは最大3件
- 一度に変更するファイルは最大3件
- 既存の未コミット変更を上書きしない
git reset、git clean、強制checkoutを禁止する- ファイル削除は明示的な許可を必要とする
- Web取得の結果を大量にコンテキストへ追加しない
関連するコミットは次の3件です。
ee69fc299 Add OpenCode project operating rules
9ab941df4 Unify approved web access into OpenCode ops agent
4a837daf9 Add bounded web access performance rules
ここでいうバイブコーディングは、AIへ無制限の操作権を渡すことではありません。対象、権限、変更量、テスト、バックアップ、ロールバックを明示したうえで、AIと対話しながら開発を進める方式です。
Radixキャッシュの効果
OpenCodeは、ファイル読取りやツール実行のたびにモデルを呼び出します。そのたびにシステム指示やツール定義、会話履歴を再処理すると、古いGPUでは負担が大きくなります。
初期設定ではキャッシュ方式がnaiveでした。これをradixへ変更したところ、同一prefixの試験で次の結果になりました。
| 試験 | 所要時間 | new-token | cached-token |
|---|---|---|---|
| 同一要求1回目 | 41秒 | 310 | 0 |
| 同一要求2回目 | 13秒 | 54 | 256 |
約68%の短縮です。ただし、Radixを有効にすればすべて速くなるわけではありません。ツール結果や会話構造が変わってprefixが一致しない場合は、cached-token=0となり、再び41秒側へ戻ります。
コンテキストとCompaction
OpenCodeは、ユーザーの入力だけでなく、システム指示、エージェント定義、ツール定義、AGENTS.md、会話履歴、ファイル内容、コマンド結果、Web取得結果まで入力へ加えます。長いセッションでは、次のコンテキスト超過が発生しました。
prompt is too long: 38879 tokens > 32768 maximum
| 設定項目 | 値 |
|---|---|
| input limit | 32,000 |
| context limit | 32,768 |
| output limit | 512 |
| request max_tokens | 512 |
| provider timeout | 30分 |
| chunk timeout | 30分 |
| automatic compaction | 有効 |
| compaction keep | 4,000 |
| compaction buffer | 12,000 |
自動Compactionは長いセッションを続けるために必要ですが、ローカル35Bモデルでは圧縮そのものも重く、約6分9秒かかった例があります。bufferを12,000へ増やして早めに圧縮を始め、keepを4,000へ下げて圧縮後のコンテキストを軽くしています。
それでも、無関係な作業を1つのセッションへ詰め込まない方が安定します。おおむね1作業1セッションが目安です。
WebFetchとWebSearchのルール
OpenCodeから公式情報や既知URLを確認できるよう、常用エージェントへWeb機能を統合しています。
- 既定URLの取得:webfetch
- Web検索:websearch(有効化は
OPENCODE_ENABLE_EXA=true) - Web権限:ask(実行前に確認する)
入力が膨らみすぎないよう、次のルールも追加しています。
- WebFetchは1ターン1 URL
- WebSearchとWebFetchを同一ターンで連続実行しない
- WebSearch結果は原則3件以内
- 同じURLを同一セッションで再取得しない
- ページ内リンクを自動取得しない
- Web取得後は再取得せず、取得済み結果を整理する
確認できたのは、WordPress公式トップページのWebFetch、公式の開発者向け資料のWebSearch、検索結果の件数制限、Web調査時にプロジェクトファイルを変更しない動作です。
実測結果
直接APIの実測
短いプロンプトを直接APIへ投げた結果です。
| 回 | 所要時間 | prompt tokens | completion tokens |
|---|---|---|---|
| 1回目 | 約4.01秒 | 17 | 2 |
| 2回目 | 約2.36秒 | 17 | 2 |
ストリーミングの実測
ストリーミングではHTTP 200を確認し、time_starttransferが約0.027秒、time_totalが約2.346秒でした。最初のトークンが早く返るため、体感はさらに軽くなります。
WebFetchの実測
OpenCode経由のWebFetchでは、最終回答まで約8分56秒かかった例があります。WebFetch自体は成功しており、その後のPrefillが4,680トークン、cached-tokenは0でした。
まとめると、短い直接APIとストリーミングは数秒、同一prefixではRadixキャッシュが効く、cache miss時のPrefillは重い、OpenCodeでは数分かかる場合がある、という挙動です。常に数秒で返るわけではありませんし、GTX 1070で35Bモデルが爆速という話でもありません。
向いている作業と向いていない作業
向いている作業
- 指定ファイルの調査
- 小規模なコード修正
- Git差分の確認
- 対象を限定したテスト
- 公式仕様のWeb検索
- ローカル環境へコードや情報を残したい作業
向いていない作業
- プロジェクト全体の無制限走査
- 大量URLの一括取得
- 複数の無関係な作業を1セッションで継続
- 最新GPUと同等の応答速度を要求する用途
- 時間制限の厳しいリアルタイム処理
プライバシーと外部通信
この構成の利点は、推論先をローカルAPIだけに限定できることです。プロンプトをクラウドLLMへ送らずに運用できます。
ただし「ローカルLLMなら完全オフライン」「情報が絶対に外へ出ない」とは言えません。次の要素は外部通信する可能性があります。
- モデルのダウンロード
- OpenCodeやパッケージの更新確認
- Gitの操作
- WebFetch、WebSearch
- MCPサーバー
- プラグインや拡張機能
- テレメトリやライセンス確認
- クラウドモデルの利用
推論は手元に閉じ込めつつ、どこで外へ出るかを把握しておくのが現実的です。
確認できたこと・高確率・未確認
確定事項
- FreeToken-Pascalの起動、API Ready、
/v1/modelsの応答 - 短い直接API、ストリーミング、OpenCode接続、構造化tool_calls
- WebFetch、WebSearch、Radixキャッシュ、自動Compaction
- systemdユーザーサービスとしての常駐と起動ログ
- OpenCode公式ドキュメントで確認したインストール手段、
AGENTS.md、Plan/Buildモード、設定ファイルの位置
高確率
- Radixキャッシュが効いた区間の短縮(41秒→13秒)
- OpenCode経由の処理が重いのは、ツール定義・文書・Web結果による入力増加が主因という見立て
- RAM 8GBのクライアントは、長いセッションや大きなリポジトリで逼迫しやすいという傾向
未確認
- Manjaro VM内でモデルを動かす構成(本記事では採用していない)
- OpenCodeのLSPによる自動補完の挙動
- マルチセッション・マルチエージェントの並列動作
- SSHトンネルの自動再接続を常駐化した場合の運用
- Manjaro固有のバージョン差分による挙動の違い
- 実測していない速度・VRAM使用量
OpenCode環境のよくある質問
管理人の小職さん
ロボ小職
管理人の小職さん
ロボ小職
管理人の小職さん
ロボ小職
管理人の小職さん
ロボ小職
まとめ
Manjaro LinuxへOpenCodeを導入し、VM300のUbuntu Serverで動くFreeToken-PascalへSSHトンネル経由で接続する構成を作りました。Qwen3.6 35B A3B NVFP4をローカルAIコーディングモデルとして、構造化tool calling、AGENTS.mdによる権限制御、WebFetch、WebSearch、Radixキャッシュ、自動Compactionまで確認しています。
最初から素直に動いたわけではありません。tool callが本文に残る問題、dtypeの不一致、MoEキャッシュ設定、コンテキスト超過を一つずつ切り分けました。古いGPUを推論側に置き、クライアントを軽くする分担は、手元のハードウェアを使い切るうえで扱いやすい形です。
短い質問は数秒、文書やWeb結果を多く含む処理は数分。この差を前提に使うと、期待値のずれで悩まずに済みます。
管理人の小職さん
ロボ小職
参考資料
- OpenCode 公式ドキュメント(Intro)
- OpenCode 公式ドキュメント(Rules / AGENTS.md)
- FreeToken-Pascal GitHubリポジトリ
- FreeToken 本家 GitHubリポジトリ
- FreeToken-PascalでGTX 1070 8GBな古めグラボでQwen3.6 35Bが動作!自作AIサーバでローカルLLMバイブコーディング術
- ローカルLLM推論環境比較2026|LM Studio・Ollama・FreeToken・vLLMを用途別に選ぶ
(PR)
タグ




