TECH NOTES
在 Mac 上架設 Local Coding Agent:LM Studio、OpenCode 與三款 Qwen 模型實測

平常開發 Android、iOS 時,我主要使用 Claude Code 和 Codex 協助開發。
這陣子開始想研究 Local Coding Agent。現在不少開源模型都宣稱具備不錯的 Coding 和 Tool Calling 能力,讓我好奇,如果不依賴雲端模型,單純使用 Mac 本身的運算能力,究竟能做到什麼程度?
尤其現在的 Coding Agent 已經不只是產生程式碼,還能讀取專案、修改檔案、執行 Build 和 Test,甚至根據錯誤嘗試自動修正。
那麼,把這些能力接到 Local LLM 上,實際使用起來會是什麼感覺?
我並不期待本地模型能完全取代 Claude Code 或 Codex,主要還是想看看,目前的開源模型是否已經達到日常開發堪用的程度,以及速度、品質與硬體資源之間需要做哪些取捨。
這篇先記錄第一階段的實驗,包括 LM Studio、OpenCode 的安裝與整合,遇到的 Context 和 Compaction 問題,以及幾款 Qwen 模型在 Android 專案上的實際表現。
為什麼選擇 OpenCode,而不是 VS Code Extension?
一開始研究時,曾考慮 Continue、Roo Code、Cline 等 VS Code Extension。
但後來想想,我平常開發 Android 和 iOS,雖然還是使用 Android Studio 和 Xcode,但也有一半以上的時間是在使用 Claude Code、Codex 協助開發。
而且我已經習慣讓 Agent 直接讀寫專案、執行指令,不一定需要依附在特定編輯器上。
因此這次決定直接找一套獨立的 Coding Agent 來試試,最後選擇了 OpenCode 搭配 LM Studio:
- OpenCode 提供 CLI 與 Desktop 操作介面。
- LM Studio 負責在 Mac 本地執行 LLM。
這樣也能保留一些彈性,未來想更換模型或推理引擎時,不需要連整套 Agent 工作流程一起更換。
為什麼先選 LM Studio,而不是 Ollama?
Local LLM 的執行環境,原本也考慮過 Ollama。
兩者都能在 Apple Silicon 上執行本地模型,也都有 CLI 和 API Server 可以整合外部工具。
這次先選 LM Studio,主要是因為它有比較完整的圖形介面,方便搜尋模型、選擇 MLX 或 GGUF 量化版本,以及調整 Context、Reasoning 等設定。
對初次建立 Local Coding Agent 測試環境而言,這樣比較容易觀察模型實際的運作情況。
至於 Ollama,之後有機會再使用相同模型與任務進行比較。
這次的測試環境
這次使用的設備與工具如下:
| 項目 | 環境 |
|---|---|
| 電腦 | MacBook Pro M5 Max |
| 記憶體 | 128GB Unified Memory |
| Local LLM Runtime | LM Studio |
| Coding Agent | OpenCode CLI |
| 推理格式 | MLX 4-bit |
| 測試專案 | ModernApp001(Android / Kotlin) |
| 測試內容 | 專案分析、程式修改、Gradle Unit Test |
模型先使用 MLX 4-bit,主要是考慮 Apple Silicon 的支援,以及避免一開始就把太多時間花在不同量化格式的比較上。
這次先專注於 Local Coding Agent 的功能、品質與速度,之後再看看記憶體較小的 Mac 是否也能順暢執行。
安裝 LM Studio 與 OpenCode
1. 安裝 LM Studio
首先從 LM Studio 官方網站 下載 macOS 版本。
安裝完成後,開啟 LM Studio,在 Discover 中搜尋想測試的模型。
這次第一個下載的是 Qwen3.8 27B,選擇 MLX 4-bit 版本,模型大小約 16GB。

下載完成後,進入 Model Server,載入模型並啟動 Local Server。

Model Server 畫面:模型已載入,截圖當下 Local Server 尚未啟動。
這次使用預設的本機位址:
http://127.0.0.1:1234
可以透過 Terminal 確認 API 是否正常:
curl http://127.0.0.1:1234/v1/models
成功後會回傳 LM Studio 提供的模型清單,例如:
{
"data": [
{
"id": "qwen/qwen3.8-27b",
"object": "model"
}
],
"object": "list"
}
這代表 OpenAI-compatible API 已經可以使用。
要注意的是,模型清單不一定表示所有模型都已經載入記憶體。
2. 安裝 OpenCode
接著安裝 OpenCode。
OpenCode 提供 CLI 與 Desktop App,這次我先使用 CLI 進行測試。
透過 Homebrew 安裝:
brew install anomalyco/tap/opencode-v2
安裝完成後,可以確認版本:
opencode --version
接著設定 OpenCode 使用 LM Studio 的本地 API。
編輯設定檔:
~/.config/opencode/opencode.json
這次使用的設定如下:
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"lmstudio": {
"npm": "@ai-sdk/openai-compatible",
"name": "LM Studio Local",
"options": {
"baseURL": "http://127.0.0.1:1234/v1"
},
"models": {
"qwen/qwen3.8-27b": {
"name": "Qwen3.8 27B MLX (Local)",
"limit": {
"context": 65536,
"output": 8192
}
}
}
}
},
"model": "lmstudio/qwen/qwen3.8-27b"
}
這是當時測試 Qwen3.8 使用的設定範例。不同 OpenCode 版本的設定格式可能有所不同,實際使用時需要確認對應版本的文件。
另外,這裡宣告的 Context 不會自動改變 LM Studio 的模型載入設定,兩邊仍然需要分別確認。
設定完成後,進入 Android 專案:
cd ModernApp001
opencode
在 OpenCode 輸入:
/models
選擇 LM Studio 提供的 Qwen 模型。
這裡還有一點要注意。
OpenCode 的模型選單中,有些模型會標示 Free,但那是免費的雲端模型,不代表在 Mac 本地執行。

這次測試要的是 Local LLM,所以必須確認選擇的是 LM Studio Provider,而不是 OpenCode 提供的雲端模型。

第一個坑:Context 不足,Agent 一直 Compaction Failed
環境設定完成後,我直接讓 OpenCode 分析 Android 專案。
使用的 Prompt:
Inspect this Android project and explain its architecture, main modules, and build configuration. Read the relevant project files before answering. Do not modify any files or execute build commands.
原本只是想看看它能不能正確讀取專案、分析 Gradle 設定與 Android 架構。
沒想到第一次執行就失敗了。
OpenCode 出現:
Compaction produced no summary

一開始還以為是 OpenCode 與模型的 Tool Calling 不相容。
後來打開 LM Studio 的 Server Log,才找到問題:
The number of tokens to keep from the initial
prompt is greater than the context length.
而且 Log 中還看到:
TruncateMiddle policy activated
以及接近 8K 的 Context 限制。
這才發現,Coding Agent 的 Context 需求跟一般 Chat 差很多。
即使使用者只輸入一小段 Prompt,Agent 本身的 System Prompt、工具定義、專案指令和對話紀錄,就可能消耗大量 Token。
尤其 OpenCode 還提供了 Read、Edit、Shell、Search 等工具,這些 Tool Definitions 也需要放進 Context。
後來重新載入模型,將 LM Studio 的 Context Length 提高到 64K,OpenCode 才成功執行專案分析。
第二個坑:Compaction 又碰到輸出上限
原本以為提高 Context 就解決了。
結果後來切換 Thinking Effort、建立新 Session 再測,又遇到另一個錯誤:
Compaction summary reached the output token limit
從 LM Studio Log 可以看到,OpenCode 的 Compaction 請求使用了:
{
"max_completion_tokens": 1024
}
摘要內容碰到輸出上限,導致 Compaction 失敗。
為了先排除這個問題,我在 OpenCode 設定檔加入:
{
"compaction": {
"auto": false
}
}
這是要合併到原有設定的最外層,不是用這段 JSON 覆蓋整個檔案。
重新啟動 OpenCode,再使用:
/new
建立全新 Session,才繼續正常完成測試。
這裡要強調,關閉自動 Compaction 只是這次 POC 的暫時處理方式。
它沒有真正解決長時間 Agent 工作時的 Context 管理問題,也不能保證 Context 用完後仍然可以繼續執行。
不過,至少讓後面的模型比較可以繼續進行。
開始測試:三款 Qwen 模型差異很大
這次主要測試三款模型:
- Qwen3.8 27B
- Qwen3-Coder 30B A3B
- Qwen3.6 35B A3B
其中 Qwen3.8 是 Dense Model,另外兩款是 MoE(Mixture of Experts)架構。
簡單說,Dense Model 在每次生成 Token 時,會使用模型中的大部分參數參與計算。
MoE 則是模型雖然擁有很多參數,但每次只啟用其中一部分 Expert。
因此 MoE 有機會減少每個 Token 所需的運算量,提高生成速度。
不過,模型的全部權重通常仍需要保留在記憶體中,並不代表 30B A3B 只需要 3B 模型的記憶體。
測試一:Android 專案架構分析
三款模型使用相同的 Prompt,分析同一個 ModernApp001 專案。
OpenCode 顯示的結果如下:
| 模型 | 完成時間 | 生成速度 |
|---|---|---|
| Qwen3.8 27B(Extra High) | 5 分 40 秒 | 15.0 tok/s |
| Qwen3.8 27B(Medium) | 6 分 14 秒 | 17.1 tok/s |
| Qwen3-Coder 30B A3B | 21.4 秒 | 60.4 tok/s |
| Qwen3.6 35B A3B | 1 分 8 秒 | 57.0 tok/s |
這些不是嚴格控制變數的 Benchmark。
每款模型自行決定探索哪些檔案、呼叫多少次工具、回答到什麼程度,因此完整任務時間不能直接當成純模型效能排名。
但實際使用起來的差異,還是相當明顯。
Qwen3.8 27B:分析深入,但等待時間較長
第一個測試的是 Qwen3.8 27B。
它產生的分析非常詳細,除了基本的 Gradle 設定與 Android 專案結構,還能辨識:
- Compose 與傳統 XML/ViewBinding 混合架構。
- WebView 中的 Data URI 圖片處理流程。
- Glance App Widgets 與狀態管理。
- Retrofit 故意設定的 Timeout 測試。
- Journeys Test 使用 JDK 21 的特殊配置。
- GitHub Actions 的 CI 設定。
甚至還指出 CI Artifact 的名稱與實際上傳檔案不一致。
這些細節讓我覺得,它真的有花時間閱讀專案,而不是只根據檔案名稱整理一般性的 Android 架構介紹。
不過,缺點就是慢。
第一次完整分析花了 5 分 40 秒。
後來在 LM Studio Chat 中測試,才注意到 Reasoning Effort 原本設定為 Extra High。
那次 Chat 產生了 7,656 Tokens,速度約 26.48 tok/s,整個過程花了數分鐘。
Model Server 的設定當時也是 Extra High。
後來嘗試將 Thinking 改為 Medium,重新執行同一個專案分析,結果反而花了 6 分 14 秒。
這不能直接說 Medium 比 Extra High 慢,因為模型讀取的檔案、推理過程和 Compaction 設定也有差異。
但至少可以確定,對這類需要大量讀檔的 Agent 工作而言,降低 Thinking Effort 不一定會讓完整任務時間等比例縮短。
Qwen3-Coder 30B A3B:速度真的很快
接著換成 Qwen3-Coder 30B A3B。
這款模型採用 MoE 架構,約 30B 總參數、3B 級別的啟用參數,主要針對 Coding 與 Agent 工作設計。
結果第一次測試就有明顯差異。
同樣的 Android 專案分析,只花了:
21.4 秒,60.4 tok/s。
跟前面的 Qwen3.8 相比,速度快上不少。
不過內容品質也出現差異。
它可以正確列出主要 Gradle 設定、Activities、Compose、Retrofit、Glance、測試框架等資訊,但回答偏向概要,沒有深入分析很多特殊設定。
而且有些描述比較制式,例如把 Java 17 Toolchain 和 Kotlin Multiplatform 混在一起,或將專案描述成具有完善的職責分離。
實際上這個專案只是用來練習 Android 技術的單模組專案,沒有完整的 Repository、Domain 或 DI 架構。
因此,雖然速度讓人印象深刻,但我還是想知道它真正修改程式碼時的表現如何。
測試二:讓 Qwen3-Coder 修改 Kotlin 程式碼
這次指定 DataUriParser.kt 和對應的 Unit Test,請 Agent 找出尚未覆蓋的 Edge Case,新增測試,必要時修改程式碼,最後執行 Gradle Test。
結果 OpenCode 確實成功:
- 讀取 Kotlin 原始碼與測試。
- 修改
DataUriParserTest.kt。 - 執行
./gradlew。 - 確認 Unit Test 通過。
完整耗時 2 分 15 秒,生成速度 76.7 tok/s。
也就是說,Local Coding Agent 已經能實際修改 Android 專案並執行測試,不只是回答問題。
但這次修改品質普通。
它新增了一些本來就已經有測試覆蓋的案例,沒有真正找到新的缺陷。
甚至有一個新增測試,和原本的測試使用完全相同的輸入與預期結果。
所以這輪讓我感覺,Qwen3-Coder 雖然快,也能正確呼叫工具,但對「應該修改什麼、不應該修改什麼」的判斷還不夠精準。
發現更新的 MoE 模型:Qwen3.6 35B A3B
後來注意到,Qwen3-Coder 30B 已經是 2025 年的模型。
既然都過了一年,應該有其他值得比較的模型才對。
查了一些近期發布的模型和相關測試後,決定再試 Qwen3.6 35B A3B。
一樣使用 LM Studio、MLX 4-bit 和 OpenCode。
第一次執行 Android 專案架構分析:
1 分 8 秒,57.0 tok/s。
雖然沒有舊 Qwen3-Coder 的 21 秒那麼快,但生成速度相當接近,而且分析內容更完整。
例如它清楚指出:
- 專案只有
:app一個 Gradle Module。 - Compose 和 XML/ViewBinding 是刻意混合的 UI 實驗。
- 沒有完整的 Clean Architecture 或 Dependency Injection。
- WebView、Glance Widgets、Notifications 和 Edge-to-edge 都是各自獨立的練習功能。
- Journeys 測試有額外的 JDK 21 設定。
這次給我的感覺比較接近 Qwen3.8 的分析品質,但不用等待五、六分鐘。
當然,分析依然有需要人工核對的地方。例如它將 Target SDK 36 與 Android 15 對應在一起,實際上 API 36 對應 Android 16。
所以它也不是完全沒有錯誤。
測試三:Qwen3.6 真的找到一個 Kotlin Bug
接著我讓 Qwen3.6 執行與 Qwen3-Coder 相同的 DataUriParser 測試任務。
這次結果讓我比較滿意。
Agent 在讀取 Parser 與現有測試後,發現原本程式使用:
metadata.contains(";base64", ignoreCase = true)
來判斷 Data URI 是否包含 Base64 標記。
但 contains() 只是檢查子字串,因此像 ;base64extra 這種不正確的標記,也會被當成合法資料。
這次 Agent 不只是指出問題,還先新增對應的 Unit Test,執行後確認測試失敗,再將程式修改為:
metadata.endsWith(";base64", ignoreCase = true)
重新執行 Gradle Unit Test 後,測試成功通過。
最後我也檢查了 Git Diff,確認它只修改一行 Parser 程式碼,並新增一個對應的 Unit Test,沒有更動其他無關的檔案。
整個任務耗時 3 分 14 秒,生成速度 78.7 tok/s。
比起 Qwen3-Coder 的 2 分 15 秒雖然慢了一些,但這次真的找出一個合理的問題,並完成了從測試失敗到修正通過的 Red → Green 流程。
當然,這個修改是針對目前 Parser 的預期用途,並不是要完整實作 RFC 2397 的所有規則。
但以這次小範圍的 Bug Fix 任務而言,我認為表現已經不錯。
三款模型的初步比較
整理目前的結果:
| 測試項目 | Qwen3.8 27B | Qwen3-Coder 30B | Qwen3.6 35B A3B |
|---|---|---|---|
| 專案分析 | 深入 | 偏概要 | 較完整 |
| 架構分析時間 | 5~6 分鐘 | 21.4 秒 | 1 分 8 秒 |
| 生成速度 | 約 15~17 tok/s | 約 60~77 tok/s | 約 57~79 tok/s |
| Tool Calling | 成功 | 成功 | 成功 |
| Kotlin 修改 | 未測 | 成功 | 成功 |
| 有價值的 Bug Fix | 未測 | 未找到 | 找到並修正 |
| 整體感受 | 品質較深入,但慢 | 非常快,判斷較表面 | 速度與品質較平衡 |
這裡的品質評價只是根據少數實際任務的主觀觀察,並不是正式 Benchmark。
而且各個模型使用的 Reasoning 設定、工具探索路徑、輸出長度也不完全一致。
如果要做嚴格比較,還需要更多可重複的測試,以及事先定義好的預期結果。
不過,這次已經足以讓我對幾款模型的使用感受有初步認識。
目前的心得
這次實驗讓我覺得,Local Coding Agent 已經有一定的實用性。
透過 LM Studio 和 OpenCode,本地模型確實可以讀取 Android 專案、呼叫工具、修改 Kotlin 程式碼,並執行 Gradle Unit Test。
但也發現幾件事。
首先,模型速度與工作品質是兩回事。
Qwen3-Coder 30B 的速度真的很快,但快速完成任務不代表每個修改都有價值。
而 Qwen3.8 雖然分析得深入,長時間的 Thinking 也可能讓日常開發失去效率。
目前測試下來,Qwen3.6 35B A3B 在速度和品質之間取得了比較好的平衡。
其次,Agent 的環境設定其實很重要。
一開始遇到的 Context、Compaction 問題,並不是換一個模型就一定能解決。
即使模型本身具備 Coding 和 Tool Calling 能力,如果 Runtime、Context 和 Agent 設定不合適,還是可能在正式開始工作前就失敗。
另外,本地模型也不能因為免費,就忽略實際使用成本。
模型下載不需要支付推理 API 費用,但仍然要付出電腦硬體資源、記憶體、等待時間,以及環境維護成本。
如果每次 Coding Agent 工作都要等待很久,或經常需要手動處理 Context 問題,就算免費,也未必適合日常使用。
最後,不要因為 Agent 說測試通過,就完全相信它的修改。
這次 Qwen3.6 的修改看起來很合理,Unit Test 也通過了,但我還是回頭檢查 Git Diff,確認它到底改了哪些內容。
這一點跟使用雲端 Coding Agent 其實沒有不同。
接下來想測試什麼?
目前這些測試都在 MacBook Pro M5 Max 128GB 上完成。
尤其如果同時開著 Android Studio、Xcode、Android Emulator 或 iOS Simulator,記憶體壓力就可能完全不同。
接下來想繼續測試:
- 不同 Context Length 對記憶體、Swap 和推理速度的影響。
- LM Studio 與 Ollama 在相同模型下的差異。
- OpenCode Desktop 與 CLI 的操作體驗。
- Swift / Xcode 專案的實際 Coding 和 Test 工作流程。
目前還沒有打算把這套環境當成 Claude Code 或 Codex 的替代品。
比較像是想知道,現在的 Local LLM 到底能幫忙處理多少日常開發工作,以及它真正的限制在哪裡。
結語
這次從 LM Studio、OpenCode 開始,原本只是想試試 Local Coding Agent 到底能不能用。
過程中遇到了 Context 不足、Compaction Failed,也花了不少時間調整設定。
後來換了幾款模型,才發現即使都是 30B 左右的規模,速度、推理方式和完成任務的品質,也可能有很大的差異。
其中 Qwen3-Coder 30B 的速度讓我印象深刻,而 Qwen3.6 35B A3B 則在這次 Kotlin Bug Fix 測試中,展現出比較好的問題判斷與修改能力。
以目前的結果來說,Local Coding Agent 已經不只是單純在本機聊天,而是真的能參與一部分 Android 開發工作。
當然,距離成熟、穩定、能長時間自主工作的 Coding Agent,還有不少需要驗證的地方。
但至少這次實驗證明,在 Mac 本機執行開放權重模型,已經能完成某些有實際價值的 Coding 任務。
至於是否真的適合日常開發,還得繼續測下去。