Mods 레퍼런스 (Mods reference)
기준일: 2026-11-03
공식 기준: Mods reference
개요
mod가 처리할 수 있는 이벤트, 호출할 수 있는 mods API 메서드, 그릴 수 있는 render site를 찾아보는 레퍼런스입니다. 항목은 Claude Code CLI와 Desktop 앱은 v2.1.290 기준, VS Code 확장은 v2.1.299 기준입니다. 각 항목은 이름과 한 줄 설명, 그리고 설명이 있는 가이드 섹션 링크로 구성됩니다.
- 완전한 레퍼런스는 Claude Code의 mods용 TypeScript 선언입니다. 모든 이벤트·메서드·요소를 예제와 함께 설명합니다.
- GitHub 사본은 설치한 버전보다 오래됐을 수 있습니다. 둘이 다르면 Claude Code가 내 버전용으로 쓰는 사본을 믿으세요.
핵심 개념
| 구분 | 내용 |
|---|---|
| 파일 | plugin.json, hooks/hooks.json, hooks module(register.js 등), 선택적으로 types/index.d.ts와 .test.ts |
| hook 함수 | on(이벤트, [matcher], hook)으로 등록. hook은 ($, e, next)를 받음 |
| 이벤트 | 도구, 프롬프트, 명령·설정, 턴, 세션, 서브에이전트, 인터페이스, 다른 mod, 텔레메트리, settings hook, mods API 호출 |
| mods API | hook이 받는 $. $.ui, $.fs, $.model 같은 namespace로 묶인 메서드 |
| render site | ui.render hook의 e.component 값. 인터페이스의 확장 지점 |
| 요소 | $.ui.resolve(e)로 얻는 트리 구성 블록(Box, Text, Button 등) |
상세
파일 (Files)
mod는 다음 파일을 가진 플러그인 디렉터리입니다.
| 파일 | 필수 | 내용 |
|---|---|---|
.claude-plugin/plugin.json |
예 | 플러그인 manifest. mod가 추가하는 필수 필드는 없음 |
hooks/hooks.json |
예 | modules: 이 파일 기준 상대 경로 하나를 담은 배열. 예: "modules": ["./register.js"]. hooks 아래에 settings hook도 둘 수 있음 |
hooks module (예: hooks/register.js) |
예 | mod의 진입점. register(on, options)를 export. 확장자는 .js, .mjs, .cjs, .jsx, .ts, .mts, .cts, .tsx. ES module |
types/index.d.ts (manifest의 types가 지정) |
$.state를 쓰거나 mods API에 namespace를 추가할 때 |
PluginState 값과 mod가 추가하는 namespace 선언 |
이름이 .test.ts 또는 .test.tsx로 끝나는 파일 |
아니요 | claude plugin test가 실행하는 테스트 |
register는 on과 options를 받습니다. options에는 manifest가 선언한 userConfig 필드 값이 기본값까지 채워져 들어옵니다.
hook 함수 (The hook function)
mod는 register 안에서 on을 호출해 hook(이벤트 핸들러)을 등록합니다. on은 이벤트 이름, 선택적 matcher(이벤트 필드에 대한 필터), hook을 받습니다.
on('tool.call', { tool: 'Bash' }, async ($, e, next) => next(e))
on은 .catch(handler) 메서드 하나를 가진 registration을 반환하며, 이것으로 hook의 오류 핸들러를 지정합니다.
| 인자 | 설명 |
|---|---|
$ |
mods API. 아래 mods API 메서드 전부. 호출은 $.fs.read('notes.md')처럼 namespace와 메서드를 모두 씀 |
e |
이벤트 입력. deeply frozen plain data. 바꾸려면 복사본을 next에 넘김 |
next(e) |
미들웨어처럼 다음 핸들러. 이후 hook들과 Claude Code의 동작을 실행하고 이벤트 결과로 resolve |
next.signal |
이벤트가 버려지면 abort되는 AbortSignal |
next.origin |
이벤트를 발생시킨 쪽의 { plugin, tier }. Claude Code 자신은 { plugin: 'engine', tier: 'core' }. mod의 tier는 mod 실행 순서의 우선순위 그룹: prepend, user, append, builtin |
next.budget |
hook의 시간 한도(ms). next.budget.ms는 전체 한도, next.budget.remainingMs는 남은 시간 |
next.to(e, tier) |
뒤쪽 tier(append, builtin, core)로 건너뜀. next.to(e, 'append')는 사용자가 설치한 mod를 건너뜀. prependPlugins 또는 appendPlugins에 있는 mod만 호출 가능 |
next.error |
.catch 핸들러 안에서만. hook이 실패하면 kind가 throw 또는 timeout, message는 오류 텍스트. 이벤트가 그 hook의 mods API 호출 안에서, 또는 hook 밖의 내 mod 코드에서 나와 hook이 건너뛰어졌으면 kind는 re-entry. re-entry는 v2.1.292 이상 필요 |
next.error.cause |
kind가 re-entry일 때만 설정. 이벤트의 원인이 된 mods API 호출을 tool.call 또는 PreToolUse hook이 바꿨거나, 그 호출이 시작한 에이전트를 agent.spawn hook이 바꿨으면 rewritten. 다른 mod가 mods API에 추가한 메서드가 그 이벤트를 발생시켰으면 lent(rewritten이 해당하면 제외). lent는 v2.1.292 이상, rewritten은 v2.1.300 이상 필요 |
next.called |
.catch 핸들러 안에서만. hook이 next를 호출했으면 true |
이벤트 (Events)
이벤트는 대상별로 묶여 있고, 각각 언제 발생하는지와 hook이 무엇을 반환할 수 있는지 나옵니다. turn.step과 process.spawn의 hook은 async generator이고, 나머지는 async function입니다.
표의 마지막 열 표기:
next(e): 이벤트를 그대로 넘김next({ ...e, text }): 지정한 필드만 바꾼 복사본을 넘김. 예:next({ ...e, text: e.text.trim() })- 객체:
next를 호출하지 않고 이벤트에 직접 답함.reason같은 단어는 직접 쓰는 문자열. 예:{ deny: 'Use the file tools.' }
도구 (Tools)
Claude가 읽는 설명부터 호출 실행 여부 결정까지, 도구 호출마다 발생합니다.
| 이벤트 | 발생 시점 | hook 반환값 |
|---|---|---|
tool.call |
도구가 곧 실행될 때 | next(e), { deny: reason }, { result } |
tool.check |
tool.call·PreToolUse hook 다음, Claude Code가 도구 호출 실행 허용 여부를 결정할 때. next(e)는 규칙·권한 모드·그 hook들이 내린 결정으로 resolve |
next(e) 또는 { decision }(allow, ask, deny, 선택적 reason) |
tool.describe |
도구마다 설명이 Claude에게 처음 전송될 때 한 번. MCP 도구는 tool search로 로드될 때 한 번 더 발생하며, 이때 e.description은 로드된 도구에 대해 Claude가 읽는 텍스트 |
{ description }. 선택적으로 isDeferred를 true(tool search 뒤로) 또는 false(처음부터 로드) |
tool.check의 에이전트·조직 필드
e.agentId: 서브에이전트 또는 in-process teammate가 호출하면 설정, 메인 대화가 호출하면 없음e.ceiling: 조직이ask로 설정한 connector 도구에 대해ask. 그 설정이 Claude Code에 도달하는 세션에서만e.agentId와e.ceiling은 v2.1.290 이상 필요
tool.check의 e.isReadOnly 필드
- 도구가 이 호출을 read-only라고 보고하면
true. 그 외에는false가 아니라 필드가 없음 - 값은 도구 자체의 보고이므로, 이 필드만으로 호출을 승인하기 전에 Check whether a tool call is read-only를 읽으세요
- v2.1.304 이상 필요
프롬프트와 Claude가 읽는 텍스트 (Prompts and what Claude reads)
사용자가 입력하는 텍스트와, 시스템 프롬프트·리마인더처럼 Claude Code가 스스로 Claude에게 보내는 텍스트를 다룹니다.
| 이벤트 | 발생 시점 | hook 반환값 |
|---|---|---|
prompt.submit |
프롬프트가 제출될 때 | next({ ...e, text }), next({ ...e, context }), { drop: reason } |
prompt.fill, prompt.suggest |
텍스트가 프롬프트 상자에 초안으로, 또는 흐린 제안으로 들어가려 할 때 | 텍스트를 바꾼 next(e) |
prompt.edit |
사용자가 프롬프트 상자를 편집할 때 | next(e) |
prompt.autocomplete |
사용자가 프롬프트 상자에 입력하다 커서 위치에서 단어가 끝날 때. e.token이 그 단어. Claude Code는 hook을 기다리지 않고 자체 자동완성 행을 먼저 표시 |
{ suggestions }: Claude Code 행 아래에 표시할 { text, label, description } 목록. 행을 고르면 그 text가 단어를 덮어씀 |
prompt.compose |
Claude Code가 시스템 프롬프트를 렌더링할 때 | { sections }: 전송 순서대로 { id, text, scope } 목록 |
prompt.section |
시스템 프롬프트의 이름 있는 섹션마다 한 번. e.name은 prompt.compose의 섹션 id |
{ text }, 섹션을 빼려면 { text: null } |
prompt.context |
대화마다 한 번, 첫 메시지와 함께 보내는 컨텍스트에 대해 | { blocks } |
prompt.attachment |
Claude Code가 리마인더 같은 자체 메시지를 Claude용으로 추가할 때. e.type이 종류, types가 선언한 종류는 e.detail에 텍스트의 근거 사실이 들어 있음 |
{ text }, 빼려면 { text: null } |
prompt.mention |
프롬프트가 @-mention한 파일을 Claude Code가 읽으려 할 때. v2.1.290 이상 필요 | 다른 파일을 읽게 하려면 next({ ...e, path }), 또는 { deny: reason } |
skill.prompt |
스킬 텍스트가 Claude용으로 펼쳐질 때 | { text } |
attribution.text |
Claude Code가 커밋 또는 PR attribution 텍스트를 구성할 때 | { text } |
skill.prompt의 source·frontmatter 필드
e.skill(스킬 이름), e.text(Claude가 읽는 텍스트)와 함께 다음 필드를 읽을 수 있습니다.
| 필드 | 타입 | 내용 |
|---|---|---|
e.source |
string | 스킬 제공자. enterprise·개인·프로젝트 위치의 스킬은 각각 policySettings, userSettings, projectSettings. 그 외 출처는 plugin, mcp, syncedSkills, built-in 같은 단어 |
e.pluginName |
string | e.source가 plugin인 스킬의 플러그인 이름 |
e.path |
string | 스킬 SKILL.md의 절대 경로, command 파일로 쓴 스킬이면 그 .md 파일 경로. 내장 스킬처럼 이 머신에 파일이 없으면 없음 |
e.frontmatter |
object | 스킬 파일의 frontmatter (plain data) |
e.frontmatterProblem |
string | e.frontmatter에 frontmatter나 일부 키가 빠진 이유. 예: is a list or a single value, not a table. 전체가 들어 있거나 frontmatter가 없으면 없음 |
- hook은 바꾼
text또는frontmatter를next에 넘길 수 있습니다. 뒤의 hook은 둘 다 읽고, Claude는 최종text를 읽습니다. - 다른 필드를 바꾸는 hook은 실패합니다.
- 이 다섯 필드는 v2.1.299 이상 필요합니다.
명령과 설정 (Commands and configuration)
명령이 실행되거나 목록에 나올 때, /config 행이 표시되거나 바뀔 때 발생합니다.
| 이벤트 | 발생 시점 | hook 반환값 |
|---|---|---|
command.run |
명령이 곧 실행될 때 | { text }, {}, next(e) |
command.describe |
명령 목록용으로 명령마다 한 번 | { description, argumentHint, isHidden } |
config.set |
/config 행이 바뀌려 할 때 |
next({ ...e, value }) 또는 { deny: reason } |
config.describe |
/config 행마다 한 번 |
{ label, description, isHidden } |
settings.read |
mod가 $.settings.read를 호출할 때, 또는 Claude Code가 세션의 병합된 settings를 만들 때. Claude Code 자체 읽기와 e.layers는 v2.1.304 이상 필요 |
next(e), { value }, { deny: reason } |
settings.read의 e.layers와 e.source
e.layers: settings를 담고 있는 사용 중인 출처마다{ source, settings }객체 하나. 우선순위가 낮은 것부터. What asettings.readhook receives 참고e.source: mod가 요청한 출처 하나. 예:$.settings.read({ source: 'policy' }). Claude Code 자체 읽기와 병합된 settings 읽기에서는 없음
턴 (Turns)
모델에 보내는 각 요청을 포함해 하나의 답변을 처음부터 끝까지 따라갑니다.
| 이벤트 | 발생 시점 | hook 반환값 |
|---|---|---|
turn.start |
턴이 시작될 때 | next(e) |
turn.step |
요청 하나가 모델로 가려 할 때 | yield* next(e), 또는 next({ ...e, model }), next({ ...e, effort }) |
turn.complete |
턴이 끝났을 때 | next(e), 또는 답변 아래 한 줄을 표시하는 { text } |
세션 (Session)
세션 시작·종료·compaction, 다른 세션과의 메시지 교환을 표시합니다.
| 이벤트 | 발생 시점 | hook 반환값 |
|---|---|---|
session.start |
로드된 mod마다 첫 프롬프트 전에 한 번, 그 mod가 reload된 뒤 다시 한 번. /clear, /resume, /branch 뒤에는 발생하지 않음 |
next(e) |
session.end |
세션이 끝나거나 /clear, /resume, /branch가 실행될 때. e.reason은 clear, resume, logout, prompt_input_exit, other. /branch는 resume으로 보고 |
next(e) |
session.compact |
대화가 곧 compact될 때 | { skip: reason } |
session.receive, session.send |
다른 에이전트·세션에서 메시지가 도착할 때, 또는 보내려 할 때. Send and receive messages between sessions 참고 | receive는 { consumed: reason }, send는 { isDelivered: false, reason } |
session.append |
대화가 보관하는 행(프롬프트, 응답 블록, 도구 결과, 알림 등)마다 저장 전에 한 번 | message.content를 바꾼 next({ ...e, message }). 행의 text 블록이나 그 안 tool_result 블록의 content를 다시 씀 |
session.attach, session.detach |
다른 앱이 세션에 연결·연결 해제될 때 | next(e) |
session.measure |
턴마다, 그리고 플랜 한도의 사용률(%)이 바뀔 때 | next(e) |
서브에이전트 (Subagents)
서브에이전트 유형이 Claude에게 제공될 때, 서브에이전트나 agent-team teammate가 시작하려 할 때 발생합니다.
| 이벤트 | 발생 시점 | hook 반환값 |
|---|---|---|
agent.offer |
서브에이전트 유형이 Claude에게 제공될 때 | 숨기려면 { isOffered: false } |
agent.spawn |
서브에이전트 또는 agent team teammate가 시작하려 할 때. teammate면 e.isTeammate가 true |
모델을 고르려면 next({ ...e, model }), 또는 { deny: reason } |
Claude가 SendMessage 도구로 서브에이전트를 재개하면 agent.spawn hook은 다시 실행되지 않습니다. 서브에이전트를 재개하는 SendMessage 호출을 거부하려면 tool.call hook에서 그 도구를 matcher로 지정하세요.
인터페이스 (Interface)
Claude Code가 render site를 그릴 때, 사용자가 mod가 그린 컨트롤을 쓸 때 발생합니다. ui.render hook이 반환하는 것은 Draw in the interface에 나옵니다.
| 이벤트 | 발생 시점 |
|---|---|
ui.render |
render site가 곧 그려질 때 |
ui.resolve |
mod가 로드될 때, 앱·render site·mod 조합마다 한 번. 결과는 $.ui.resolve(e)가 읽는 요소 테이블 |
ui.press, ui.input, ui.select |
mod가 그린 Button, Input, Select가 사용될 때 |
ui.focus, ui.scroll |
pane이나 band의 포커스된 컨트롤 또는 스크롤 위치가 바뀌려 할 때 |
ui.close |
pane이 닫히려 할 때. e.id는 pane, e.origin.kind는 plugin, person, unload |
ui.message |
Client 요소가 자기 mod에 데이터를 post할 때 |
ui.fault |
내 mod가 그린 Client 요소가 로드·그리기·실행에 실패할 때. e.phase는 load, render, run, e.reason은 오류 메시지. v2.1.289 이상 필요 |
다른 mod (Other mods)
다른 mod가 로드될 때 거부하거나 그 mod가 받는 mods API를 바꿀 수 있습니다.
| 이벤트 | 발생 시점 | hook 반환값 |
|---|---|---|
plugin.register |
hooks module이 곧 로드될 때. e.uses에 그 module의 이벤트, mods API 호출, 환경 변수, state가 claude plugin validate 출력 형태로 들어 있음. 호출은 $. 없이 fs.read처럼 씀 |
{ refuse: reason } |
engine.create |
이 mod용 mods API가 만들어질 때 | namespace를 추가한 mods API. user tier 밖의 mod는 namespace를 뺄 수도 있음 |
다른 mod의 hook이 내가 engine.create에서 추가한 namespace의 메서드를 호출하면, 그 이벤트의 모든 hook이 반환할 때까지 내 메서드의 $ 호출은 그 hook의 컨텍스트에서 실행됩니다. 예를 들어 상대 경로는 그 hook의 작업 디렉터리 기준으로 풀리고, 턴이 그 hook을 기다리는 동안 $.prompt.submit은 reject됩니다. 그 이후 메서드가 하는 호출은 내 mod 자신의 컨텍스트에서 실행됩니다.
텔레메트리 (Telemetry)
Claude Code가 기록하는 사용 레코드에 대해 발생합니다.
| 이벤트 | 발생 시점 | hook 반환값 |
|---|---|---|
telemetry.log, telemetry.mark |
텔레메트리 레코드가 곧 기록되거나 기능 사용 1회가 표시될 때 | next(e) 또는 { deny: reason } |
- 설치하는 mod에서는 텔레메트리 hook에
{ to: 'collector' }필터를 줘야 합니다. 예:on('telemetry.log', { to: 'collector' }, hook). 필터가 없으면claude plugin validate에서 실패합니다. *는 이 이벤트들과 매치되지 않습니다.
settings hook 이벤트 (Settings hook events)
각 settings hook 이벤트는 classic.Stop, classic.PostToolUse처럼 classic.<Event>라는 이벤트입니다. e는 그 hook의 stdin JSON입니다.
mods API 호출 (Mods API calls)
모든 mods API 메서드는 fs.read, model.complete, ui.open처럼 namespace와 메서드 이름을 딴 이벤트이기도 합니다. 여기에 건 hook은 자기보다 뒤에 실행되는 mod의 호출을 가로채며, next(e), { deny: reason }, { value }를 반환할 수 있습니다.
mods API 메서드 (Mods API methods)
mods API는 모든 hook이 받는 $ 인자입니다. 메서드는 $.ui 같은 namespace로 묶입니다. 표의 $.ui 행에 있는 open은 $.ui.open(...) 호출입니다. 가이드는 자주 쓰는 것을 보여 주고, 내 빌드의 types는 모든 메서드를 예제와 함께 문서화합니다.
| Namespace | 메서드 |
|---|---|
$.plugin |
name, root: 이 플러그인의 이름과 디렉터리 |
$.ui |
resolve, invalidate, open, close, panes, focus, scroll, toast, notify, status, log, notice, ask, copy, selection, blit |
$.command |
register, run, list |
$.tool |
register, call, check, list |
$.agent |
register, spawn, list. list()는 이 세션의 서브에이전트와 teammate를 반환하며 각각 status가 pending, running, waiting, idle, completed, failed, killed 중 하나. idle과 waiting은 v2.1.289 이상 필요 |
$.model |
complete, fork, classify |
$.prompt |
submit, read, fill, suggest, compose. submit({ text })의 텍스트는 내 mod를 발신자로 밝히는 문장 뒤에 Claude가 읽음. submit({ text, asUser: true })는 그 문장 없이 사용자 자신의 말로 보냄 |
$.turn |
abort |
$.session |
messages, cwd, root, model, turns, id, repo, surfaces, usage, version, compact, send, append, authorize. usage()는 { startedAt, context, rateLimits, cost } 반환. context는 tokens, window, percent, rateLimits는 { kind, percentUsed, resetsAt } 목록 |
$.config |
list, set |
$.settings |
read |
$.env |
get, set |
$.fs |
read, write, list, exists, stat, ancestors. write는 atomic이 아님: 파일 내용을 제자리에서 바꾸므로 다른 프로세스가 덜 쓴 파일을 읽을 수 있음. 여러 세션이 바꾸는 데이터는 $.store에 둘 것 |
$.store |
get, set, delete, keys. 머신의 모든 세션이 공유하는 key-value 저장소. Save from more than one session 참고 |
$.state |
반응형 state: get, set. 헬퍼 atom, read, update, derive, memberOf는 claude-code에서 import |
$.clock |
now, sleep, after, every |
$.http |
fetch |
$.process |
run, spawn |
$.mcp |
call, connect. connect(server)는 내 플러그인 manifest에 있는 MCP 서버를 연결 |
$.audio |
play, speak |
$.telemetry |
log, mark. 레코드는 Claude Code나 내장 mod가 호출했을 때만 전송 |
render site (Render sites)
render site는 Claude Code 인터페이스의 확장 지점입니다. 각 행은 ui.render hook의 e.component 값이며, e.props 필드와 렌더링하는 앱이 함께 나옵니다. e.surface는 그리고 있는 앱(terminal, desktop, vscode 등)입니다. site에서 hook이 할 수 있는 일은 Change what Claude Code already draws에 예제와 함께 나옵니다.
- VS Code 확장에서 렌더링하려면 확장 버전 2.1.299 이상이 필요합니다.
- feature flag를 가져오지 않는 세션은 2.1.304 이상이 필요합니다.
- 확장이 다르게 그리는 부분은 Draw in the VS Code extension에 있습니다.
| Site | e.props |
e.requestId |
렌더링 앱 |
|---|---|---|---|
Pane |
title, isFocused, bodyColumns, placement, scroll, view |
pane의 id |
Terminal, Desktop, VS Code |
AbovePrompt |
hasSurvey, isWorking, maxRows, bodyColumns, scroll, view |
인스턴스 하나 | Terminal, Desktop |
UserMessage |
text, origin, isExpanded, origin에 따라 task 또는 from |
메시지 id | Terminal, Desktop, VS Code |
AssistantMessage |
응답 텍스트 | 메시지 id | Terminal, Desktop, VS Code |
ToolUse, ToolResult, ToolGroup |
도구 이름, 입력, 결과 | 도구 호출 id | Terminal, Desktop, VS Code |
CommandOutput |
command, text |
메시지 id | Terminal, Desktop |
AskUserQuestion |
질문과 선택지 | 도구 호출 id | Terminal, Desktop, VS Code |
ToolProgress |
kind |
도구 호출 id | Terminal |
Spinner |
word, message, suffix, mode |
에이전트 id | Terminal, Desktop, VS Code |
TurnDuration |
word, durationMs |
메시지 id | Terminal |
InfoNotice |
text, command |
메시지 id | Terminal |
SessionMode |
modes |
인스턴스 하나 | Terminal, Desktop |
PromptHint |
isDraft, isWorking, hint |
인스턴스 하나 | Terminal, Desktop |
e.viewport는 columns, rows, isFullscreen을 가집니다. 터미널과 Desktop 앱에서는 앱이 창 크기를 측정하기 전까지 없고, rows는 내 pane이 아니라 창 전체 높이입니다. VS Code 확장에서는 항상 있습니다.
트리를 site에 맞추려면 hook에서 다음 props를 읽습니다.
Pane또는 band의 너비:e.props.bodyColumns에 맞춰 그림- transcript 옆
Pane의 높이:e.props.placement가'dock'이면e.props.scroll.bodyRows가 트리에 쓸 수 있는 행 수 - 프롬프트 위
Pane의 높이:e.props.placement가'inline'이면 pane이 트리에 맞춰 한도까지 커지고bodyRows가 그 한도. 다른 한도를 요청하려면$.ui.open의rows필드 참고
pane보다 큰 트리는 통째로 스크롤됩니다.
요소 (Elements)
요소는 ui.render hook이 반환하는 트리의 구성 블록이며 $.ui.resolve(e)로 얻습니다. 자주 쓰는 요소와 터미널에서의 모양은 Build a tree from elements에, 대부분의 스크린샷은 interface gallery에 있습니다. ✓는 그 앱이 요소를 그릴 수 있다는 뜻입니다.
| 요소 | 주요 props | Terminal | Desktop | VS Code |
|---|---|---|---|---|
Box |
key, flex layout, gap·padding·margin(아래 spacing 단계), width, height, minWidth, minHeight, borderStyle(아래 border 스타일), borderColor, borderDimColor, backgroundColor, position, top, left, right, bottom, overflow, display, hover |
✓ | ✓ | ✓ |
Text |
color, backgroundColor, bold, italic, underline, strikethrough, dimColor, inverse, wrap, size·weight·mono·tabular(아래 typography), hover |
✓ | ✓ | ✓ |
Button |
key, label, onPress, hotkey, plain, dimColor, autoFocus, action, hover |
✓ | ✓ | ✓ |
Link |
href, label. 한도 표 참고 |
✓ | ✓ | ✓ |
Code |
source, language, path, startLine, format, wrap |
✓ | ✓ | ✓ |
Markdown |
text, key, dimColor, onLinkPress, pressableLinks |
✓ | ✓ | ✓ |
Input |
key, label, placeholder, value, submitLabel, onSubmit, onInput, autoFocus |
✓ | ✓ | ✓ |
Select |
key, label, options, value, onSelect, autoFocus |
✓ | ✓ | ✓ |
Svg |
최대 131,072자의 SVG markup source, alt 텍스트, width, height, isInteractive |
✓ | ✓ | |
Client |
module, key, props, width, height, flexGrow |
✓ | ✓ | |
Raster |
key, 최대 512의 columns, 최대 256의 rows, cells. Draw a grid of colored cells 참고 |
✓ | ||
Image |
key, PNG·RGBA 바이트(최대 2 MiB) 또는 파일 경로인 source, 최대 255의 columns·rows, alt 텍스트. 어떤 터미널이 그리는지 참고 |
✓ |
Button 추가 규칙:
action: Claude Code 자체 keybinding action 하나를 지정. 그 action에 대한 사용자 바인딩이 chord나 modifier 키 조합이면 그 바인딩이 버튼을 누름- band의 숫자 hotkey: band에 있는 버튼의 숫자
hotkey는 사용자가 빈 프롬프트에 그 숫자만 입력하고 잠시 멈춰도 동작 - 접힌 band: band가 접혀 있는 동안은
action바인딩도 hotkey도 그 안의 버튼을 누르지 않음 - 같은 hotkey의 버튼 두 개: 한 그림에서 두 버튼이 같은
hotkey를 지정하면 뒤의 버튼이 가져감
autoFocus는 어떤 컨트롤에서든 true만 받으므로, 끄려면 prop을 생략하세요.
VS Code 확장은 일부 props를 무시하고 그 prop이 없는 것처럼 요소를 그립니다.
Box:position과top·left·right·bottom,alignSelf,borderDimColor,hoverText:size,mono,tabular,hoverButton:hotkey,plain,autoFocus,action,hover. 그래서 버튼은 클릭하거나, 포커스가 있을 때 Enter로 누름Code:language,path,startLine,format,wrap. 그래서 색이나 줄 번호 없이 그려지고,format: 'diff'블록은 diff 원문을 보여 줌Input,Select:autoFocusSvg:isInteractive
Box border 스타일
Box에 테두리를 그리려면 borderStyle을 borderStyle: 'round'처럼 다음 이름 중 하나로 설정합니다.
borderStyle |
터미널이 그리는 모양 | 위쪽 테두리 |
|---|---|---|
'single' |
얇은 선, 각진 모서리 | ┌──┐ |
'double' |
이중선 | ╔══╗ |
'round' |
얇은 선, 둥근 모서리 | ╭──╮ |
'bold' |
굵은 선 | ┏━━┓ |
'singleDouble' |
위아래 얇은 선, 좌우 이중선 | ╓──╖ |
'doubleSingle' |
위아래 이중선, 좌우 얇은 선 | ╒══╕ |
'classic' |
ASCII 문자 +, -, | |
+--+ |
'arrow' |
Box 안쪽을 가리키는 화살표 |
↘↓↓↙ |
'dashed' |
점선, 모서리는 빈칸 | ╌╌ |
'quote' |
왼쪽에 막대 ▎, 나머지 세 면은 빈 셀 |
빈칸 |
'rounded'처럼 다른 이름을 지정한 Box는 테두리 없이 그려집니다.
Box spacing 단계
Box spacing props는 gap, columnGap, rowGap, padding, margin, 그리고 paddingX, marginTop 같은 한쪽·한 축 형태입니다. 각각 gap: 1처럼 터미널 셀 수나 gap: 'md'처럼 단계 이름을 받습니다. 터미널과 VS Code 확장에서 각 단계의 셀 수는 다음과 같습니다.
| 단계 | 가로 셀 | 세로 셀 |
|---|---|---|
'xs' |
1 | 0 |
'sm' |
1 | 0 |
'md' |
2 | 1 |
'lg' |
3 | 1 |
'xl' |
4 | 2 |
gap,padding,margin을 단계로 지정하면 가로·세로에 동시에 적용됩니다. 예: 터미널과 VS Code 확장에서padding: 'md'는 좌우 각 2셀, 위아래 각 1행입니다.- 단계 이름은 v2.1.299 이상 필요합니다. 그 이전 릴리스에서는 단계 이름을 쓴 트리 대신 Claude Code가 site의 자체 버전을 그립니다.
Text typography props
Text에 size, weight, mono, tabular를 설정하면 트리를 그리는 앱에 글자 크기, 굵기, 고정폭 서체, 같은 폭 숫자를 요청합니다. 의존하기 전에 터미널과 VS Code 확장의 처리를 확인하세요. 앱이 prop을 무시해도 트리는 그 prop이 없는 것처럼 그려집니다.
| Prop | 값 | 터미널 | VS Code 확장 |
|---|---|---|---|
size |
'caption', 'footnote', 'body', 'heading', 'title' |
무시 (글자 크기가 하나뿐) | 무시 |
weight |
'regular', 'medium', 'semibold', 'bold' |
semibold, bold는 굵게 |
semibold, bold는 굵게 |
mono |
앱의 고정폭 서체 요청 시 true |
무시 (항상 고정폭) | 무시, 확장 자체 서체 유지 |
tabular |
제자리에서 바뀌는 숫자나 숫자 열이 정렬되도록 같은 폭 숫자 요청 시 true |
무시 (숫자가 이미 한 셀 폭) | 무시 |
이 네 props는 v2.1.299 이상 필요합니다. 그 이전 릴리스에서는 이를 설정한 트리 대신 Claude Code가 site의 자체 버전을 그립니다.
bold를 weight로 교체
Text의bold는 deprecated이며weight로 대체되었지만 여전히 동작합니다.weight가 없는Text에서bold: true를weight: 'semibold'로 바꾸면 v2.1.299 이상에서 같은 결과가 나옵니다.- v2.1.299 이전 릴리스에서는
weight를 설정한 트리가 그려지지 않고 Claude Code가 site의 자체 버전을 그립니다. bold와weight를 둘 다 설정하면bold는 효과가 없습니다.
한도 (Limits)
hook과 mods API 호출은 시간·크기 한도 아래에서 실행됩니다. 시간 한도를 넘긴 hook은 Claude Code가 건너뜁니다. 중첩·요소 수·Raster 셀·Image 바이트 한도를 넘는 트리는 그려지지 않습니다.
| 한도 | 값 |
|---|---|
이벤트 하나에 대한 hook 자체 실행 시간 (next 안의 시간과 $.clock.sleep 외 mods API 호출 안의 시간은 제외) |
10초, prompt.edit hook은 50밀리초 |
.catch 핸들러 실행 시간 |
1초 |
모든 session.end hook 합계 |
SessionEnd hook budget만큼. 바꾸지 않으면 1.5초이며, settings의 SessionEnd hook이 끝난 시점부터 셈 |
$.process.run timeout |
기본 30초, 최대 10분 |
$.process.run stdout, stderr |
각각 4 MiB. 잘리면 isStdoutTruncated 또는 isStderrTruncated가 true |
$.model.complete maxTokens |
기본 1024, 최대 64,000 또는 모델의 출력 한도 |
$.fs.read, $.fs.write |
파일 하나당 4 MiB |
$.http.fetch 요청 body |
4 MiB(문자 수 기준). 더 크면 호출이 reject |
$.http.fetch 응답 body |
4 MiB. text에 처음 4 MiB만 담기고 나머지는 읽지 않음. Content-Length 헤더가 더 큰 값을 선언하면 대신 호출이 reject되고 reason은 is over the 4194304-byte limit로 끝남. 단, redirect 후 마지막 요청이 HEAD 메서드면 예외. HEAD 예외는 v2.1.296 이상 필요 |
$.http.fetch 호출 하나 (redirect·body 포함) |
30초 |
$.http.fetch 호출 하나가 따르는 redirect 수 |
5 |
hook의 drop reason 또는 config.set deny reason |
4,096자. 더 긴 reason은 끝이 잘리고 drop·deny는 그대로 적용. 자르기는 v2.1.292 이상이며, 이전 버전에서는 hook이 실패 |
| 트리 하나의 텍스트 | 처음 100,000자만 그림 |
Code의 language·path, Select option의 value, Client의 module |
10,000자. 더 길면 그것을 반환한 ui.render hook이 실패 |
Link의 href |
2,048자. 더 길면 그것을 반환한 ui.render hook이 실패 |
| 트리 하나의 중첩 깊이 | 루트 요소 아래 32단계 |
| 트리 하나의 요소와 텍스트 자식 수 | 20,000 |
트리 하나의 Raster 셀 수 (각 Raster의 columns × rows) |
262,144 |
트리 하나의 모든 Image PNG·RGBA 바이트 |
2 MiB |
$.store |
JSON 합계 4 MiB |
$.session.messages() |
최신 4,096개 항목 |
$.ui.invalidate('ui.render') 다시 그리기 |
초당 10회로 throttle. 터미널에서 보이는 pane, 펼친 band, 프롬프트 아래 hint 줄은 초당 30회. 그보다 빠른 호출은 합쳐짐 |
$.ui.toast |
{ timeoutMs }를 넘기지 않으면 4초 표시. classic renderer에서는 mod의 새 toast가 표시 중이거나 대기 중인 이전 toast를 대신할 수 있음 |
| 사용자가 요청하지 않았는데 열린 pane | 터미널 144열부터 배치, 사용자가 한 번 연 뒤에는 110열 |
| mods API 호출 인자의 중첩 깊이 | 28,000단계. 넘으면 호출이 nesting deeper than 28000 levels is not supported로 끝나는 메시지와 함께 reject. v2.1.299 이상 필요 |
next에 넘기는 바뀐 이벤트의 중첩 깊이 (turn.step 같은 async generator hook 제외) |
28,000단계. 넘으면 next가 nesting deeper than 28000 levels is not supported로 끝나는 메시지와 함께 reject. v2.1.299 이상 필요 |
hook 반환값의 중첩 깊이 (ui.render, ui.resolve, async generator hook 제외) |
28,000단계. 넘으면 hook 결과가 거부되고, 이를 알리는 notice에 nesting deeper than 28000 levels is not supported가 포함됨. v2.1.299 이상 필요 |
| hooks module 파일 하나 안에서 서로 중첩된 scope(함수, 블록, 루프 등) | 2,000 |
| 명령, 도구, 서브에이전트 유형, pane 이름 | 영문자, 숫자, _, -, 최대 64자 |
claude plugin test 테스트 하나 |
테스트가 timeoutMs를 설정하지 않으면 5초 |
설정과 환경 변수 (Settings and environment variables)
mod에 영향을 주는 설정과 환경 변수입니다. "읽는 곳" 열은 어느 settings 파일이나 환경에서 읽는지를 나타냅니다.
| 이름 | 읽는 곳 | 동작 |
|---|---|---|
CLAUDE_CODE_PLUGIN_DIRS |
환경 변수, 또는 ~/.claude/settings.json의 env |
플래그를 넘길 수 없는 앱에서 --plugin-dir처럼 로드할 플러그인 디렉터리. 절대 경로를 :(Windows는 ;)로 구분 |
CLAUDE_CODE_PLUGIN_DIR_WATCH |
환경 변수 | 1이면 장시간 실행되는 non-interactive 세션이 저장 시 --plugin-dir mod를 reload |
prependPlugins, appendPlugins |
managed settings. managed settings가 없는 머신에서, credential이 Team·Enterprise /login이 아닌 세션에서만 user settings |
acme-guard@acme-tools 같은 플러그인 id 목록. prependPlugins의 mod는 사용자가 설치한 모든 mod보다 먼저, appendPlugins는 뒤에, 나열 순서대로 실행. The order mods run in 참고 |
allowManagedModsOnly |
managed settings, 내장 guard의 옵션으로 | 조직의 mod로 인정되는 mod와 Claude Code 내장 mod만 hook을 실행. 사용자의 settings hook은 계속 실행 |
allowModsToOverrideDenyRules |
managed settings, 내장 guard의 옵션으로 | 사용자가 설치한 mod가 deny 규칙이 거부하는 도구 호출을 승인할 수 있게 함 |
allowManagedHooksOnly |
managed settings | 조직의 것이 아닌 hook과 설치된 mod를 차단. 계속 실행되는 것 참고 |
disableAllHooks |
모든 settings 파일 | managed settings에 있으면 설치된 플러그인의 mod·hook은 하나도 실행되지 않음. 내 settings에 있으면 조직이 관리하는 것은 계속 실행. disableAllHooks 참고 |
disableSideloadFlags |
managed settings | 시작 시 --plugin-dir, --plugin-url을 거부 |
pluginConfigs |
user 또는 managed settings | mod의 userConfig 값. 키는 플러그인 id(acme-guard@acme-tools)이거나, --plugin-dir로 로드한 mod는 이름과 @inline(first-mod@inline) |
sec-default@builtin은 Claude Code에 내장된 guard이며 /plugin과 debug log에는 cc-plugin-sec-default로 나옵니다.
- managed settings가 있는 머신, 또는 credential이 Team·Enterprise
/login인 세션에서 사람이 설치한 모든 mod보다 먼저 로드됩니다. - managed
prependPlugins가 설정돼 있으면 그 목록이 guard를 지정할 때만, 지정된 위치에서 로드됩니다. - 소스는 Claude Code 저장소의
mods/sec-default디렉터리에 있습니다.
명령 (Commands)
mod를 로드·검사·테스트하는 명령과 플래그입니다. claude 명령은 셸에서, / 명령은 Claude Code 프롬프트에서 실행합니다. <directory>는 claude plugin validate ./first-mod처럼 입력하는 경로이고, 대괄호는 선택 인자입니다.
| 명령 | 동작 |
|---|---|
/plugin |
내장이 아닌 mod가 로드되면 탭 아래에 1 mod active · first-mod 같은 줄을 표시 |
claude plugin validate <directory> |
플러그인 manifest와 hooks module을 읽고 오류, 처리하는 이벤트, 하는 mods API 호출을 보고. --strict는 경고를 오류로 취급, --json은 기계가 읽을 수 있는 보고서 출력 |
claude plugin test [directory] |
디렉터리(생략 시 현재 디렉터리) 아래에서 이름이 .test.ts 또는 .test.tsx로 끝나는 파일을 모두 실행. 테스트가 실패하면 상태 코드 1로 종료 |
claude --plugin-dir <directory> |
플러그인 디렉터리를 한 세션 동안 로드하고 저장 시 hooks module을 reload. 여러 개를 로드하려면 플래그를 반복 |
/reload-plugins |
실행 시 플러그인을 reload |
체크리스트
-
plugin.json,hooks/hooks.json의modules, hooks module(register(on, options)export)을 갖췄다. -
$.state를 쓰거나 namespace를 추가한다면 manifest의types로types/index.d.ts를 지정했다. - 쓰려는 이벤트·필드·props가 요구하는 버전(예: v2.1.290, v2.1.299, v2.1.304)을 확인했다.
- 텔레메트리 hook에
{ to: 'collector' }필터를 줬다. - 그리려는 render site와 요소가 대상 앱(Terminal, Desktop, VS Code)에서 지원되는지 표로 확인했다.
- hook 실행 시간(10초,
prompt.edit50ms),$.fs·$.http.fetch4 MiB 같은 한도 안에서 동작한다. - 여러 세션이 바꾸는 데이터는
$.fs.write대신$.store에 둔다. -
claude plugin validate로 이벤트와 mods API 호출을 확인했다.
다음 단계
- mod 만들기에서 첫 mod를 작성하고 내 빌드의 types를 받습니다.
- mod 테스트에서 이 레퍼런스의 이벤트 결과를 stub으로 씁니다.
- mod 문제 해결에서 mod가 동작하지 않는 원인을 찾습니다.
- mods 관리에서
prependPlugins, 내장 guard 옵션 등 조직 설정을 봅니다.
기준일
이 문서는 2026-11-03에 공식 Mods reference 페이지를 기준으로 작성했습니다. 이벤트·메서드·요소의 최신 정의는 설치한 버전의 TypeScript 선언을 함께 확인하세요.