Skip to content

핵심 큐브에 퍼즐 조각처럼 모듈이 끼워지는 확장 개념 이미지

확장(extension)은 Pi의 동작을 확장하는 TypeScript 모듈입니다. 라이프사이클 이벤트를 구독하고, LLM이 호출할 수 있는 커스텀 도구를 등록하고, 명령을 추가하는 등의 일을 합니다. Pi는 "확장은 Pi가 직접 만들 수 있다"고 안내합니다 — 사용 사례에 맞는 확장을 Pi에게 직접 시켜도 됩니다.

확장은 Pi 프로세스 안에서, 같은 OS 권한으로 실행됩니다. 프롬프트, 도구 호출, 파일, 자격 증명, 세션 기록을 들여다볼 수 있으므로 신뢰할 수 있는 출처의 것만 로드해야 합니다.

빠른 시작 ​

~/.pi/agent/extensions/my-extension.ts를 만듭니다.

typescript
import { type ExtensionAPI, isToolCallEventType } from "@earendil-works/pi-coding-agent";
import { Type } from "typebox";

export default function (pi: ExtensionAPI) {
  // 이벤트 수신
  pi.on("session_start", async (_event, ctx) => {
    ctx.ui.notify("Extension loaded!", "info");
  });

  // 도구 호출 가로채기: 위험 명령 확인
  pi.on("tool_call", async (event, ctx) => {
    if (isToolCallEventType("bash", event) && event.input.command.includes("rm -rf")) {
      const ok = await ctx.ui.confirm("Dangerous!", "Allow rm -rf?");
      if (!ok) return { block: true, reason: "Blocked by user" };
    }
  });

  // 커스텀 도구 등록
  pi.registerTool({
    name: "greet",
    label: "Greet",
    description: "Greet someone by name",
    parameters: Type.Object({
      name: Type.String({ description: "Name to greet" }),
    }),
    async execute(toolCallId, params, signal, onUpdate, ctx) {
      return {
        content: [{ type: "text", text: `Hello, ${params.name}!` }],
        details: {},
      };
    },
  });

  // 명령 등록
  pi.registerCommand("hello", {
    description: "Say hello",
    handler: async (args, ctx) => {
      ctx.ui.notify(`Hello ${args || "world"}!`, "info");
    },
  });
}

-e 플래그로 빠르게 시험할 수 있습니다. 정식 배치는 자동 탐색 위치, 즉 전역은 ~/.pi/agent/extensions/, 프로젝트는 .pi/extensions/에 두고 /reload로 핫 리로드하는 방식입니다.

bash
pi -e ./my-extension.ts

확장으로 할 수 있는 것 ​

공식 문서가 나열하는 주요 능력입니다.

능력설명
커스텀 도구pi.registerTool()로 LLM이 호출하는 도구 등록
이벤트 가로채기도구 호출 차단·수정, 컨텍스트 주입, 압축 커스터마이징
사용자 상호작용ctx.ui의 select·confirm·input·notify
커스텀 UIctx.ui.custom()으로 키보드 입력을 받는 TUI 컴포넌트
커스텀 명령pi.registerCommand()로 /mycommand 등록
세션 영속 상태pi.appendEntry()로 재시작을 버티는 상태 저장
커스텀 렌더링도구 호출·결과·메시지의 터미널 표시 제어
제공자·MCP모델 제공자, 가상 모델, MCP 서버 등록

문서가 제시하는 활용 예시도 눈여겨볼 만합니다: rm -rf 같은 위험 명령 사전 확인(권한 게이트), 턴마다 stash하는 git 체크포인트, .env·node_modules/ 쓰기 차단(경로 보호), 나만의 방식의 대화 요약 압축, 질문 마법사·다이얼로그 같은 대화형 도구, todo 리스트처럼 상태를 기억하는 도구, 파일 watcher·웹훅 연동, 심지어 기다리는 동안 하는 게임(snake 예시)까지 있습니다.

저장소의 예제 확장 ​

레포의 packages/coding-agent/examples/extensions/에는 동작하는 구현체가 모여 있습니다. 일부만 옮겨 보면:

예제내용
permission-gate.ts도구 호출 확인 게이트
protected-paths.ts특정 경로 쓰기 차단
git-checkpoint.ts턴별 git 체크포인트
auto-commit-on-exit.ts종료 시 자동 커밋
custom-footer.ts, custom-header.ts커스텀 헤더·푸터 UI
custom-compaction.ts커스텀 압축
dynamic-tools.ts동적 도구 로딩
file-trigger.ts파일 변경 트리거
project-trust.ts프로젝트 신뢰 판정 처리
confirm-destructive.ts파괴적 작업 확인
custom-provider-anthropic/커스텀 제공자 구현

예제들은 라이프사이클 이벤트 핸들러, 커스텀 도구, 명령과 단축키, 커스텀 UI, git 연동, 시스템 프롬프트 수정, 외부 연동, 커스텀 제공자 등 주요 주제를 망라합니다.

어디에 두고 어떻게 로드하나 ​

위치범위
~/.pi/agent/extensions/사용자 전역
.pi/extensions/프로젝트(신뢰 허용 후 로드)
settings의 extensions 배열, Pi 패키지설정으로 지정
pi -e ./path.ts한 번의 실행(신속한 시험용)

설정이나 -e로 지정한 확장도 /reload로 다시 읽힙니다. 확장 내부에서 사용할 수 있는 import(@earendil-works/pi-coding-agent의 타입과 헬퍼, typebox 등)와 이벤트 라이프사이클, ExtensionContext와 ExtensionAPI의 전체 메서드, 도구 노출 제어, 에러 처리, 모드별 동작 차이는 공식 Extensions 문서가 레퍼런스입니다. Pi에게 확장 작성을 시킬 때는 이 문서 경로를 함께 알려 주면 좋습니다.

오픈소스를 한국어로 읽고 배웁니다.