"A coding agent with the IDE wired in." — pi-mono(Mario Zechner)의 fork, TypeScript + Rust(~55k 줄) 하이브리드. 32개 내장 도구, 14개 LSP 작업, 28개 DAP 작업, 40개+ AI 프로바이더. Claude Code·Cursor 시대에 또 다른 코딩 에이전트가 왜 필요한지 뜯어본다.
터미널에서 돌아가는 AI 페어 프로그래머.
2024~2025년부터 Claude Code, Cursor Agent, Aider, Codex 같은 도구들이 폭발적으로 나왔다. 공통 패턴은 — 터미널이나 IDE 안에서 AI가 직접 파일을 읽고 쓰고 명령을 실행하는 도구다. 사람이 "이거 고쳐 줘" 라고 한 마디 하면, AI가 파일을 찾아서 편집하고 테스트를 돌리고 다시 고치고 — 진짜 동료처럼 일한다.
omp(oh-my-pi)는 그 생태계에서 "하네스(harness)와 도구 표면(tool surface)을 극한까지 다듬은 버전"을 표방한다. 같은 AI 모델(Claude·GPT·Gemini)을 쓰더라도 — 주변 도구가 잘 만들어져 있으면 같은 모델이 훨씬 잘 일한다는 게 핵심 주장. README 첫 표가 그 증거다.
전체 글의 핵심 메시지.
같은 Grok Code Fast 1 모델이 — 표준 도구 셋에서 SWE-bench 6.7%, omp의 hashline 편집 + LSP + Rust 인프로세스 search에서 68.3%. 모델은 그대로다. 주변이 바뀌었다.
omp는 "내가 만난 가장 똑똑한 모델보다, 내가 만난 가장 잘 갖춰진 도구 표면이 더 큰 차이를 만든다"는 가설을 코드로 증명하려는 프로젝트다.
또 다른 코딩 에이전트가 왜 필요한가.
Claude Code, Cursor, Codex, Aider 가 이미 잘 작동하는데 omp가 어떤 자리를 차지하나. README의 주장을 추리면 4가지.
대부분의 에이전트는 str_replace 같은 단순 문자열 치환 방식을 쓴다. 그런데 모델이 옛 코드 라인을 정확히 외워서 보내야 하는데, 공백 한 칸 틀리면 실패하고 재시도한다. 같은 작업을 두세 번 재시도하면서 토큰만 태운다.
모델이 줄을 통째로 베껴 보내지 않고, 콘텐츠 해시(content hash)로 "여기 이 줄"이라고 가리킨다. 파일이 그 사이 바뀌었으면 해시 불일치 → 패치 즉시 거절 (덮어쓰기 사고 방지). Grok 4 Fast의 출력 토큰이 61% 줄어든 이유가 이거다.
대부분 에이전트는 rg(ripgrep), grep, find, bash 같은 외부 바이너리를 쉘로 호출한다. 호출 한 번마다 프로세스 fork-exec 비용 + 표준출력 파싱 비용. Windows에선 그 바이너리가 아예 없어서 안 돌아가는 경우도.
ripgrep·glob·find·bash(brush-shell)·image-decode·BPE counting까지 — 전부 Rust로 짜서 같은 프로세스 안에서 직접 함수 호출. fork-exec이 없으니 빠르다. macOS/Linux/Windows 한 바이너리. WSL 안 필요. ~55,000 줄 Rust 코어가 이 일을 한다.
에이전트가 rename을 하려면 — 변수명 한 곳만 바꾸는 게 아니라 모든 참조·재export·alias import까지 다 같이 바꿔야 한다. 그런데 단순 grep + sed로는 alias된 import를 놓친다. 결국 사람이 마지막 정리를 해야.
omp는 LSP의 workspace/willRenameFiles·references·rename·codeAction까지 다 노출. AI가 rename을 요청하면 — 14개 LSP 작업 중 적절한 걸 호출해서 진짜 IDE처럼 안전하게 작업. "IDE가 아는 건 에이전트도 안다".
대부분 에이전트는 segfault나 hang을 만나면 println·print를 뿌리고 재실행한다. 진짜 디버거를 attach하지 못한다.
C 바이너리 segfault → lldb attach + 스텝 + 프레임 읽기. Go 서비스 hang → dlv + goroutine 워크. Python 멈춤 → debugpy + pause + inspect. 28개 DAP 작업으로 진짜 디버거를 운전한다.
여기에 더해 — 40+ AI 프로바이더(Anthropic·OpenAI·xAI·Gemini·Cursor·Copilot·GLM·Ollama 등) + 14개 웹 검색 백엔드(Exa·Brave·Tavily·Kagi 등) + ACP로 Zed 같은 에디터 통합까지. 한마디로 "이 분야의 다른 도구가 별도로 해결한 모든 문제를 한 패키지에 묶었다"가 트렌딩 6위까지 끌어올린 이유다.
TypeScript 얼굴 + Rust 심장의 하이브리드.
omp는 Node.js가 아니라 Bun으로 권장된다. Bun 1.3.14 이상. Zig로 만든 JavaScript 런타임으로 시작 속도가 Node보다 훨씬 빠르고, 자체 패키지 매니저 + 번들러 + 테스트 러너 내장. 터미널 도구의 cold start가 중요한 만큼 — 마지막 0.1초까지 짜내는 선택.
도구·세션 관리·프로바이더 라우팅·TUI(터미널 UI)·서브에이전트 오케스트레이션 — 모두 TypeScript. 모노레포(monorepo)로 14개+ 패키지가 함께 산다. 코드는 전부 MIT 라이선스로 공개.
~55k 줄 Rust 코어. N-API(Node-API)로 묶여 TypeScript 측에서 native 함수처럼 호출. fork-exec 비용 없이 같은 프로세스에서 직접 실행. pi-natives, pi-shell, pi-ast, pi-iso 4개 크레이트로 분리.
이 표가 omp의 본질을 가장 잘 보여 준다. 다른 에이전트가 외부 도구로 쉘 호출하는 모든 것을 Rust로 인프로세스 구현. brush-shell이라는 Rust로 짠 bash 호환 셸까지 vendor 해서 박아 넣었다.
직접 API. oauth 태그가 있는 건 OAuth 로그인 지원(Anthropic, Google Antigravity, Perplexity, OpenAI Codex 등). 자기 API 키 또는 OAuth 로그인.
한 달 구독으로 코딩 모델 무제한 쓰는 플랜들을 omp에서 그대로 활용. Kimi Code, MiniMax Coding Plan, Alibaba Coding Plan(Qwen) 같은 중국발 플랜들도 모두 라우팅 가능.
OpenAI 호환 /v1/models 엔드포인트면 다 붙는다. 로컬 인스턴스는 API 키 없이도 OK. 보안에 민감한 환경에서 자체 호스팅 모델을 쓸 수 있다는 게 핵심.
40+ 프로바이더를 한 세션에서 같이 쓰는 방법.
default(보통), smol(저렴 — 서브에이전트용), slow(깊은 추론), plan(계획 모드), commit(체인지로그)~/.omp/agent/models.yml에 OpenAI/Anthropic/Google 포맷 호환이면 뭐든 선언전체 그림 + 가장 차별되는 5개 깊이 분석.
이 그림에서 핵심은 — "한 프로세스 안에 다 들어 있다"는 점이다. shell도, grep도, AST 파서도, 디버거 클라이언트도, LSP 클라이언트도 모두 같은 프로세스 메모리를 공유하며 작동한다. fork도 IPC도 없다.
편집 시 모델이 줄을 베껴 보내지 않고 콘텐츠 해시로 anchor 지정. 파일이 그 사이 바뀌면 해시 mismatch → 패치 거절. 스테일 파일 덮어쓰기 사고를 사전 차단하면서 토큰까지 절약. Grok 4 Fast 기준 출력 토큰 -61%.
사용자의 룰이 평소엔 잠자다가, 모델이 잘못된 길로 가는 순간 — 정규식 매치로 스트림을 mid-token에서 중단, 룰을 시스템 리마인더로 주입, 같은 지점에서 재시도. 매 턴 룰을 컨텍스트에 박지 않으니 토큰 절약 + compaction 후에도 주입이 살아남는다. "AI가 Box::leak을 쓰려는 순간 룰이 깨우는 그림".
대부분 에이전트는 Python sandbox 하나로 끝. omp는 Python과 Bun 두 커널이 영구 세션으로 살아있고, 그 안에서 다시 read·search·task 같은 에이전트 도구를 호출 가능. Python 안에서 tool.read로 CSV 읽고, JavaScript로 차트 만들기 — 셀을 떠나지 않고.
task 도구로 서브에이전트 fan-out. 각 워커가 isolated worktree(APFS clone, btrfs/zfs reflink, overlayfs, projfs 중 환경 맞춤)에서 독립 작업. 최종 결과는 스키마 검증된 객체로 부모에게 반환 — prose 파싱이 아니라 typed result. 형제들끼리 IRC로 짧은 메시지 교환 가능.
pr://1428, issue://42, agent://findings.0.path, skill://..., conflict://1 — 10개+ 내부 스킴을 모든 FS-shaped 도구가 인식. PR 읽기 = 파일 읽기. 머지 컨플릭트 해결 = write conflict://1 @theirs. 에이전트가 외워야 할 도구가 줄어들고, 한 인터페이스로 모든 걸 처리.
conflict://N에 @theirs/@ours/@base 쓰기모노레포 + Rust 크레이트의 이중 구조.
사용자가 omp를 실행할 때 직접 진입하는 패키지. CLI 인자 파싱, TUI 띄우기, 세션 매니저 초기화, 도구 등록, 슬래시 커맨드 등록. SDK 모드(SessionManager, createAgentSession)도 여기서 export.
실제 에이전트 루프 로직. 도구 호출, 응답 해석, 도구 결과를 다시 모델에 먹이기, 컨텍스트 관리. UI와 분리돼 있어 RPC/ACP/SDK 모드에서도 같은 코어가 동작.
TypeScript 측 packages/natives가 Rust 측 pi-natives를 호출하는 다리. 플랫폼별 prebuilt binary (linux-x64, linux-arm64, darwin-x64, darwin-arm64, win32-x64) 5개를 npm publish 시 함께 배포. 사용자는 빌드 안 해도 됨.
외부 의존성 brush-shell를 vendor한 크레이트. "왜 vendor를 했나" — omp의 hot path에 들어가는 만큼 빠른 빌드와 패치 컨트롤이 필요해서. Mario Zechner의 fork가 시작점이라, "fork에 또 fork"의 layered 구조.
코딩 에이전트를 만든다면 꼭 봐야 할 패턴.
같은 Grok Code Fast 1이 6.7%→68.3%로 점프하는 데이터는 충격적이다. 좋은 모델을 기다리기보다, 가진 모델에 좋은 도구 표면을 만드는 게 ROI가 높다. 자기 에이전트 만들 때도 — 모델 업그레이드보다 편집 포맷·검색 도구·LSP 통합 같은 인프라에 먼저 투자.
omp가 ripgrep/glob/find/bash를 다 Rust로 내장한 이유 — fork-exec 비용 + Windows 호환성 + 표준출력 파싱 비용을 한 번에 없애려고. 자기 도구 만들 때도 외부 바이너리 의존을 줄일수록 단단해진다.
PR도 파일, 이슈도 파일, 컨플릭트도 파일, 서브에이전트 결과도 path. "한 인터페이스로 모든 걸 다루게" 만들면 — AI가 외워야 할 도구가 줄어들고, 사람이 디버깅할 면적도 줄어든다. UNIX의 "everything is a file" 철학을 LLM 시대에 재발견한 셈.
git의 content-addressing 아이디어를 편집 도구에 적용. 파일이 그 사이 바뀌면 거절 → 사고 방지 + 토큰 절약. 편집 작업이 멱등성을 갖게 만드는 핵심 패턴. 자기 도구에도 hash 기반 anchor를 도입할 가치.
40+ 프로바이더 라우팅의 핵심 4노브 — 역할(default/smol/slow/plan), 커스텀 프로바이더, 페일오버 체인, 라운드로빈 키. 자기 에이전트가 여러 모델을 쓴다면 이 4가지를 표준 노브로 도입.
실제 돌리려면 뭐가 필요한가.
플랫폼 자동 감지 → 적절한 prebuilt binary 설치. ~/.omp/에 설정 폴더.
Bun ≥ 1.3.14 필요. 별도 인스톨 스크립트 없이도 동작. 업그레이드도 bun update -g로.
WSL 안 필요. omp는 Windows 네이티브 바이너리로 동작. ripgrep/glob/bash 다 내장돼 있어 외부 도구 없이 같은 동작.
최소 한 개 프로바이더의 API 키 또는 OAuth 로그인. Anthropic·OpenAI·Gemini API 키, Cursor/Copilot 구독, 또는 로컬 Ollama. /login 슬래시 커맨드로 설정.
LSP 기능을 쓰려면 해당 언어의 LSP 서버 설치 필요. (TypeScript는 보통 자동, Python은 pyright/pylsp, Rust는 rust-analyzer 등). 디버거 기능엔 lldb·gdb·dlv·debugpy 같은 해당 언어 디버거.
난이도 ★~★★★★★.
omp 설치 후 자기 프로젝트 디렉토리에서 omp 실행. "이 레포의 README를 한 문단으로 요약해 줘" 같은 단순 작업으로 워크플로우 익히기. TUI의 도구 카드, 슬래시 커맨드(/model, /login), Ctrl+P 모델 사이클을 체험.
실제 프로젝트에서 변수/함수 이름을 한 번 일괄 변경. "이 변수 rename해 줘"만 던지고, omp가 LSP를 통해 모든 참조·alias·재export까지 안전하게 갱신하는지 관찰. 같은 작업을 grep + sed로 하면 얼마나 빠뜨릴지 비교.
일부러 segfault나 hang을 만들고 omp에게 디버거로 잡으라고 요청. C 코드면 lldb, Python이면 debugpy. 에이전트가 print 디버깅 대신 진짜 디버거를 운전하는 모습이 인상적.
TypeScript 모듈 한 개로 omp 확장을 작성. 같은 도구 API·슬래시 커맨드 API·핫키 테이블 사용. 자기 워크플로우에 맞춘 새 슬래시 커맨드(예: /deploy-staging)를 만든다. /reload-plugins로 즉시 적용.
Node/TypeScript 호스트 앱에 @oh-my-pi/pi-coding-agent를 import. SessionManager·createAgentSession으로 자기 앱 컨텍스트에서 에이전트 동작. 예: 사내 도구 안에서 "이 데이터 분석해 줘" 같은 명령을 자기 도구 서피스로 처리.
4주 코스.
omp + Claude Code + Cursor Agent + Aider 4개를 같은 작업으로 돌려본다. 토큰 사용량·완료 시간·결과 품질 비교. 어디서 omp가 빛나고 어디서 다른 게 나은지 감 잡기.
microsoft/language-server-protocol 스펙 정독. omp가 노출하는 14개 LSP 작업·28개 DAP 작업을 직접 실험. 이걸 알면 자기 에이전트 만들 때도 LSP/DAP를 어떻게 통합할지 청사진이 생긴다.
N-API + napi-rs로 작은 Rust 네이티브 모듈을 직접 만들어 Node/Bun에서 호출. omp의 pi-natives가 어떻게 짜여 있는지 코드 읽기 + 자기 도구에 한 모듈 추가. "외부 바이너리 fork-exec 비용을 없애는 경험"을 손에 익힌다.
Zed 또는 ACP 지원 에디터에서 omp acp 모드로 에이전트를 띄우고, 에디터의 버퍼·터미널·permission 프롬프트로 작업. 또는 ACP 클라이언트를 직접 만들어 자기 도구에 통합.
짧은 정의 모음.
--tools로 활성 집합 핀 가능, search_tool_bm25로 나머지 도구를 mid-session에 검색 활성화.napi-rs로 N-API에 맞는 cdylib을 빌드. Bun도 N-API 호환.summarize·ast_grep 도구가 이걸 기반.search_tool_bm25가 "현재 작업에 어떤 도구가 가장 관련 있나"를 점수화해서 자동 활성화하는 데 사용.레포·문서·관련 도구.
@oh-my-pi/pi-coding-agentcurl -fsSL https://omp.sh/install | sh 한 줄로 끝. 자기 작은 프로젝트에서 "README 한 문단 요약" 정도로 워크플로우 익히기.auto 체인에서 우선순위 위로 올리기. 한 번 켜 두면 다른 도구에서도 같은 모델·키를 활용 가능.