오늘도 공부
Pi(pi) 확장 만들기 — pi-subagents 스타일 포함 본문
@mariozechner/pi-coding-agent가 제공하는 pi CLI는 확장(extensions) 으로 동작을 바꿀 수 있습니다. 서드파티 패키지 pi-subagents 도 “npm 패키지 + package.json의 pi 메타데이터 + ExtensionAPI” 조합으로 구현된 확장입니다.
이 문서는 확장이 무엇인지, 파일·패키지 구조, pi-subagents가 하는 방식, SDK에 끼워 넣는 방법까지 한 번에 정리합니다.
공식 세부 스펙은 upstream pi-mono 의 extensions.md · packages.md 를 함께 보세요.
1. 확장이란 무엇인가
- TypeScript 모듈 하나(또는 디렉터리의 index.ts)가 기본 내보내기(default export) 로 함수를 내보냅니다.
- 그 함수는 ExtensionAPI (pi 객체)를 인자로 받습니다.
- 그 안에서 다음을 할 수 있습니다(대표적).
- pi.registerTool(...) — LLM이 호출할 커스텀 도구
- pi.on("이벤트이름", handler) — 세션/도구/에이전트 라이프사이클 가로채기
- pi.registerCommand("슬래시명", ...) — /mycommand 같은 TUI 커맨드
- ctx.ui — 확인창, 입력, 알림, 커스텀 TUI 위젯 등
- 로더는 jiti 로 TS를 그대로 읽으므로, 별도 tsc 빌드 없이 동작하는 것이 일반적입니다(패키지로 배포할 때도 마찬가지로 TS 소스를 넣는 경우가 많음).
중요: 확장은 Node.js 환경에서 사용자 권한으로 실행됩니다. 임의 코드 실행과 같으므로 신뢰하는 소스만 설치하세요.
2. 확장을 두는 위치 (로컬 개발·배포)
2.1 전역 (~/.pi/agent/extensions/)
경로의미
| ~/.pi/agent/extensions/my-ext.ts | 단일 파일 확장 |
| ~/.pi/agent/extensions/my-ext/index.ts | 디렉터리 + 진입점 |
프로젝트에 상관없이 pi를 켤 때 자동 탐색됩니다. /reload 로 핫 리로드되는 것은 이 자동 탐색 경로에 둔 확장이 대상입니다(문서 기준).
2.2 프로젝트 로컬 (.pi/extensions/)
저장소마다 다른 확장을 쓰고 싶을 때:
- .pi/extensions/*.ts
- .pi/extensions/*/index.ts
2.3 한 번만 시험: --extension / -e
pi -e ./path/to/extension.ts
pi -e ./path/to/extension-dir
임시로만 로드해 빠르게 테스트할 때 유용합니다.
2.4 settings.json에 경로 추가
~/.pi/agent/settings.json 또는 프로젝트 .pi/settings.json의 extensions 배열에 절대/상대 경로를 넣을 수 있습니다. (공식 extensions.md 표 참고.)
3. npm 패키지로 배포하기 (pi-subagents 방식)
로컬 폴더만 쓰지 않고 npm에 올려서 pi install npm:패키지 로 쓰려면 Pi 패키지 규칙을 따릅니다.
3.1 package.json의 pi 필드
pi-subagents의 실제 예:
{
"name": "pi-subagents",
"type": "module",
"keywords": ["pi-package", "pi", "pi-coding-agent"],
"pi": {
"extensions": [
"./index.ts",
"./notify.ts"
]
}
}
- keywords에 pi-package 를 넣으면 생태계에서 “Pi 패키지”로 인식하기 쉽습니다.
- pi.extensions 배열에 확장 진입 파일(보통 .ts)을 나열합니다. 여러 파일 = 여러 확장 모듈이 순서대로 로드될 수 있습니다(한 패키지에 부트스트랩 + 보조 모듈 패턴).
3.2 패키지 안에 두는 것들
- 필수: package.json, 확장 진입 TS(들)
- 선택: agents/*.md, prompts/*.md, skills 등 리소스 — 패키지 구조와 로더 규칙은 packages.md 및 각 리소스 타입 문서 참고
- 의존성: dependencies / devDependencies에 @mariozechner/pi-coding-agent, @mariozechner/pi-agent-core 등 — peer 버전을 맞추는 것이 중요합니다(특히 메이저가 어긋나면 확장 로드 실패).
3.3 설치·실행
pi install npm:pi-subagents
# 또는 버전 고정
pi install npm:pi-subagents@0.11.12
프로젝트만 쓰려면 -l 로 프로젝트 settings에 기록하는 방식이 문서화되어 있습니다.
4. 최소 확장 뼈대 (단일 파일)
~/.pi/agent/extensions/hello-pi.ts 예시:
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
import { Type } from "@sinclair/typebox";
export default function (pi: ExtensionAPI) {
pi.on("session_start", async (_event, ctx) => {
ctx.ui.notify("hello-pi 확장이 로드되었습니다.", "info");
});
pi.registerTool({
name: "greet",
label: "Greet",
description: "이름으로 인사합니다.",
parameters: Type.Object({
name: Type.String({ description: "이름" }),
}),
async execute(toolCallId, params, _signal, _onUpdate, _ctx) {
return {
content: [{ type: "text", text: `안녕하세요, ${params.name}님` }],
details: {},
};
},
});
}
실행:
pi -e ~/.pi/agent/extensions/hello-pi.ts
도구 스키마는 @sinclair/typebox 가 일반적입니다(공식 예제와 동일).
5. ExtensionAPI로 할 수 있는 일 (요약)
공식 문서 목차와 대응해 요약합니다. 전체 API·이벤트 목록은 반드시 packages/coding-agent/docs/extensions.md 원문을 보세요.
영역설명
| pi.registerTool | LLM 도구 등록 (parameters는 Typebox 등) |
| pi.on(...) | session_start, tool_call, 에이전트/세션 이벤트 등 — 반환으로 도구 차단(block) 가능 |
| pi.registerCommand | /command 형태 TUI 커맨드 |
| ctx.ui | confirm, input, notify, 커스텀 위젯 등 |
| 상태/세션 | pi.appendEntry 등 세션 로그 연동(문서: State Management) |
모드: 인터랙티브 TUI vs print/JSON vs RPC 등에서 동작 차이가 있을 수 있어, 공식 Mode Behavior 절을 참고하세요.
6. pi-subagents는 구조적으로 어떻게 다른가 (참고 아키텍처)
pi-subagents는 “작은 예제”가 아니라 실제 제품 수준 확장입니다.
특징설명
| 다중 진입점 | pi.extensions에 index.ts, notify.ts 등 복수 엔트리 |
| 도구 | subagent 등 고유 도구 + 스키마·실행기·비동기 잡 추적 |
| 에이전트 정의 | 패키지 agents/*.md + 프로젝트 .pi/agents/*.md 탐색 |
| 자식 pi 프로세스 | 서브에이전트 실행 시 pi CLI를 spawn — 브라우저가 아니라 Node/터미널 환경이 필요 |
| TUI | Slash 커맨드, 위젯, 브리지 모듈 등 pi-tui 사용 |
새 확장을 큰 규모로 만들 때는 디렉터리 + 여러 모듈 + index.ts만 export default 패턴을 따르고, 부가 기능은 tools.ts, bridge.ts 등으로 쪼개면 됩니다.
7. SDK 앱에 확장 경로 넣기 (DefaultResourceLoader)
pi CLI가 아니라 createAgentSession 등 SDK로 임베드할 때는, 로컬 폴더나 node_modules/패키지명 을 additionalExtensionPaths 로 넘깁니다.
이 저장소의 my-agent/packages/cli 는 대략 다음 패턴입니다.
- node_modules/pi-subagents 절대 경로를 구한다.
- new DefaultResourceLoader({ ..., additionalExtensionPaths: [piSubagentsRoot] })
- await resourceLoader.reload()
- createAgentSession({ ..., resourceLoader, tools: createCodingTools(cwd), ... })
이렇게 하면 npm으로 설치한 pi-subagents의 package.json → pi.extensions 에 적힌 엔트리들이 로드됩니다.
자세한 단계는 subagents-my-agent.md 참고.
8. 디버깅·주의사항
- 버전 정렬: @mariozechner/pi-coding-agent / pi-agent-core / pi-ai 와 확장 패키지의 peer 요구 범위를 맞추세요.
- 권한: 확장은 사용자 권한으로 파일·네트워크·프로세스에 접근할 수 있습니다.
- 브라우저: pi-web-ui만으로는 pi 자식 프로세스나 확장 전체를 그대로 돌리기 어렵습니다. 확장·서브에이전트는 CLI/SDK(Node) 전제가 맞습니다.
- 공식 예제: pi-mono/packages/coding-agent/examples/extensions/ 에 권한 게이트, 이벤트 버스, RPC 데모 등이 있습니다.
9. 관련 링크
자료URL / 경로
| 공식 Extensions 문서 | pi-mono docs/extensions.md |
| Pi Packages | pi-mono docs/packages.md |
| 예제 확장 모음 | pi-mono/packages/coding-agent/examples/extensions/ |
| pi-subagents | GitHub: nicobailon/pi-subagents |
| 이 저장소: my-agent + subagents | subagents-my-agent.md |
10. 체크리스트 (새 npm 확장 패키지를 만들 때)
- [ ] package.json: "type": "module", keywords에 pi-package 권장
- [ ] package.json: "pi": { "extensions": ["./index.ts", ...] }
- [ ] 기본 내보내기: export default function (pi: ExtensionAPI) { ... }
- [ ] 도구 파라미터: Typebox 등 공식과 동일한 패턴
- [ ] peerDependencies 또는 README에 호환 pi-coding-agent 버전 명시
- [ ] 로컬 테스트: pi -e ./index.ts → 이후 pi install npm:./path 또는 npm publish 후 pi install npm:@scope/pkg
이 순서를 따르면 pi-subagents와 같은 방식으로 확장을 나누고 배포할 수 있습니다.
'AI' 카테고리의 다른 글
| Audio Diffusion PyTorch: 오디오 디퓨전 (0) | 2026.04.02 |
|---|---|
| EmDash: WordPress의 전제를 다시 쓰는 CMS (0) | 2026.04.02 |
| Apple 은 바이브 코딩 앱을 차단중이다. (0) | 2026.04.01 |
| See-through: AI로 2D이미지->Live2D(2.5D) 이미지로 (0) | 2026.04.01 |
| Sherlock: 사용자명 하나로 SNS 모든 계정 AI로 추적 (0) | 2026.03.31 |
