# macOS에서 로컬 코딩 에이전트 설정하는 방법

> Clean Markdown view of GeekNews topic #30461. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=30461](https://news.hada.io/topic?id=30461)
- GeekNews Markdown: [https://news.hada.io/topic/30461.md](https://news.hada.io/topic/30461.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2026-06-13T22:45:09+09:00
- Updated: 2026-06-13T22:45:09+09:00
- Original source: [ikyle.me](https://ikyle.me/blog/2026/how-to-setup-a-local-coding-agent-on-macos)
- Points: 1
- Comments: 1

## Topic Body

- **로컬 코딩 에이전트** 구성은 인터넷 장애 때도 macOS에서 OpenAI 호환 API로 모델을 실행하고 Pi에서 텍스트와 이미지 입력을 처리하도록 만드는 설정임
- Apple M1 Max 64GB, macOS 15.7.7에서 **llama.cpp Metal**과 Gemma 4 26B-A4B GGUF 모델을 사용했으며, 기본 생성 속도는 58.2 tok/s였음
- **MTP draft model**을 추가하고 `--spec-draft-n-max 3`으로 조정한 뒤 생성 속도가 72.2 tok/s로 올라가 약 24% 개선됨
- `mmproj-BF16.gguf`를 `--mmproj`로 로드하고 Pi 모델 입력을 `["text", "image"]`로 설정해야 스크린샷 같은 **이미지 입력**이 전달됨
- 최종 구성은 llama.cpp 서버를 `127.0.0.1:8080/v1`에서 실행하고 Pi가 이를 로컬 제공자로 쓰는 방식이며, Qwen3.6 35B-A3B는 더 나은 코딩 에이전트 벤치마크를 보였지만 이 테스트에서는 55 tok/s로 더 느렸음

---

### 로컬 코딩 에이전트 구성 목표
- 인터넷 장애가 몇 번 발생해 코딩 에이전트를 사용할 수 없었던 상황이 로컬 실행 구성을 시도한 계기가 됨
- 원하는 구성은 Mac에서 실제로 쓸 만큼 빠르고, **OpenAI 호환 API**를 통해 다른 도구에서도 사용할 수 있어야 했음
- 필요할 때 스크린샷이나 이미지를 처리해 에이전트가 만든 결과물을 다시 입력으로 줄 수 있는 구성이 목표였음
- 최종 구성은 `llama.cpp`, Gemma 4 26B-A4B GGUF, Q8 MTP draft model, Gemma 4 multimodal projector, Pi 터미널 코딩 에이전트로 이뤄짐
- 테스트 환경은 Apple M1 Max, 64GB 통합 메모리, macOS 15.7.7이었음

### 모델
- 메인 모델은 `gemma-4-26B-A4B-it-UD-Q4_K_XL.gguf`였으며, Hugging Face의 `unsloth-gemma-4-26B-A4B-it-GGUF` 저장소에 있음
- 해당 파일 크기는 약 16GB이며, MTP draft head와 multimodal projector를 함께 두면 모델 폴더는 약 17GB가 됨
- 벤치마크 프롬프트는 `Write a compact Python function that parses a unified diff and returns the changed file paths. Then explain two edge cases.`였음
- 각 벤치마크는 약 128개 토큰을 생성함

### 기본 실행: llama.cpp + Metal
- 메인 모델을 `llama.cpp`와 **Metal 가속**으로 직접 실행했음
- 실행 명령은 `llama-cli`에 모델 경로, `-ngl 999`, `-fa on`, `-c 4096`, `-n 128`을 지정하는 방식이었음
- 기본 구성의 프롬프트 처리 속도는 298.0 tok/s, 생성 속도는 58.2 tok/s였음
- 58 tok/s는 빠르지는 않지만 사용할 수 있는 수준이며, 코딩 에이전트 작업에서는 많은 도구 호출 때문에 가능한 한 빠른 속도가 필요함

### MTP draft model 추가
- Gemma 4에는 `MTP/gemma-4-26B-A4B-it-Q8_0-MTP.gguf` 형태의 **MTP draft model**이 제공됨
- `llama.cpp`에서는 이를 `--model-draft`, `--spec-type draft-mtp`, `--spec-draft-n-max`로 투기적 디코딩(speculative decoding)에 로드함
- MTP 첫 실행은 draft token 4개에서 69.2 tok/s를 기록함
- Unsloth 문서는 `--spec-draft-n-max 2`를 시작점으로 권장하지만, 1부터 6까지 하드웨어별로 테스트해 가장 빠른 값을 쓰라고 함
- `--spec-draft-n-max`를 조정한 결과, draft token 3개에서 72.2 tok/s가 가장 빨랐음
- 메인 모델 단독은 58.2 tok/s였고, Q8 MTP draft model을 더한 구성은 72.2 tok/s였음
- 프롬프트 처리 속도는 거의 유지됐고, 생성 속도는 약 24% 개선됨

### MTP 튜닝 결과
- `--spec-draft-n-max` 값 1부터 6까지 테스트했음
- 값 1은 프롬프트 295.5 tok/s, 생성 68.4 tok/s였음
- 값 2는 프롬프트 299.1 tok/s, 생성 72.0 tok/s였음
- 값 3은 프롬프트 295.6 tok/s, 생성 72.2 tok/s로 가장 빨랐음
- 값 4는 생성 70.7 tok/s, 값 5는 63.7 tok/s, 값 6은 61.2 tok/s로 느려졌음
- M1 Max 환경에서는 `3`이 가장 빨랐고, `2`도 충분히 가까운 결과를 냈음

### MLX 비교
- Mac에서 모델을 실행하는 더 빠른 방식을 확인하기 위해 `mlx-lm` 기반 MLX 모델도 테스트했음
- `llama.cpp Metal + MTP`는 Unsloth GGUF Q4와 Q8 MTP 조합에서 72.2 tok/s를 기록함
- `llama.cpp Metal` 단독은 Unsloth GGUF Q4에서 58.2 tok/s를 기록함
- `MLX-LM`은 Unsloth UD MLX 4-bit에서 45.8 tok/s를 기록함
- `MLX-LM`은 `mlx-community 4-bit`에서 43.9 tok/s, `mlx-community OptiQ 4-bit`에서 38.1 tok/s를 기록함
- 이 특정 구성에서는 **llama.cpp**가 MLX보다 빨랐고, MTP를 적용한 llama.cpp가 가장 좋은 선택이었음
- `gemma-4-swift-mlx`로 Gemma 4 MTP도 시도했지만, 테스트한 26B 4-bit MLX 체크포인트가 로더의 예상 weight key와 맞지 않아 새 모델을 다시 내려받아 조정하지 않고 중단함

### 이미지 지원 추가
- Pi에서 스크린샷을 첨부하려면 모델 입력이 텍스트 전용이면 안 됨
- 원래 로컬 모델 항목은 `"input": ["text"]`로 설정되어 있었고, 이 경우 Pi가 이미지 도구 출력을 모델에 제대로 보내지 못함
- `llama.cpp` 서버도 멀티모달 기능을 위해 Gemma 4 **multimodal projector**인 `mmproj-BF16.gguf`가 필요함
- `--mmproj`로 projector를 로드하면 `llama.cpp`가 멀티모달 지원을 알리고 Pi가 이미지를 보낼 수 있음
- projector 없이 `llama.cpp Metal + MTP`를 실행한 테스트는 프롬프트 120.3 tok/s, 생성 71.4 tok/s였음
- `mmproj-BF16.gguf`를 로드한 최종 실행은 프롬프트 297.4 tok/s, 생성 72.2 tok/s였음
- projector를 로드한 최종 실행에서 텍스트 생성 속도 저하는 나타나지 않았음

### llama.cpp 설치
- 의존성은 Homebrew로 `cmake`, `git`, `tmux`, `python@3.11`을 설치함
- `~/Developer/ML-Models/Gemma4/repos` 경로를 만들고 `ggml-org/llama.cpp` 저장소를 `repos/llama.cpp`로 클론함
- 빌드는 `cmake -B build -DCMAKE_BUILD_TYPE=Release -DGGML_METAL=ON -DGGML_ACCELERATE=ON`으로 구성함
- 이후 `cmake --build build --config Release -j`로 릴리스 빌드를 수행함
- 테스트한 빌드는 `GGML_METAL=ON`, `GGML_ACCELERATE=ON`, `GGML_BLAS=ON`, `GGML_BLAS_VENDOR=Apple` 설정을 가짐

### 모델 파일 다운로드
- Python 3.11 가상환경을 만들고 `huggingface_hub`와 `hf_xet`를 설치함
- `huggingface-cli download`로 Gemma 4 메인 모델, `mmproj-BF16.gguf`, MTP draft model을 내려받음
- 다운로드 대상 파일은 `gemma-4-26B-A4B-it-UD-Q4_K_XL.gguf`, `mmproj-BF16.gguf`, `MTP/gemma-4-26B-A4B-it-Q8_0-MTP.gguf`임
- 최종 모델 폴더는 `models/unsloth-gemma-4-26B-A4B-it-GGUF/` 아래에 세 파일을 포함함

### 로컬 서버 시작
- 최종 서버는 `llama-server`로 실행하며, 메인 모델과 MTP draft model, multimodal projector를 모두 지정함
- 주요 옵션은 `--spec-type draft-mtp`, `--spec-draft-n-max 3`, `-ngl 999`, `-fa on`, `-c 65536`, `--parallel 1`임
- 서버는 `--host 127.0.0.1 --port 8080`으로 실행함
- OpenAI 호환 엔드포인트는 `http://127.0.0.1:8080/v1`임
- `start_server.sh` 래퍼는 `tmux` 세션에서 서버를 실행하고 로그를 `logs/llama-server-mtp.log`에 남김
- `chmod +x start_server.sh` 후 `./start_server.sh`로 서버를 시작함
- 서버 동작 여부는 `curl http://127.0.0.1:8080/v1/models`로 확인함

### Pi 설정
- Pi는 모델 제공자 설정을 `~/.pi/agent/models.json`에서 읽음
- 로컬 제공자 `gemma4-local`의 `baseUrl`은 `http://127.0.0.1:8080/v1`을 가리킴
- `api`는 `openai-completions`이고, 로컬 서버이므로 `authHeader`는 `false`로 둠
- 모델 ID는 `gemma-4-26B-A4B-it-UD-Q4_K_XL.gguf`이고, 이름은 `Gemma 4 26B-A4B Q4 + MTP`로 설정함
- `input`은 `["text", "image"]`여야 하며, 그렇지 않으면 Pi가 모델을 텍스트 전용으로 취급함
- 컨텍스트 윈도는 65536, 최대 토큰은 8192로 설정함
- 필요하면 `~/.pi/agent/settings.json`에서 `defaultProvider`를 `gemma4-local`, `defaultModel`을 해당 GGUF 파일명으로 지정함
- `pi --offline --list-models gemma` 실행 시 이미지 지원이 `yes`로 표시되는 결과를 기대함
- 로컬 모델 실행은 `pi --provider gemma4-local --model gemma-4-26B-A4B-it-UD-Q4_K_XL.gguf`로 수행함
- 비대화형 실행은 `pi -p --provider gemma4-local --model gemma-4-26B-A4B-it-UD-Q4_K_XL.gguf "Explain what this repository does"` 형태로 수행함
- 스크린샷 입력은 `pi -p @"/path/to/screenshot.png" "Describe this image and point out anything relevant to the UI"` 형태로 수행함

### 최종 구성
- 최종 추론 런타임은 `llama.cpp`임
- macOS 가속은 **Metal + Accelerate** 조합임
- 메인 모델은 `gemma-4-26B-A4B-it-UD-Q4_K_XL.gguf`임
- draft model은 `gemma-4-26B-A4B-it-Q8_0-MTP.gguf`임
- MTP 설정은 `--spec-draft-n-max 3`임
- multimodal projector는 `mmproj-BF16.gguf`임
- 서버는 `127.0.0.1:8080`의 `llama-server`임
- API는 OpenAI 호환 `/v1`임
- 코딩 에이전트는 Pi이며, Pi 모델 입력은 `["text", "image"]`임
- MTP draft model은 이 환경에서 Gemma 4 생성 속도를 58.2 tok/s에서 72.2 tok/s로 올렸고, 로컬 OpenAI 호환 서버로 실행할 만큼 구성이 단순함

### Qwen3.6 35B-A3B 대안
- 일부는 `Gemma 4 26B-A4B` 대신 `Qwen3.6 35B-A3B` 사용을 제안함
- 확인 가능한 벤치마크 기준으로 Qwen은 Gemma 4보다 훨씬 더 나은 코딩 에이전트라고 평가됨
- 하지만 Qwen 구성은 더 느렸으며, `Qwen3.6-35B-A3B-UD-Q4_K_XL.gguf`, `unsloth-Qwen3.6-35B-A3B-MTP-GGUF`, `mmproj-BF16.gguf` 조합에서 55 tok/s를 기록함
- 72 tok/s 대신 55 tok/s는 사용자가 기다리는 상황에서 상당한 차이로 작용함
- Qwen 모델 다운로드는 `unsloth/Qwen3.6-35B-A3B-MTP-GGUF`에서 `Qwen3.6-35B-A3B-UD-Q4_K_XL.gguf`와 `mmproj-BF16.gguf`를 받는 방식임
- Qwen 서버는 같은 `llama-server`를 쓰되 `--port 8081`로 실행함
- Pi 설정의 Qwen 제공자 이름은 `qwen36-local`, `baseUrl`은 `http://127.0.0.1:8081/v1`임
- Qwen 모델 설정은 `reasoning: true`, `input: ["text", "image"]`, `contextWindow: 65536`, `maxTokens: 8192`를 사용함

## Comments



### Comment 59567

- Author: neo
- Created: 2026-06-13T22:45:10+09:00
- Points: 1

###### [Hacker News 의견들](https://news.ycombinator.com/item?id=48507020) 
- 벤치마크 프롬프트가 “unified diff를 파싱해 변경된 파일 경로를 반환하는 간결한 Python 함수를 작성하고, 엣지 케이스 두 가지를 설명하라”였고, 각 벤치마크가 약 128토큰을 생성했다면 좋은 결과를 얻기엔 **128토큰**이 너무 적어 보임  
  MTP 가속은 예측 토큰이 얼마나 자주 채택되는지에 달려 있는데, 경험상 출력 초반부는 채택률이 더 높아서 짧은 테스트가 **거짓 양성 가속**을 만들 수 있음  
  llama.cpp에는 서버를 재시작하고 프롬프트를 보낼 필요 없이 인자를 훑어주는 벤치마크 전용 도구가 있음: [https://github.com/ggml-org/llama.cpp/blob/master/tools/llam...](<https://github.com/ggml-org/llama.cpp/blob/master/tools/llama-bench/README.md>)  
  모델 다운로드 섹션도 llama.cpp의 `-hf` 인자가 모델을 대신 내려받아 준다는 점을 언급했어야 함. 작성자가 경험을 공유한 건 고맙지만, 초보자에게는 최선의 가이드가 아닐 수 있음
  - 제대로 된 개발자 가이드로 쓴 글은 아니었음. 화면 녹화가 즐겨찾기를 많이 받고 설정 방법을 묻는 메시지가 오기 시작해서, 이 테스트를 어떻게 구성했는지 빠르게 정리한 것임  
    Unclothe의 “속도 2배” 발표를 보고 “이 정도면 실제로 쓸 만큼 빨라질까?” 싶어서 직접 설정해 봤음  
    작년에도 Devstral 같은 걸로 테스트했지만 너무 느리고 멍청해서 계속 써 볼 마음이 안 들었고, 이번에는 드디어 속도와 지능 모두에서 **쓸 만하다**는 느낌에 도달함
  - 현실적으로는 임의의 사용자 프롬프트에 더해 충분한 **시스템 프롬프트**까지 넣고 실험해야 함. 최소 1000토큰 이상, 실제로는 3000토큰 정도가 좋아 보임  
    llama.cpp에는 이를 위한 도구가 있고, 제대로 측정하려면 토큰 생성 전에 **프리필(prefill)** 을 넣어야 함. 점점 32k나 64k 같은 긴 문맥에서의 토큰 생성 속도 측정도 중요해지고 있음
  - 128토큰이면 오페라가 아니라 **서곡**만 벤치마크하는 셈임
  - 실제 문제를 살피지 않고 “내 컴퓨터에서는 돌아감”이라고 말하는 것과 비슷함. 128토큰은 정말 아무것도 아니고, 짧은 인사 응답보다 조금 긴 수준임

- 예전에 ollama와 opencode를 써서 비슷한 글을 쓴 적이 있음: [https://blog.kulman.sk/running-local-llm-coding-server/](<https://blog.kulman.sk/running-local-llm-coding-server/>)
  - **Ollama**는 좋은 선택이 아님: [https://sleepingrobots.com/dreams/stop-using-ollama/](<https://sleepingrobots.com/dreams/stop-using-ollama/>)  
    opencode는 시스템 프롬프트가 문맥을 너무 많이 먹지 않나? 로컬 모델은 문맥 제약이 큰데, 기억으로 opencode는 그중 10k 정도 또는 그에 가까운 양을 사용함
  - 실제로 유용하고, **ollama GUI**를 쓰면 아마 더 단순화할 수도 있음

- llama.cpp만 쓴다면 무언가를 다운로드하려고 `huggingface-cli`가 꼭 필요하진 않아 보임. `-hf ...`를 넘기면 모델을 내려받아 줌  
  다운로드 위치를 바꾸려면 `LLAMA_CACHE`를 설정하면 됨:  
  `LLAMA_CACHE="models" ./llama-server \`  
  `-hf unsloth/gemma-4-31B-it-GGUF:UD-Q4_K_XL \`  
  `...`
  - 드래프트 모델에는 `-hfd`를 쓰면 됨

- 통합 메모리 RAM은 크지만 테라플롭스와 대역폭 GB/s가 중간 이하라면 보통 **MoE**가 가장 희망적임. 내 환경인 M2 Max 96GB에서 `(지능, tok/s, 문맥 깊이)` 기준 현재 1위는 DeepSeek-V4-Flash REAP25 `<65gb gguf` + ds4-server + pi agent임  
  물론 클라우드 API보다 낫진 않지만, 필요하다면 감수하고 쓸 만큼은 됨. 인터넷 없는 4시간 비행에서도 로컬 LLM이 60W를 먹는데 배터리가 충분히 버텼음  
  REAP을 지원하는 ds4 브랜치는 여기 있음: [https://github.com/ljubomirj/ds4/tree/reap-compact-support](<https://github.com/ljubomirj/ds4/tree/reap-compact-support>)  
  DS4F가 **784K 문맥**에서야 10 tok/s 미만의 사용 불가 수준으로 떨어지는 점이 큰 차이를 만듦

- 이런 로컬 모델이 특정 프로그래밍 언어에 전문가가 아닌 사용자에게도 정말 문제를 해결해 줄 수 있을지 궁금함  
  인라인 자동완성이나 단위 구현을 넘어서, 실제로 작동하는 **기술 명세**를 설계하고 조합할 수 있는지 확신이 안 듦

- llama.cpp/server를 써서 로컬 LLM을 띄우고 Claude Code나 Codex-CLI와 함께 쓰는 건 비교적 간단함  
  필요한 llama server 설정이 여기저기 흩어져 있는 경우가 많아서, 인기 있는 오픈 LLM 몇 가지에 대한 지침을 여기 관리하고 있음: [https://pchalasani.github.io/claude-code-tools/integrations/...](<https://pchalasani.github.io/claude-code-tools/integrations/local-llms/>)
  - 그걸 **일상용**으로 쓰고 있나? Claude Code의 프롬프트가 엄청 커서 로컬 모델에서는 프롬프트 처리에 아주 오래 걸리고, 얼마 지나지 않아 문맥도 다 써버리게 됨

- omlx.ai로 내 하드웨어에 맞는 여러 **MLX 모델**을 다운로드하고, 그 모델로 오픈소스와 폐쇄형 하네스(Claude Code, Codex)를 자동 실행하는 데 꽤 성공적으로 썼음  
  웹 또는 데스크톱 UI에서 모두 가능해서, 개인적으로는 omlx를 쓰면 블로그 글을 따라 할 필요가 없음
  - 64GB M1 Max에서 oMLX나 MLX가 llama.cpp의 **GGUF**보다 특별히 유리한 점은 못 봤음  
    지금까지 찾은 Gemma 4 MLX 빌드는 같은 양자화에서 더 느렸고, MTP에서는 훨씬 느렸음  
    모델을 고른 뒤에는 llama.cpp의 내장 웹 UI가 꽤 좋고, 이것저것 만져볼 때는 LM Studio도 괜찮음  
    Gemma-4와 Qwen 3.6은 일반적인 opencode 시스템 프롬프트의 큰 덩어리가 전혀 필요 없으며, 빼는 편이 더 나음
  - oMLX와 Pi에 붙일 **샌드박스**를 찾는다면 이게 있음: [https://github.com/Dotnaught/pi-sandbox](<https://github.com/Dotnaught/pi-sandbox>)
  - Mac에서 로컬 추론을 위한 **최첨단**이라고 봄. 회귀가 생겨도 개발자들이 엄청 빠르게 대응하고, 최근 본 오픈소스 프로젝트 중 가장 인상적임

- antirez의 ds4로 돌리는 **DeepSeek v4 Flash**가 꽤 인상적이었음  
  “저장된 지식” 측면에서는 GPT-4급 모델처럼 느껴지지만, 긴 흐름의 도구 호출은 GPT-4급 모델들보다 더 잘함  
  128GB MBP M4 Max에서 생성은 약 24 t/s, 프리필은 약 200 t/s가 나옴. 느릴 줄 알았고 코드 생성 같은 작업에서는 실제로 느리지만, 간단한 작업을 위한 **머신 오케스트레이터**로는 놀랄 만큼 유용함  
  에이전트형이 아닌 용도에서는 대화하기에 충분히 괜찮은 모델이고, 완전히 자체 구동·비공개라는 장점도 있음  
  [0][https://github.com/antirez/ds4](<https://github.com/antirez/ds4>)

- 매우 게으르게 하고 싶다면 터미널에서 Claude Code를 열고, 이 글을 가리킨 다음 그냥 “해줘”라고 시키면 됨
  - 이제 Google 검색을 거의 안 하게 됨. 10번 중 9번은 정보 품질이 형편없고, 주변의 스팸 속에서 필요한 내용을 가려내기 어렵기 때문임  
    반면 Claude는 한 번에 처리하거나 아주 조금만 다듬으면 바로 해줌  
    지식과 실행으로 가는 관문은 이제 **LLM**이고, Google Search는 공룡처럼 느껴짐  
    스마트폰보다도 더 멋질 정도로, 한 세기쯤 미래에 와 있는 느낌임
