クラウドLLMの高騰にさよなら。M4 MaxとOpenCodeで挑む、本気のローカルLLM開発環境構築

4 min read

お久しぶりです。

皆様は、コーディングにおいてどのようなツールを使用していますか。

ほとんどの方が、ClaudeやChatGPTなどのAIによるコーディング支援を受けていると思います。
中には、単なる支援にとどまらず、AIにコード作成の大部分を投げている方もいるでしょう。

非常に便利な一方で、気になるのがコストの問題です。
ガツガツ使いたいところですが、クラウドLLMの多くは従量課金制です。
課金制限をかけていると作業が途中で止まってしまいますし、制限をかけなければ、気づかないうちに高額な請求が来てしまいます。
しかも、多くはドル建ての請求であるため、為替の影響も受けてしまいます。

「有意義に、かつお金を気にせず使えるAIコーディング環境を作りたい」

ということで、本気でローカルLLM環境を構築することにしました。
本記事では、2日間かけて構築した、ローカルLLMを用いたコーディング環境の構築手順を解説していきます。

構築のゴール:ローカルLLMによる完全自律型コーディング環境

構築にあたり、以下の3つを実現することを目指します。

  • ローカルLLMのみで作業を完結させること
  • コーディングエージェントによる自動コーディングを実現すること
  • VSCode上でもローカルLLMを活用すること

ローカルLLMで完結すること

本記事の主題です。
コストをかけずに、AIの支援を最大限に受けられる環境を構築します。

コーディングエージェントが使えること

現在は、会社でClaude Codeを使用しています。
自律的にコードを書いてくれる機能は、極めて強力です。
問題があれば修復し、不明点があれば質問してくれる。素晴らしい体験です。
この便利さを知ってしまうと、コーディングエージェントを使わない開発には戻れません。
そのため、今回もコーディングエージェントを導入します。

VSCode上でもローカルLLMを使えること

私はこのブログをVSCodeで書いています。
保存時の自動整形やMarkdownのプレビューなど、便利な機能が多く、現在のワークフローを離れる予定はありません。

また、GitHub Copilotも非常に便利です。
サイドバーのチャット機能を使えば、コードを書きながら質問や提案を受け取れます。
文章を執筆している際に「この言い回しを直して」といった、ちょっとした添削を依頼するのにも適しています。

github copilot のチャット画面
Copilot Chat は無料で使えるんですよね

前提

ローカルLLMを動かすには、PCのスペックが重要です。
今回は、以下のスペックでの構築を前提とします。

  • CPU: Apple M4 Max
  • メモリ: 128GB
  • OS: macOS 26.5.2

購入時の詳細情報は、こちらにまとめています。
https://autumn-color.com/blog/2024/12/2024-12-02/

構築手順

ここから具体的な構築手順を説明します。

爆速化の鍵:mlx-serveによるLLMランタイムの構築

LLMランタイムは、ローカルLLMを実行するための基盤です。
ローカルLLMを運用する上で、PCのスペックに次いで重要だと考えています。

今回は、 mlx-serve を使用します。
https://github.com/ddalcu/mlx-serve

選定理由は以下の通りです。

もともとLM Studioを使用していましたが、mlx-serveのほうが高速であったため、こちらに乗り換えました。
※体感による判断です。厳密な比較は行っていません。

Local LLM のダウンロード

以下の3つのローカルLLMをダウンロードしました。

  • Qwen3.6 35b A3b Optiq 4bit
    • 用途: メインエージェント(調査やテスト用のサブエージェントとしても活用)
    • 選定理由:
  • Qwen3 Code Next 4bit
    • 用途: コーディング特化
    • 選定理由:
      • コーディング特化モデルであること
      • MoEによる高速なレスポンス
      • (本当はGLMやKimiを動かしたかったのですが、今回は断念しました)
  • gemma 4 26B A4B it Optiq 4bit
    • 用途: 文章の添削
    • 選定理由:

GitHub Copilot の設定

まずはVSCodeの拡張機能から、GitHub Copilotをインストールします。

拡張機能GitHub Copilot で検索してインストールし、GitHubアカウントと連携させてください。

次に、GitHub Copilot上でローカルLLMを使用できるように設定します。

拡張機能GitHub Copilot LLM Gateway を検索してインストールします。

インストール後、拡張機能の設定を開きます。

ここに、 http://localhost:11234 を入力します。

VSCodeを再起動すると、ローカルLLMが利用可能になります。

http://localhost:11234 は mlx-serve のデフォルトのポート番号です。
接続できない場合は、mlx-serveの設定を確認してください。

OpenCode のインストール

コーディングエージェントにはOpenCodeを採用しました。
理由は以下の通りです。

  • 情報量が多い
  • Open Codeのような使い勝手を実現できる

PiAider も魅力的ですが、今回はより確実な選択肢(安牌)を選びました。
Claude CodeもローカルLLMに対応しているようですが、会社ですでに利用しているため、今回はOpenCodeを選択しています。

インストール方法は公式ドキュメントに記載されています。
brewでインストールできるため、非常にスムーズです。

はじめに
opencode.ai
image

OpenCode の設定

主な設定

  • 共有設定: 無効

  • デフォルトエージェント: orchestrator

  • プラグイン: context-mode, envsitter-guard, opencode-worktree, opencode-dcp

  • MCP サーバー: playwright, chrome-devtools, context7

  • 使用モデル(ローカル):

    • Qwen3-Coder-NEXT-30B
    • Qwen3.6-35B
    • Gemma4-26B (※注:原稿の記載に基づき修正)

エージェント構成

エージェント役割
orchestrator計画立案とタスク委譲(直接の編集は行わない)
coder実装・編集・バグ修正
testテスト作成・実行・報告
research読み取り専用の調査

orchestrator は、タスクを分解し、適切なサブエージェントに割り振るため、agents ディレクトリに設定ファイル(~/.config/opencode/agents/orchestrator.md)を作成しています。

設定情報全文

~/.config/opencode/opencode.jsonc

{
  "$schema": "https://opencode.ai/config.json",
  
  "share":"disabled",

  "plugin": [
    "context-mode",
    "envsitter-guard",
    "opencode-worktree",
    "@tarquinen/opencode-dcp@latest"
  ],

  "default_agent": "orchestrator",

  "permission": {
    "question": "deny",

    "bash": {
      "*": "ask",

      "rtk *": "allow",
      "echo *": "allow",
      "pwd": "allow",
      "ls *": "allow",
      "ls": "allow",
      "cat *": "allow",
      "grep *": "allow",
      "which *": "allow",

      "node -v": "allow",
      "node --version": "allow",
      "npm -v": "allow",
      "npm --version": "allow",

      "git status *": "allow",
      "git status": "allow",
      "git diff *": "allow",
      "git log *": "allow",
      "git branch": "allow"
    }
  },

  "mcp": {
    "playwright": {
      "enabled": true,
      "type": "local",
      "command": ["npx", "-y", "@playwright/mcp@latest"]
    },
    "chrome-devtools":{
      "enabled": true,
      "type": "local",
      "command": ["npx", "-y", "chrome-devtools-mcp@latest"]
    },
    "context7": {
      "enabled": true,
      "type": "remote",
      "url": "https://mcp.context7.com/mcp",
      "headers": {
        "Authorization": "YOUR_CONTEXT7_API_KEY"
      }
    }
  },

  "provider": {
    "mlx-server": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "mlx-server",

      "options": {
        "baseURL": "http://127.0.0.1:11234/v1"
      },

      "models": {
        "mlx-community/Qwen3-Coder-Next-4bit": {
          "name": "Qwen3-Coder-NEXT-30B",
          "modalities": {
            "input": ["text"],
            "output": ["text"]
          }
        },

        "mlx-community/Qwen3.6-35B-A3B-OptiQ-4bit": {
          "name": "Qwen3.6-35B",
          "modalities": {
            "input": ["text", "audio", "image", "video", "pdf"],
            "output": ["text", "audio", "image", "video", "pdf"]
          }
        },

        "mlx-community/gemma-4-12B-it-4bit": {
          "name": "Gemma4-12B",
          "modalities": {
            "input": ["text", "audio", "image", "video", "pdf"],
            "output": ["text", "audio", "image", "video", "pdf"]
          }
        }
      }
    },
    "github-copilot": {
      "whitelist": [
        "claude-sonnet-4.5",
        "kimi-k2.7-code",
        "gemini-3.7-flash",
        "gpt-5.4-mini"
      ]
    }
  },

  "agent": {
    "orchestrator": {
      "mode": "primary",
      "model": "mlx-server/mlx-community/Qwen3.6-35B-A3B-OptiQ-4bit",
      "temperature": 0.2,
      "description": "計画立案とsubagentへのタスク委譲を行う司令塔。自分ではファイル編集しない。",
      "tools": {
        "task": true,
        "write": false,
        "edit": false,
        "bash": false
      }
    },

    "coder": {
      "mode": "subagent",
      "model": "mlx-server/mlx-community/Qwen3-Coder-Next-4bit",
      "temperature": 0.2,
      "description": "コードの実装・編集・バグ修正を担当。ライブラリのAPIやバージョン固有の仕様を確認する際は必ずcontext7で最新ドキュメントを調べてから実装する。ブラウザ上での動作確認が必要な変更(UI、フロントエンド)はplaywrightかchrome-devtoolsで実際に動かして検証する。",
      "tools": {
        "context7_*": true,
        "playwright_*": true,
        "chrome-devtools_*": true
      },
      "permission": {
        "edit": "allow",
        "context7_*": "allow",
        "playwright_*": "allow",
        "chrome-devtools_*": "allow",
        "serena_*": "allow"
      }
    },


    "test": {
      "mode": "subagent",
      "model": "mlx-server/mlx-community/Qwen3.6-35B-A3B-OptiQ-4bit",
      "temperature": 0.2,
      "description": "テストの作成・実行・結果報告を担当。E2E/UIの検証はplaywrightで実ブラウザ操作を行い、フロントエンドの挙動確認・エラー調査はchrome-devtoolsのコンソール/ネットワークログを積極的に見る。テスティングフレームワークの書き方に迷ったらcontext7でドキュメントを確認する。",
      "tools": {
        "context7_*": true,
        "playwright_*": true,
        "chrome-devtools_*": true
      },
      "permission": {
        "edit": "ask",
        "context7_*": "allow",
        "playwright_*": "allow",
        "chrome-devtools_*": "allow"
      }
    },

    "research": {
      "mode": "subagent",
      "model": "mlx-server/mlx-community/Qwen3.6-35B-A3B-OptiQ-4bit",
      "temperature": 0.3,
      "description": "コードベースの調査、ドキュメント検索、依存関係の把握を担当。ファイルは変更しない、読み取り専用の調査タスクに使う。",
      "permission": {
        "edit": "deny",
        "webfetch": "allow",
        "serena_*": "allow"
      }
    }
  }
}

~/.config/opencode/agents/orchestrator.md

# あなたの役割

あなたはコーディングタスクを直接実行しません。すべての実装・テスト・調査作業は、必ず `task` ツールを使って専用のsubagentに委譲してください。

## 厳守ルール

1. コードの実装・編集・バグ修正が必要な場合 → 必ず `task` ツールで `coder` を呼ぶ。自分でコードを書いて提示することは禁止。
2. テストの実行・結果確認が必要な場合 → 必ず `task` ツールで `test` を呼ぶ。
3. コードベースの調査・ドキュメント確認が必要な場合 → 必ず `task` ツールで `research` を呼ぶ。
4. あなた自身の役割は「タスクを分解し、適切なsubagentに割り振り、結果を統合してユーザーに報告すること」のみです。

##

ユーザー: 「ログイン機能にバグがあるので直して」

あなたの正しい行動:
1. `task` ツールで `research` を呼び、関連ファイルとログイン処理のフローを調査させる
2. 調査結果を元に `task` ツールで `coder` を呼び、修正を依頼する
3. 修正後、`task` ツールで `test` を呼び、既存テストを実行させる
4. 全体の結果をユーザーに要約報告する

上記のいずれの工程でも、あなた自身がコードを書いたり、ファイルを直接編集したりしてはいけません。

使ってみる

お試しで、このブログのビルド時間の短縮を試みます。

まずは、どこがボトルネックかを調査してもらいます。

ログを見ると、サブエージェントにタスクを投げてくれているのがわかります。

24分ほどで解析が完了しました。

かなり時間がかかっている印象ですが、無事に調査が完了しました。
あと、PCがめっちゃ熱いです。

次に、実装を依頼しました。

ログの表示はありませんが、これも 30分ほど かかったと思います。
Claudeであれば数分で終わるはずなので、やはりローカルLLMは遅いです。

感想

会社でClaude Codeを使っているため、ローカルLLMの遅さは理解していましたが、それでもやっぱり遅いですね。
人類には、まだ少し早いのかもしれません。

ひとまずはこの構成で様子を見て、厳しければ一部をクラウドLLMに切り替える設定にしておこうと思います。

まとめ

ローカルLLMによるコーディング環境を構築してみました。

「RAM 128GBあるのでなんとかなるだろう」と思っていましたが、現実は厳しいものでした。
Claude Codeのように、サクサクと動作する環境を作るには、さらなるスペックが必要だと感じています。

もしこの遅さに耐えられなくなったら、また別の方法を検討します。

一方で、エラーになるかと思いましたが、なんとか自走してくれました。
これについては、OpenCodeやmlx-serveの開発者の皆様に感謝いたします。

「もっとこうするといいよ」といったアドバイスがあれば、ぜひいただけると嬉しいです。