"AI agent toolkit: unified LLM API, agent loop, TUI, coding agent CLI" 45.9k 스타, 3,967 커밋, 213 릴리스. Mario Zechner(badlogic)가 이끄는 4패키지 TypeScript 모노레포. MCP·서브에이전트·플랜 모드·권한 팝업까지 전부 빼버린 대신 Extensions · Skills · Prompt Templates · Themes 네 갈래로 사용자가 직접 빌드해 끼우는 철저한 BYO 구조다.
"한 마디로 무엇을 하는 프로젝트인가."
Pi는 read · write · edit · bash 4개의 기본 도구만 들고 출발한다. grep · find · ls는 tool options로 추가 활성화 가능한 내장 도구다. MCP도, 서브에이전트도, 플랜 모드도, 권한 팝업도, TODO 리스트도 없다. 대신 TypeScript Extension으로 도구·UI·명령·이벤트 핸들러를 마음대로 끼우고, Agent Skills로 모델에게 능력 패키지를 던져주고, Prompt Templates로 자주 쓰는 지시를 슬래시 명령으로 등록한다.
사용자 입장에선 그냥 "터미널에서 자연어로 코딩을 시키는 도구"다. 하지만 그 뒤를 들춰보면, JSONL로 저장되는 트리 구조 세션, 30+ LLM 프로바이더를 통합한 pi-ai 라이브러리, 차분 렌더링으로 60fps를 유지하는 자체 TUI 엔진이 돌아간다. 그 위에 사용자가 직접 짠 확장이 npm 패키지로 유통된다.
Pi = Vim의 코딩 에이전트 버전. Vim은 빈 텍스트 에디터로 시작해서 .vimrc·플러그인으로 사용자가 자기 작업 방식에 맞게 빚어 쓴다. Pi도 똑같다. 코어는 작게 두고, 사용자가 자기 워크플로에 맞춰 npm으로 패키지를 깐다. "에이전트가 내 워크플로에 맞춰주는 게 아니라, 내가 에이전트를 내 워크플로에 맞춘다."
트렌딩 이유, 경쟁 제품 대비 장점.
2026년 5월 23일 TrendShift 일일 트렌딩 12위로 진입한 데에는 세 가지 흐름이 겹쳐 있다.
Claude Code는 강력하지만 Anthropic 모델 중심이고 코드가 닫혀 있다. Pi는 MIT 라이선스 + 30+ 프로바이더 어댑터로 OpenAI·Google·Bedrock·DeepSeek·Groq·xAI·OpenRouter·Cerebras·MiniMax·Kimi·MiMo까지 같은 인터페이스로 돌린다. /login 하나로 ChatGPT Plus 구독, GitHub Copilot 구독을 그대로 활용할 수 있다는 점이 결정타.
플랜 모드·서브에이전트·MCP가 핫한 트렌드인데 Pi는 그걸 의식적으로 거부한다. "MCP가 정말 필요한가"라는 blog 글이 X에서 화제가 되면서 "에이전트는 미니멀해야 한다"는 진영의 깃발이 됐다. "기능은 코어 대신 Extension으로"가 핵심 슬로건.
pi install npm:@foo/pi-tools·pi install git:github.com/user/repo로 npm·git·SSH 어디서든 한 줄로 확장이 깔린다. 이미 openclaw처럼 Pi를 SDK로 임베드한 다운스트림 프로젝트가 등장하고 있고, 인메모리 사이드카로 Pi를 돌리는 도구들이 늘고 있다.
"Pi packages run with full system access. Extensions execute arbitrary code, and skills can instruct the model to perform any action including running executables." — 공식 README가 직접 경고한다. 제3자 패키지를 깔 때는 반드시 소스를 한 번 읽어야 한다. npm install처럼 무심코 깔면 임의 코드 실행 가능.
백엔드 · 프론트엔드 · 인프라 각각 상세히.
Pi는 npm workspaces 기반 TypeScript 모노레포다. 언어 구성은 TypeScript 96.9%, JavaScript 2.4%, CSS·Shell·HTML 약간. 일반적인 "프론트엔드/백엔드/인프라" 구분 대신 4개 패키지로 책임을 나눈 모듈식 구조로 이해해야 한다.
@earendil-works/* npm 스코프로 배포)┌────────────────────────────────────────────────────────────────┐ │ Pi Monorepo (npm workspaces · TS 5.9 · Node 22.19+) │ ├────────────────────────────────────────────────────────────────┤ │ │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │ pi-ai │ ◀ │ pi-agent- │ ◀ │ pi-coding- │ │ │ │ │ │ core │ │ agent (CLI) │ │ │ │ 30+ provider │ │ tool calling │ │ 사용자 진입점 │ │ │ │ 통합 LLM API │ │ + 상태머신 │ │ 인터랙티브 │ │ │ └──────────────┘ └──────────────┘ └──────────────┘ │ │ ▲ │ │ │ 렌더링 │ │ ┌──────────────┐ │ │ │ pi-tui │ │ │ │ Differential │ │ │ │ Rendering │ │ │ └──────────────┘ │ └────────────────────────────────────────────────────────────────┘
pi 명령어가 이 패키지./login 한 번이면 끝.packages/ai/src/env-api-keys.ts).~/.pi/agent/models.json에 OpenAI/Anthropic/Google 호환 엔드포인트를 추가하면 즉시 사용 가능. 비호환 API는 Extension으로 직접 어댑터 작성.~/.pi/agent/sessions/ 아래 작업 디렉토리별로 JSONL 파일. 각 엔트리는 id + parentId 구조 → 단일 파일 안에서 트리 분기.~/.pi/agent/settings.json, 프로젝트는 .pi/settings.json(글로벌을 오버라이드).AGENTS.md(또는 CLAUDE.md) — cwd → 부모 디렉토리 → 글로벌 순으로 모두 연결해서 로드..pi/SYSTEM.md로 통째로 교체하거나 APPEND_SYSTEM.md로 뒤에 붙이기 가능.npm run check에서 tsgo --noEmit로 타입체크.npx tsx ../../node_modules/vitest/dist/cli.js 패턴 강제).packages/ai/src, packages/agent/src, packages/coding-agent/src)는 Node의 "strip-only" 모드에 호환되는 문법만 허용. enum, namespace, 생성자 파라미터 프로퍼티 금지.--mode json — 한 번 응답하고 종료. stdin 파이프 지원. CI · 스크립트 친화.--mode rpc) — stdin/stdout JSONL로 외부 프로세스와 양방향 통신. Node가 아닌 언어에서 Pi를 임베드할 때 사용. ⚠️ 줄 분리는 \n만(Node readline은 유니코드 분리자 때문에 금지).@earendil-works/pi-coding-agent를 npm에 깔고 createAgentSession()으로 자기 앱에 임베드. AuthStorage·ModelRegistry·SessionManager 의존성 주입.시스템 구조도와 핵심 설계 패턴.
┌────────────────────────────┐
Terminal (TUI) ─────▶│ pi-coding-agent (CLI) │
$ pi "리팩터링 해줘" │ - 커맨드 파서 │
│ - 에디터(@파일·!bash·Img) │
│ - 슬래시 명령(/login 등) │
└────────────┬───────────────┘
│ ExtensionAPI 노출
┌─────────────────────┼─────────────────────┐
▼ ▼ ▼
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ Extensions(TS) │ │ Skills(.md) │ │ Prompt Templates │
│ - 도구 추가 │ │ - 모델에게 능력 │ │ - /name 슬래시 │
│ - UI 컴포넌트 │ │ 카드 전달 │ │ 확장 │
│ - 이벤트 훅 │ │ - agentskills.io │ │ │
└──────────────────┘ └──────────────────┘ └──────────────────┘
▼ ▼ ▼
└─────────────────────┴─────────────────────┘
│ Tool calls + 상태머신
▼
┌──────────────────┐
│ pi-agent-core │
│ - Tool dispatch │
│ - Message Queue │
│ - Compaction │
│ - Auth/Provider │
└────────┬─────────┘
│ Unified API
▼
┌──────────────────┐
│ pi-ai │
│ 30+ providers를 │
│ AssistantMessage │
│ EventStream 으로 │
│ 표준화 │
└────────┬─────────┘
│ HTTP/SSE/WebSocket
▼
Anthropic · OpenAI · Google · Bedrock ...
세션 저장: ~/.pi/agent/sessions/<cwd>/*.jsonl
각 엔트리: { id, parentId, role, content, ... } → Tree
대부분의 에이전트는 대화 분기를 위해 별도 파일을 만들지만, Pi는 한 JSONL 파일 안에서 id + parentId 그래프로 분기를 표현한다. /tree 명령어로 트리를 시각적으로 탐색하고, 과거 메시지 어느 지점에서든 분기를 만들어 다른 시도를 해볼 수 있다. /fork는 그 지점에서 새 파일로 떼어내고, /clone은 활성 브랜치를 통째로 복사한다.
Pi 세션은 Git의 commit DAG와 같다. 평소엔 일직선처럼 쓰지만, 필요할 때 어디서든 분기해서 다른 시도를 해볼 수 있다. 그리고 모든 분기 기록은 사라지지 않는다. /tree가 git log --graph --all인 셈.
에이전트가 도구를 호출하고 응답을 기다리는 사이에도 사용자는 다음 메시지를 입력할 수 있다. Enter는 steering 메시지 — 현재 어시스턴트 턴이 끝난 직후 즉시 전달, 방향 수정용. Alt+Enter는 follow-up 메시지 — 에이전트가 모든 작업을 마치면 그때 전달. 설정에서 steeringMode를 "one-at-a-time" 또는 "all"로 바꿔 한 번에 묶어 전달할지 결정.
일반적인 터미널 앱은 화면 전체를 매 프레임 클리어하고 다시 그린다(console.clear() + console.log()). 그러면 깜빡임이 생기고 CPU도 낭비된다. pi-tui는 이전 프레임과 현재 프레임을 셀 단위로 비교해서 바뀐 ANSI 시퀀스만 보낸다. React의 Virtual DOM과 같은 발상을 터미널로 옮긴 것. 그래서 사이드바, 입력창, 에이전트 응답, 푸터가 동시에 살아 움직이면서도 끊김이 없다.
Extension은 단순한 플러그인이 아니라 ExtensionAPI라는 광범위한 인터페이스를 통해 코어와 동등한 위치에서 동작한다. 도구 추가/교체, 명령 등록, 키바인딩, 이벤트 훅(pi.on("tool_call", ...)), 에디터 교체, 헤더/푸터/상태줄, 권한 게이트, MCP 통합, SSH 실행, 게임(공식 예제에 Doom)까지. 코어의 모든 동작을 가로채고 변경할 수 있다.
Pi의 Skills는 agentskills.io 표준을 따른다. 즉 SKILL.md(YAML frontmatter + Markdown 본문) 구조가 Anthropic Skills · Cursor · Cline · Codex와 호환된다. 한 번 짠 스킬을 여러 에이전트에서 재사용할 수 있다는 게 핵심.
Pi의 README에서 가장 인상적인 부분은 의도적으로 제외한 기능 목록이다. 어디서 그어졌는지 그어진 선을 알면 이 도구의 사상이 보인다.
Pi가 사용자의 워크플로에 맞춰지지, 사용자가 Pi의 워크플로에 맞추지 않는다. 이 한 문장이 모든 설계 결정의 근간이다.
주요 폴더 · 파일의 역할.
pi/ ← 레포 루트 (예전 이름: pi-mono) ├── packages/ ← npm workspaces (4개 + examples) │ ├── ai/ ← @earendil-works/pi-ai │ │ ├── src/ │ │ │ ├── types.ts ← Api/Provider/Message 타입 정의 │ │ │ ├── providers/ ← 30+ 프로바이더 어댑터 (1개 파일 = 1 프로바이더) │ │ │ │ └── register-builtins.ts ← lazy loader 등록 │ │ │ ├── env-api-keys.ts ← 환경변수에서 API 키 자동 감지 │ │ │ └── models.generated.ts ← scripts로 자동 생성, 손대지 말 것 │ │ └── scripts/ │ │ └── generate-models.ts ← 모델 목록 자동 생성기 │ │ │ ├── agent/ ← @earendil-works/pi-agent-core │ │ └── src/ ← 툴 디스패치 · 상태머신 · 메시지큐 · 컴팩션 │ │ │ ├── coding-agent/ ← @earendil-works/pi-coding-agent (사용자 진입점) │ │ ├── src/ │ │ │ ├── cli/ ← args 파싱, 모드 분기 │ │ │ ├── core/ ← 모델 리졸버, 프로바이더 표시명 │ │ │ └── tui/ ← TUI 화면 컴포저 │ │ ├── docs/ ← providers.md, sdk.md, rpc.md 등 │ │ ├── examples/ │ │ │ ├── extensions/ ← Extension 샘플 │ │ │ │ ├── with-deps/ │ │ │ │ ├── custom-provider-anthropic/ │ │ │ │ ├── custom-provider-gitlab-duo/ │ │ │ │ └── sandbox/ ← Anthropic sandbox-runtime 사용 │ │ │ └── sdk/ ← SDK 사용 샘플 │ │ ├── test/ │ │ │ └── suite/regressions/ ← <issue#>-<slug>.test.ts 네이밍 강제 │ │ └── CHANGELOG.md │ │ │ └── tui/ ← @earendil-works/pi-tui (차분 렌더링) │ ├── .pi/ ← 프로젝트 로컬 Pi 설정(예제로 포함) ├── .github/ │ └── workflows/ │ ├── issue-gate.yml ← 신규 컨트리뷰터 이슈 자동 닫기 │ ├── pr-gate.yml ← 신규 컨트리뷰터 PR 자동 닫기 │ └── approve-contributor.yml ← lgtmi/lgtm 코멘트로 승인 │ ├── scripts/ ← release.mjs, sync-versions.js, │ generate-coding-agent-shrinkwrap.mjs 등 ├── AGENTS.md ← 사람&에이전트 모두를 위한 프로젝트 규칙 ├── CONTRIBUTING.md ├── biome.json ← Biome 설정 (lint+format) ├── package.json ← 루트, workspaces 선언 ├── tsconfig.base.json ← 공통 TS 설정 ├── pi-test.sh / pi-test.ps1 ← 소스에서 pi 실행 (어디서든) └── test.sh ← API 키 없으면 LLM 의존 테스트 스킵
~/.pi/agent/ ← 글로벌 Pi 환경 ├── settings.json ← 모든 프로젝트 공통 설정 ├── AGENTS.md ← 글로벌 컨텍스트 ├── SYSTEM.md ← 시스템 프롬프트 교체용 ├── APPEND_SYSTEM.md ← 시스템 프롬프트 뒤에 붙이기 ├── keybindings.json ← 키바인딩 커스텀 ├── auth.json ← 프로바이더 인증 토큰 ├── models.json ← 커스텀 프로바이더/모델 ├── prompts/ ← Prompt Templates (.md) ├── skills/ ← Skills (SKILL.md 포함 폴더) ├── extensions/ ← Extensions (.ts/.js) ├── themes/ ← Themes ├── git/ ← git 설치한 패키지 └── sessions/<cwd-hash>/*.jsonl ← 세션 트리 <프로젝트>/.pi/ ← 프로젝트 로컬 Pi 환경(글로벌 오버라이드) ├── settings.json ├── prompts/ · skills/ · extensions/ · themes/ ├── git/ · npm/ ← -l 옵션으로 깐 패키지 └── SYSTEM.md / APPEND_SYSTEM.md
레포 하나에서 얻을 수 있는 12개 분야 핵심 인사이트.
Node 22+의 --experimental-strip-types(이제 안정화 진행)는 빌드 없이 .ts를 실행할 수 있게 해주는데, 단 JavaScript 이미트가 필요한 TS 문법은 못 쓴다. enum·namespace·생성자 파라미터 프로퍼티 금지. AGENTS.md가 이 규칙을 명시적으로 코어 패키지에 강제한다. 배울 점: "빌드 없는 TS" 시대의 글쓰기 습관.
Microsoft가 Go로 다시 짠 TypeScript 컴파일러를 devDependencies에 박아두고 npm run check에서 tsgo --noEmit로 타입체크한다. 배울 점: 4-10배 빨라진 차세대 TS 인프라를 모노레포에 도입하는 실제 방식.
설정 한 파일(biome.json)으로 lint+format을 통합. biome check --write --error-on-warnings .가 일종의 게이트. 배울 점: Rust 기반 차세대 JS 툴체인의 실전 구성.
대화 기록을 트리로 저장하는 발상은 흔치 않다. docs/session-format.md가 포맷을 자세히 설명한다. 실습 아이디어: 자기 챗봇/LLM 앱에 같은 패턴을 도입해서 "분기 + 되감기"가 가능한 대화 UX를 만들어보기.
terminal-kit, blessed, ink는 알지만 pi-tui는 자체 구현. React Reconciler처럼 가상 화면 버퍼와 실제 터미널을 비교해 ANSI 이스케이프를 최소화한다. 실습 아이디어: pi-tui 단독 npm으로 import해서 자기 CLI에 60fps 진행 표시줄을 붙여보기.
30+ 프로바이더를 같은 AssistantMessageEventStream 표면으로 노출하려면 메시지 변환, 도구 호출 매핑, 스트리밍 이벤트(text · tool_call · thinking · usage · stop) 표준화가 필수. packages/ai/src/providers/에 30개 가까운 어댑터 파일이 한 패턴으로 정리된 것을 보면 "어댑터 패턴 + 이벤트 정규화"의 실전 카탈로그다.
scripts/check-pinned-deps.mjs가 모든 의존성이 정확한 버전으로 핀 되어 있는지 검증. lockstep versioning(전 패키지 동일 버전)도 흥미로운 운영 방식. 실습 아이디어: npm workspaces 모노레포를 만들고 release.mjs 스타일의 자동 릴리스 스크립트를 따라 작성해보기.
신규 컨트리뷰터 이슈/PR이 자동으로 닫히고, 메인테이너가 코멘트로 lgtm/lgtmi를 달면 권한이 부여된다. 배울 점: "유지비용 낮은 오픈소스 운영"의 한 모델. 메가 인기 OSS의 이슈 폭주 대응 패턴.
devDependencies에 @anthropic-ai/sandbox-runtime이 박혀 있고 예제 폴더에 sandbox Extension이 있다. 에이전트가 격리된 환경에서 명령을 실행하는 패턴을 들여다볼 수 있는 좋은 참조.
RPC 모드 문서가 Node readline을 절대 쓰지 말라고 명시한다. readline은 유니코드 라인 분리자(U+2028/U+2029)로도 줄을 나누기 때문에 JSON 페이로드 안에 있는 그 문자를 만나면 깨진다. 배울 점: 외부 프로세스 IPC 설계에서 절대 빠뜨리지 말아야 할 함정.
한 모듈 시스템에 4가지 표면을 두는 설계. Skills는 모델에게 능력 카드를 전달(LLM의 인지 확장), Extensions는 런타임에 코드 실행(시스템 확장), Prompt Templates는 사용자가 슬래시 명령으로 호출(UX 확장), Themes는 시각 확장. 각 축의 책임이 명확히 분리되어 있다는 점이 큰 학습 포인트.
Pi는 사용자에게 자기 코딩 세션을 Hugging Face에 업로드하라고 권장한다(badlogic/pi-share-hf). 실제 OSS 작업의 도구 사용·실패·복구 데이터가 모델 학습/평가의 새 골든 데이터셋이 된다는 발상. 이 트렌드는 향후 1-2년간 핵심 흐름이 될 가능성.
설치 · 실행 환경.
engines.node에 명시. 더 낮은 버전은 거부.npmCommand 설정).Alt+Enter가 전체화면 단축키라 리매핑 필요(docs/terminal-setup.md).PI_OFFLINE=1 또는 --offline로 텔레메트리·업데이트 체크까지 차단../test.sh는 키가 없으면 LLM 의존 테스트를 자동 스킵.난이도별 5개 — 한 주에 하나씩 도전.
curl -fsSL https://pi.dev/install.sh | sh 또는 npm i -g @earendil-works/pi-coding-agent로 깔고, /login으로 Anthropic·OpenAI·GitHub Copilot 중 하나에 인증. "이 프로젝트의 폴더 구조 설명해줘"로 가벼운 첫 대화 시작. 목표: Pi가 read·bash·grep을 어떻게 조합해서 답하는지 트레이스 보기.
자기 프로젝트 루트에 AGENTS.md를 짜서 코딩 컨벤션·금지사항·빌드 명령을 적는다. 그다음 ~/.pi/agent/prompts/review.md를 만들어 /review 슬래시 명령으로 코드 리뷰를 즉시 트리거. 목표: Pi의 "컨텍스트 + 슬래시 명령" 워크플로 체화.
~/.pi/agent/skills/csv-cleaner/SKILL.md를 만들고 YAML frontmatter(name, description)와 본문에 단계별 가이드를 작성. /skill:csv-cleaner로 호출. 응용: 같은 SKILL.md를 Anthropic Skills 폴더에 복사해서 호환성 확인. 목표: 한 번 짠 스킬을 여러 에이전트에서 재사용 가능하다는 표준의 가치 체감.
TypeScript로 ~/.pi/agent/extensions/auto-checkpoint.ts를 작성. pi.on("tool_call", ...)로 write/edit 직전에 git stash 생성, 직후에 결과를 체크포인트 브랜치로 커밋. 목표: "에이전트가 망쳐도 되돌릴 수 있다"는 안전망을 직접 짜보면서 Extension API의 위력을 체감. examples/extensions/ 폴더의 샘플을 참고.
@earendil-works/pi-coding-agent를 자기 Node 앱에 깔고 createAgentSession()로 세션을 만든 뒤, Slack Bolt 핸들러에서 멘션이 올 때마다 session.prompt()를 호출. SessionManager.inMemory()로 휘발성 세션 사용. 목표: Pi를 한 사용자가 쓰는 CLI가 아닌 "조직 봇"으로 확장. 가능하면 자매 레포 pi-chat 참고.
4주 주차별 학습 계획.
anthropics/skills 레포 16개 스킬 분석.packages/tui/src를 읽으며 차분 렌더링 알고리즘을 자기 말로 정리.packages/ai/src/providers/에서 어댑터 3개(Anthropic/OpenAI/Google) 비교 분석.pi-package 키워드로 묶어 npm에 발행.처음 만나면 헷갈리는 용어 정리.
--mode rpc는 stdin/stdout JSONL로 외부 프로세스에서 Pi를 제어. Node 아닌 언어에서 임베드할 때 쓴다.createAgentSession() 같은 함수로 다른 앱에 Pi를 임베드하게 해준다. openclaw가 실제 SDK 통합 사례./compact 둘 다 지원.jq·grep로 다루기 쉽고 스트리밍 친화적. Pi 세션 저장 포맷. 주의: 줄 분리는 LF(\n)만이라야 하고 줄 안에 raw LF가 들어가면 깨진다.--experimental-strip-types로 빌드 없이 .ts를 직접 실행하기 위해 강제. enum·namespace·생성자 파라미터 프로퍼티 금지.npm run check가 이걸로 lint+format 일괄 처리. Babel/ESLint 시대의 후계자 후보.devDependencies에 박아두고 매일 쓴다.package.json의 workspaces 필드로 선언. 패키지끼리 로컬 링크되어 동시 개발이 쉽다. Turborepo·Nx 없이 npm 기본 기능만으로도 가능.release.mjs가 전 패키지 버전을 한 번에 올린다. 반대는 independent versioning(Lerna 기본값).공식 문서 · 관련 레포 · 학습 자료.
npm i -g @earendil-works/pi-coding-agent, pi, /login. 자기 작은 사이드 프로젝트에 "README 다시 써줘"부터 시켜본다. Claude Code · Codex와 직접 비교해보면 차이가 즉시 보인다./skill:i18n-clean으로 호출. 같은 파일을 Anthropic Skills 폴더에 복사해서 동작 확인 → "표준의 가치"를 직접 체감.subprocess로 pi --mode rpc를 띄우고 JSONL을 주고받는 minimal client 작성. Node 아닌 언어가 코딩 에이전트를 통제하는 경험.