Pi: 내 방식대로 조립하는 코딩 에이전트

코딩 에이전트를 쓰다 보면 기능이 많아서 편한 순간도 있지만 답답할 때도 있습니다. 계획 모드의 동작이 마음에 안 들 수 있어요. 권한 확인 창이 작업 흐름을 자꾸 끊거나 꼭 필요한 모델을 지원하지 않기도 하죠. 제품이 정해둔 방식에 내 작업을 끼워 맞추는 기분이 듭니다.
이런 불편을 직접 고쳐 쓰고 싶을 때 눈에 들어오는 도구가 Pi입니다. Pi는 스스로를 최소형 에이전트 하네스(minimal agent harness)라고 소개해요. 필요한 기능을 전부 내장하지 않고 작고 단단한 코어(core) 위에 확장(extension)과 스킬(skill)을 얹도록 설계됐습니다. 프롬프트 템플릿(prompt template)과 테마(theme)도 마음대로 바꿀 수 있고요.
처음 실행하면 다른 터미널 코딩 에이전트와 크게 달라 보이지 않습니다. 파일을 읽고 고치며 셸 명령을 실행하죠. 하지만 조금만 들여다보면 방향이 꽤 과감합니다. 내장 계획 모드(plan mode)도, 하위 에이전트(sub-agent)도, 권한 확인 창(permission prompt)도 없어요. 필요하면 직접 만들거나 패키지로 설치하라는 겁니다.
기능을 일부러 뺀 도구가 왜 매력적일까요? 이번 글에서는 Pi의 철학과 기본 사용법을 알아봅니다. 대화 이력 트리와 확장 시스템을 써보고 어디서 주의해야 하는지도 짚어볼게요.
Pi는 무엇인가
Pi를 이해하려면 먼저 코딩 에이전트의 작동 원리에서 말하는 언어 모델과 하네스를 분리해서 봐야 합니다. 언어 모델이 다음 행동을 판단하는 두뇌라면 하네스는 모델에 파일 도구와 셸을 연결하는 실행 환경입니다. 대화 이력과 컨텍스트(context)도 하네스가 관리하죠.
Claude Code나 Codex 같은 제품은 모델과 하네스뿐 아니라 계획부터 권한과 작업 관리 방식까지 하나의 완성된 경험으로 제공합니다. 빠르게 시작하기 좋지만 제품이 선택한 작업 흐름(workflow)에 영향을 많이 받습니다.
Pi는 다른 길을 택했어요. 기본 코어에는 파일 읽기와 쓰기, 부분 수정, 셸 실행이라는 네 가지 도구를 제공합니다. 여기에 모델 호출과 대화형 터미널 사용자 인터페이스(terminal user interface, TUI)를 붙였습니다. 세션(session)이나 대화 이력 관리처럼 에이전트 실행에 꼭 필요한 토대만 두고 나머지는 사용자가 조립합니다.
이런 설계는 Harness Engineering의 개인용 구현체에 가깝습니다. 좋은 에이전트를 고르는 데서 끝나지 않고 에이전트가 일하는 환경 자체를 코드와 설정으로 다루는 거죠. Pi의 구호인 “작업 흐름을 Pi에 맞추지 말고, Pi를 작업 흐름에 맞추라”가 방향을 잘 보여줍니다.
설치와 첫 대화
Pi는 npm 패키지로 배포됩니다. Bun을 쓴다면 다음 명령으로 전역 설치(global install)할 수 있어요. --ignore-scripts는 의존성의 생명주기 스크립트(lifecycle script) 실행을 막는 옵션입니다. Pi는 일반적인 설치 과정에서 이 스크립트를 필요로 하지 않습니다.
$ bun add -g --ignore-scripts @earendil-works/pi-coding-agent
macOS나 Linux에서는 공식 설치 스크립트도 쓸 수 있습니다.
$ curl -fsSL https://pi.dev/install.sh | sh
설치가 끝나면 작업할 프로젝트로 이동해 pi를 실행합니다.
$ cd my-project
$ pi
처음에는 모델 제공자(provider)를 연결해야 하는데요. 대화창에서 /login을 입력하면 ChatGPT Plus나 Pro, Claude Pro나 Max, GitHub Copilot 같은 구독 계정으로 로그인할 수 있습니다. 단, Claude 구독을 외부 하네스에서 사용할 때는 플랜 사용량이 아니라 별도 사용량으로 과금될 수 있으니 로그인 화면과 공식 제공자 문서를 확인하는 편이 안전합니다.
API 키를 쓰고 싶다면 환경 변수(environment variable)로 넘겨도 됩니다.
$ export ANTHROPIC_API_KEY="sk-ant-..."
$ pi
Pi의 장점은 특정 모델 회사에 묶이지 않는다는 데 있습니다. Anthropic과 OpenAI, Google을 비롯한 여러 API와 클라우드 제공자를 지원해요. Ollama나 llama.cpp 같은 로컬 모델(local model)도 연결할 수 있습니다. 대화 중 /model을 실행하거나 Ctrl+L을 누르면 모델을 바꿀 수 있어 모델마다 잘하는 일이 달라도 세션을 새로 열 필요가 없습니다.
기본 사용법
프로젝트에서 Pi를 실행한 뒤 평소 말하듯 요청하면 됩니다.
이 저장소의 구조를 요약하고 변경 후 실행해야 하는 검사를 알려줘.
Pi는 현재 디렉터리를 기준으로 파일을 읽습니다. 필요하면 코드를 고친 뒤 셸 명령까지 실행하죠. @를 입력하면 프로젝트 파일을 퍼지 검색(fuzzy search)해서 대화에 첨부할 수도 있어요.
$ pi @README.md "이 프로젝트의 개발 환경을 설명해줘"
대화형 모드(interactive mode)에서 !로 시작하는 명령은 직접 실행되고 출력도 모델에 전달됩니다. 반면 !!는 명령만 실행하고 결과를 모델의 컨텍스트에는 넣지 않습니다. 빌드 출력이 너무 길거나 에이전트가 볼 필요가 없는 명령에 유용해요.
!bun run typecheck
!!git status --short
프로젝트 규칙은 AGENTS.md나 CLAUDE.md에 적어두면 됩니다. Pi는 사용자 홈의 ~/.pi/agent/AGENTS.md부터 현재 디렉터리와 상위 디렉터리의 컨텍스트 파일을 찾아 합칩니다. 테스트 명령과 코딩 규칙처럼 매번 설명하기 귀찮은 내용을 넣어두세요. 건드리면 안 되는 파일도 적어두면 좋고요.
# Project Instructions
- 코드 변경 후 `bun run typecheck`를 실행합니다.
- 프로덕션 마이그레이션은 로컬에서 실행하지 않습니다.
- 새 의존성을 추가하기 전에 이유를 설명합니다.
파일을 고친 뒤에는 /reload로 규칙과 확장 자원을 다시 불러올 수 있습니다.
세션 트리
긴 코딩 작업에서 대화 이력은 단순한 채팅 로그가 아닙니다. 잘못된 접근을 버리고 이전 결정 지점으로 돌아갈 수 있어야 하죠. 두 해결책을 나란히 시험하고 싶을 때도 있습니다.
Pi는 세션을 트리 구조(tree structure)로 저장합니다. /tree를 실행하면 이전 메시지로 이동해 거기서 새 분기를 만들 수 있어요. 기존에 진행한 분기도 같은 줄 단위 JSON(JSON Lines, JSONL) 파일에 남기 때문에 한쪽을 선택했다고 다른 시도가 사라지지 않습니다.
예를 들어 인증 버그를 고치다가 쿠키 방식과 토큰 방식 두 가지가 모두 가능하다는 걸 알게 됐다고 해볼까요? 첫 번째 방식으로 진행한 뒤 /tree로 설계 결정을 내리기 전 메시지로 돌아가 두 번째 방식도 시험할 수 있습니다. 결과를 비교한 뒤 더 나은 분기를 이어가면 돼요.
세션은 작업 디렉터리별로 ~/.pi/agent/sessions/에 자동 저장됩니다. 최근 작업을 바로 잇거나 이전 세션 목록에서 고를 수도 있습니다.
$ pi -c # 가장 최근 세션 계속하기
$ pi -r # 이전 세션 찾아서 열기
대화가 모델의 컨텍스트 한도에 가까워지면 Pi가 오래된 내용을 자동으로 압축(compaction)합니다. 최근 작업은 남기고 앞부분을 구조화된 요약으로 바꾸는 방식이에요. 필요하면 /compact로 직접 실행할 수 있고, 확장을 통해 요약 방식 자체도 바꿀 수 있습니다.
빠진 기능으로 보는 Pi의 철학
Pi가 특별한 이유는 무엇을 넣었는가보다 무엇을 넣지 않았는가에서 선명해집니다. 공식 문서는 내장하지 않은 기능을 꽤 솔직하게 밝히고 있어요.
| 원하는 기능 | Pi가 제안하는 방식 |
|---|---|
| 계획 모드 | 계획을 파일에 쓰거나 확장으로 구현 |
| 하위 에이전트 | tmux에서 Pi를 더 실행하거나 패키지 설치 |
| 권한 확인 | 컨테이너를 쓰거나 확인 확장 구현 |
| 할 일 목록 | TODO.md를 쓰거나 전용 도구 추가 |
| 백그라운드 셸 | tmux로 직접 관찰하며 실행 |
| MCP | CLI와 스킬을 쓰거나 MCP 확장 설치 |
여기에는 분명한 취향이 있습니다. 여러 해법이 가능한 기능을 코어에서 하나로 못 박지 않겠다는 거예요. MCP가 모든 외부 도구 연결에 꼭 맞는다고 보지도 않습니다. 잘 만든 CLI와 사용법이 담긴 스킬이면 충분한 경우가 많다는 판단이죠.
처음부터 모든 기능이 있어야 마음이 놓이는 사용자에게는 불친절하게 느껴질 수 있습니다. 반대로 내 도구와 보안 정책, 팀 규칙에 맞춰 하네스를 설계하고 싶다면 이런 빈 공간이 자유가 됩니다.
스킬과 확장
Pi의 사용자 정의 수단은 역할이 나뉘어 있습니다. 프롬프트 템플릿은 자주 쓰는 요청을 재사용하고 테마는 TUI 모양을 바꿉니다. Agent Skills는 특정 작업의 지침과 스크립트를 필요할 때만 불러옵니다. 자세한 참고자료도 스킬 안에 함께 둘 수 있어요.
TypeScript로 작성하는 확장은 손댈 수 있는 범위가 훨씬 넓습니다. 도구 호출 전후나 세션 시작 같은 생명주기 이벤트(lifecycle event)를 가로챌 수 있어요. 새 도구와 슬래시 명령을 등록하고 TUI까지 바꿉니다.
Pi에는 기본 권한 확인 창이 없는데요. 위험한 명령만 확인받고 싶다면 프로젝트의 .pi/extensions/에 다음과 같은 확장을 만들 수 있습니다.
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
export default function (pi: ExtensionAPI) {
pi.on("tool_call", async (event, ctx) => {
if (
event.toolName === "bash" &&
event.input.command?.includes("rm -rf")
) {
const allowed = await ctx.ui.confirm(
"위험한 명령",
"rm -rf 실행을 허용할까요?",
);
if (!allowed) {
return {
block: true,
reason: "사용자가 명령 실행을 거부했습니다.",
};
}
}
});
}
저장하고 /reload를 실행하면 곧바로 적용됩니다. 완성된 기능을 따로 기다릴 필요 없이 하네스를 실행 중에 고쳐 쓰는 셈이죠. 경로 보호와 Git 체크포인트부터 사용자 정의 도구와 장기 메모리까지 같은 방식으로 만들 수 있습니다. 상태줄도 예외가 아니고요.
여러 자원을 묶어 공유하려면 Pi 패키지를 사용합니다. 확장, 스킬, 프롬프트, 테마를 하나로 묶어 npm이나 Git 저장소에서 설치할 수 있어요.
$ pi install npm:@acme/pi-team-tools
$ pi install git:github.com/acme/pi-workflow
다만 Pi 패키지의 확장은 사용자 계정과 같은 시스템 권한으로 실행됩니다. 스킬도 에이전트에게 임의의 명령 실행을 지시할 수 있고요. 설치 전에 반드시 소스와 변경 이력을 확인해야 합니다.
대화형 터미널 밖의 Pi
Pi는 터미널에서 사람과 대화하는 용도에만 머물지 않습니다. 실행 방식은 네 가지입니다.
대화형 모드는 TUI에서 직접 작업할 때 씁니다. 출력 모드(print mode)는 pi -p로 한 번 요청하고 결과를 받는 자동화에 어울려요. JSON 모드는 이벤트를 구조화해 내보냅니다. 원격 프로시저 호출(remote procedure call, RPC) 모드는 표준 입출력의 JSONL 프로토콜로 다른 언어의 프로그램과 연결합니다.
마지막으로 소프트웨어 개발 키트(software development kit, SDK)를 이용하면 Pi의 에이전트 세션을 TypeScript 애플리케이션에 직접 넣을 수 있습니다.
import {
createAgentSession,
ModelRuntime,
SessionManager,
} from "@earendil-works/pi-coding-agent";
const modelRuntime = await ModelRuntime.create();
const { session } = await createAgentSession({
sessionManager: SessionManager.inMemory(),
modelRuntime,
});
await session.prompt("현재 디렉터리의 파일을 요약해줘.");
사내 개발 도구에 에이전트를 넣거나 자체 UI를 만들 때 유용합니다. CI 파이프라인에서 판단이 필요한 작업도 처리할 수 있어요. 터미널 제품과 SDK가 별개의 구현이 아니라 같은 하네스를 공유한다는 점도 눈에 띕니다.
직접 설계하는 보안
Pi를 평가할 때 가장 주의 깊게 봐야 할 부분입니다. Pi에는 내장 격리 환경(sandbox)이 없습니다. Pi가 실행한 도구는 Pi를 시작한 사용자 계정의 권한으로 동작합니다. 프로젝트 신뢰(project trust) 기능은 로컬 설정과 확장을 불러올지 결정합니다. 패키지도 여기 포함되지만 파일이나 명령 접근을 격리해 주지는 않습니다.
출처를 모르는 저장소에서 곧바로 Pi를 실행하거나 검토하지 않은 확장을 설치하면 위험할 수 있습니다. 중요한 환경에서는 Docker 같은 컨테이너(container)나 별도의 격리 환경 안에서 실행해야 해요. 쓰기 권한이 필요한 경로만 연결하세요. 인증 정보와 운영 환경 접근 권한도 최소화하는 편이 좋습니다.
권한 확인 창이 없어서 편하다는 말은 아무 명령이나 믿고 실행해도 된다는 뜻이 아닙니다. Pi는 보안 정책도 작업 흐름의 일부로 직접 설계하라는 도구입니다. 앞서 만든 확인 확장은 실수를 줄여주지만 격리 환경을 대신하지는 못합니다.
Pi가 잘 맞는 개발자
Pi는 코딩 에이전트를 설치하자마자 모든 기능이 갖춰진 제품으로 쓰고 싶은 사람보다 자신의 작업 방식을 직접 설계하고 싶은 개발자에게 잘 맞습니다. 여러 모델을 오가며 비교하는 분이라면 특히 재미있을 거예요. TypeScript로 도구와 UI를 만들거나 팀의 스킬과 확장을 패키지로 공유하기도 좋습니다.
반면 내장 계획 모드와 세밀한 권한 승인을 원한다면 다른 제품이 더 편할 수 있습니다. 공식 IDE 통합처럼 정돈된 기본 경험이 중요한 경우도 마찬가지예요. Pi에서도 구현할 수 있지만 가능하다는 것과 처음부터 편하다는 것은 다른 이야기니까요.
결국 선택 기준은 기능 개수가 아닙니다. 제품이 정한 안전하고 완성된 길을 선호하는지, 작은 코어를 바탕으로 자신만의 하네스를 만들고 싶은지의 차이에 가깝습니다.
마치며
Pi는 “또 하나의 코딩 에이전트”라기보다 코딩 에이전트를 만드는 재료에 가깝습니다. 기본 도구와 세션 관리, 여러 모델 연결은 바로 쓸 수 있게 제공하면서도 계획 모드, 하위 에이전트, 권한 확인 같은 기능은 의도적으로 사용자의 선택에 맡깁니다.
첫인상은 소박하지만 오래 들여다볼수록 가능성이 커집니다. 기존 제품의 작업 흐름이 답답했다면 작은 프로젝트에서 Pi를 한번 실행해보세요. 에이전트가 일하는 환경을 코드로 관리해보고 싶은 분에게도 잘 맞습니다. 먼저 기본 기능만 써보다가 반복해서 아쉬운 지점이 생길 때 확장이나 스킬을 하나씩 더해보세요.
설치 옵션과 최신 제공자 목록은 Pi 공식 문서에서 확인할 수 있습니다. 확장을 만들 때 사용할 수 있는 이벤트와 API는 확장 문서를 참고하세요.
This work is licensed under CC BY 4.0