- Claude에게 작성하도록 요청: Claude Code 세션에서 원하는 것을 설명하세요
- 직접 작성: 튜토리얼을 따르세요 모드의 코드가 어떻게 작동하는지 배우세요. Node.js, 번들러 또는 빌드 단계가 필요하지 않습니다. Claude Code는
.js및.ts파일을 직접 로드하기 때문입니다.
모드는 Claude Code v2.1.287 이상이 필요합니다. 셸에서
claude --version을 실행하여 확인하세요. 모드가 로드될 수 있는지 확인하려면 모드가 로드될 수 있는지 확인을 참조하세요.Claude에게 모드 작성 요청
대화형 Claude Code 세션에서 원하는 모드를 설명하면 Claude가 작성합니다. Claude는plugin-authoring이라는 내장 스킬에서 작동하며, 이는 모드를 작성할 위치, 버전이 가진 이벤트 및 메서드, 모드가 로드되는 방식을 알려줍니다. Claude는 모드를 요청할 때 스킬을 로드할 수 있거나, Claude Code 프롬프트에서 /plugin-authoring을 실행하여 직접 로드할 수 있습니다.
모드는 승인하면 실행됩니다. 단, Claude가 작성한 모드가 로드될 수 없는 세션은 제외됩니다.
1
모드 설명
자신의 말로 모드를 요청하세요. 예를 들어
현재 git 브랜치를 프롬프트 위에 표시하는 모드를 만들어라고 할 수 있습니다. Claude는 세션의 모드 폴더에 있는 자신의 디렉토리에 모드를 작성합니다. 이는 ~/.claude/dev-mods/ 다음에 세션의 ID가 옵니다. 모드의 전체 경로는 ~/.claude/dev-mods/3f2a9c1e-5b7d-4e8a-9c21-6d0f4b8a7e13/git-branch/와 같습니다.default 및 acceptEdits 권한 모드에서 Claude Code는 Claude가 모드의 각 파일을 생성하기 전에 요청합니다. ~/.claude는 보호된 경로이기 때문입니다. 각 파일이 나타나면 승인하세요.2
모드 승인
Claude가 첫 번째 파일을 저장하면 Claude Code는 세션에 대해 핫 리로딩을 활성화할지 묻습니다. 핫 리로딩은 이 세션에서 Claude가 작성한 모드를 실행하고 나중에 변경 사항을 선택합니다.다음 중 하나를 선택하세요:
- 이 세션에 대해 활성화: 세션의 모드 폴더에 있는 모드는 턴이 끝날 때 로드되고, 변경 사항이 있는 각 턴의 끝에 다시 로드됩니다. 답변은 세션 동안 지속되며, 재개한 후에도 지속됩니다.
- 지금은 아님: 지금은 아무것도 로드되지 않습니다. 파일은 Claude가 작성한 위치에 남아 있으며, 모드는 해당 세션이 다음에 시작될 때 로드됩니다. 모드가 로드되지 않도록 하려면 해당 디렉토리를 삭제하세요.
3
모드가 로드되었는지 확인
Claude Code 프롬프트에서
/plugin을 실행하고 Installed 탭이 선택될 때까지 Tab을 누르세요. 모드가 나열되며, 여기서 끌 수 있습니다.4
모드 시도
요청한 것을 사용하세요. 예제 프롬프트의 경우 현재 브랜치 이름이 프롬프트 상자 위에 나타납니다. 모드가 원하는 작업을 수행하지 않으면 Claude에게 변경할 사항을 알려주세요. 모드는 파일을 변경하는 각 턴의 끝에 다시 로드되므로 Claude가 완료되는 즉시 변경 사항을 시도할 수 있습니다.
다른 세션에서 모드 사용
Claude가 작성한 모드는 모드를 만든 세션에서만 로드되며, Claude Code는cleanupPeriodDays보다 오래되면 해당 세션의 모드 폴더를 삭제합니다. 모드를 유지하려면 모드 폴더에서 디렉토리를 ~/mods/git-branch와 같은 자신의 위치로 복사하세요. 그런 다음 로드 방법을 선택하세요:
- 시작하는 세션에서: 셸에서
claude --plugin-dir ~/mods/git-branch를 실행하세요 - 다른 사람들을 위해: 마켓플레이스에 추가하여 설치할 수 있도록 하세요
Claude가 작성한 모드가 로드될 수 없는 세션
Claude가 작성한 모드는 승인 후에만 로드되며, 모드가 실행될 수 있는 신뢰할 수 있는 작업 공간에서만 로드됩니다. 이 세션에서는 로드되지 않습니다:- 승인할 사람이 없음:
claude -p실행 또는dontAsk모드와 같이 세션이 프롬프트를 표시할 수 없습니다 - 작업 공간을 신뢰하지 않음: 디렉토리에 대한 신뢰 프롬프트를 수락하지 않았습니다
- 모드가 중지됨:
--safe-mode또는--bare로 시작했거나,disableAllHooks를 설정했거나, 조직의 관리 설정이 차단했습니다
모드 직접 작성
이 튜토리얼에서는 Claude가 수행하는 도구 호출을 세고, Claude가 작동하는 동안 스피너 옆에 개수를 표시하고, 개수를 인쇄하는/tally 명령을 추가하는 first-mod라는 모드를 빌드합니다. 그런 다음 Claude Code가 모드 옆에 작성한 타입 선언을 읽고 claude plugin validate를 실행합니다. 함께 버전이 제공하는 이벤트 및 메서드와 Claude Code가 코드에서 읽는 것을 보여줍니다.
이 녹화는 완성된 모드를 보여줍니다. 스피너는 도구 호출을 세고, /tally는 개수를 인쇄하며, 코드 편집은 세션이 실행되는 동안 적용됩니다:
plugin.json: 플러그인의 매니페스트hooks.json: 코드 파일을 가리킵니다register.js: 코드, hooks 모듈이라고 불립니다
1
플러그인 디렉토리 생성
파일을 보관할 두 디렉토리를 생성하세요:
- Bash or Zsh
- PowerShell
2
매니페스트 작성
모드는 플러그인이며, 모드는 매니페스트가 필요합니다. 이 모드의 매니페스트에는 특별한 필드가 없습니다. 이를
first-mod/.claude-plugin/plugin.json으로 저장하세요:first-mod/.claude-plugin/plugin.json
3
Claude Code에 코드 위치 알리기
Claude Code가 플러그인을 로드할 때, 플러그인의
hooks/hooks.json을 읽습니다. 해당 파일의 modules 키는 코드의 경로를 제공하며, 이를 가지는 것이 플러그인을 모드로 만드는 것입니다. 한 경로를 나열하세요. hooks.json에 상대적입니다. 여기서는 다음 단계에서 작성할 register.js를 가리킵니다.이를 first-mod/hooks/hooks.json으로 저장하세요:first-mod/hooks/hooks.json
4
코드 작성
이 파일은 모드의 코드이며, hooks 모듈이라고 불립니다. 모드가 로드될 때, Claude Code는 파일이 내보내는 파일은
register 함수를 호출하고 on이라는 함수를 전달합니다. on에 대한 각 호출은 이벤트 핸들러(hook이라고 불림)를 이름이 지정한 이벤트에 등록합니다.이를 first-mod/hooks/register.js로 저장하세요:first-mod/hooks/register.js
calls에 개수를 유지하고 네 개의 hooks를 등록합니다:- **
session.start**는 세션이 시작될 때, 첫 번째 프롬프트 전에 실행되며, 모드가 다시 로드될 때마다 실행됩니다. Claude Code에/tally명령을 추가합니다. - **
tool.call**는 Claude가 도구를 사용하려고 할 때마다 실행됩니다.calls에 1을 더하고 Claude Code에 인터페이스를 다시 그리도록 요청합니다. - **
command.run**은/tally를 입력할 때 실행됩니다. 인쇄할 텍스트를 반환합니다. - **
ui.render**는 Claude Code가 스피너를 그릴 때마다 실행됩니다. 스피너의 단어 뒤에 개수를 추가합니다.
5
모드 로드
--plugin-dir 플래그로 Claude Code를 시작하세요. 이는 설치하지 않고 한 세션에 대해 플러그인 디렉토리를 로드합니다:6
모드 시도
Claude에게 몇 가지 도구 호출을 수행하는 작업을 요청하세요. 예를 들어
여기 파일을 나열하고 README를 읽어. Claude가 작동하는 동안 스피너의 단어 뒤에 증가하는 개수가 나타납니다. 예를 들어 생각 중 · 도구 호출: 2…. Claude가 완료되면 /tally를 입력하고 Enter를 누르세요. 트랜스크립트는 first-mod: Claude가 이 모드가 로드된 이후 2개의 도구 호출을 했습니다를 표시하며, 자신의 개수가 있습니다. Claude Code는 플러그인의 이름을 명령의 텍스트 앞에 놓습니다.대화형 세션 없이 명령을 확인하려면 비대화형 모드에서 실행하세요:/tally가 명령 목록에 없으면 모듈이 로드되지 않았습니다. 모드가 아무것도 하지 않는 이유 찾기를 참조하세요.7
세션이 실행되는 동안 코드 변경
세션을 열어 두세요. 트랜스크립트의 한 줄은
register.js에서 ui.render hook의 ' · tool calls: '를 ' · tools used: '로 변경하고 저장하세요. 강조된 줄이 변경되는 줄입니다:first-mod/hooks/register.js
first-mod가 다시 로드되었고 hooks를 나열하며, 다음 스피너는 새 텍스트를 사용합니다. 예를 들어 생각 중 · 사용된 도구: 1….예제 모드가 어떻게 작동하는지
on에 전달하는 각 함수는 hook이며, 이는 이벤트 핸들러입니다. Claude Code는 모든 hook에 동일한 세 개의 인수를 전달합니다:
- mods API,
$라고 이름 지어짐: 모드가 자신 외부에 도달하기 위해 호출할 수 있는 모든 메서드.$.ui및$.command와 같은 네임스페이스에 있습니다 - 이벤트,
e라고 이름 지어짐: 이벤트의 입력. 도구 호출의 이름 및 인수와 같은 일반 데이터 - 다음 핸들러,
next라고 이름 지어짐: 이벤트를 다른 모드로 전달한 다음 Claude Code의 자체 동작으로 전달하고 결과를 반환하는 함수
first-mod의 hooks는 hook이 할 수 있는 세 가지 방식으로 이벤트를 처리합니다:
- 관찰:
session.starthook은 명령을 등록하고,tool.callhook은 호출을 세고 다시 그리도록 요청합니다. 둘 다next(e)를 반환하므로 세션이 시작되고 도구가 평소대로 실행됩니다. - 답변:
command.runhook은 자신의 결과를 반환하고next를 호출하지 않습니다.on의 두 번째 인수인{ command: 'tally' }는 matcher라고 불리는 필터이므로 hook은/tally에 대해서만 실행됩니다. - 다시 쓰기:
ui.renderhook은e의 복사본과 함께next를 호출하며, 그suffix는 개수를 보유하므로 Claude Code는 단어 뒤에 텍스트가 있는 일반적인 스피너를 그립니다
--plugin-dir으로 로드된 디렉토리를 감시하고 파일이 변경될 때 hooks 모듈을 핫 리로드합니다. 각 리로드는 register를 다시 실행하므로 calls는 0으로 돌아가고 /tally는 다시 세기 시작합니다. 리로드 전체에서 값을 유지하려면 상태 유지를 참조하세요.
모드에서 계속 작업하기
모드가 로드되면 Claude가 변경하도록 할 수 있으며, 버전의 타입 정의에 대해 코드를 확인하고, Claude Code가 찾은 이벤트 및 호출을 나열하고, 테스트할 수 있습니다.Claude로 모드 변경하기
이미 가지고 있는 모드를 변경하려면--plugin-dir이 모드의 디렉토리를 가리키도록 하여 세션을 시작하세요. 그러면 Claude가 작성한 것이 동일한 세션에서 로드됩니다:
이 모드에 /tally-reset 명령을 추가하여 tally를 0으로 설정하세요. Claude는 hooks 모듈을 편집하고, claude plugin validate를 실행하고, 보고하는 것을 수정합니다. --plugin-dir으로 로드하는 디렉토리는 보호된 경로이므로 default 및 acceptEdits 모드에서 모드에 대한 Claude의 각 편집을 승인하도록 요청받습니다. 보호된 경로 테이블은 다른 권한 모드의 결과를 제공합니다.
Claude가 턴 중에 저장한 파일은 턴이 끝날 때 다시 로드되므로 Claude가 완료되는 즉시 /tally-reset을 시도할 수 있습니다.
버전의 타입 정의 가져오기
Claude Code가--plugin-dir에 전달한 디렉토리에서 모드를 로드하거나 다시 로드할 때마다, 또는 Claude가 작성한 모드일 때마다, .d.ts로 끝나는 TypeScript 선언 파일을 모드의 디렉토리 내 .claude-plugin/types/에 작성합니다. 이들은 실행 중인 Claude Code 버전의 정확한 이벤트, mods API 메서드 및 요소를 설명하므로 편집기는 hooks를 자동 완성하고 타입 확인할 수 있습니다. 선언을 온라인으로 탐색하려면 Claude Code 저장소의 mods/types/claude-code.d.ts를 읽으세요. 첫 번째 줄은 이를 작성한 버전의 이름을 지정합니다. 디렉토리는 다음 파일을 보유합니다:
모드에 자신의
tsconfig.json이 없으면 Claude Code는 생성된 것을 확장하는 모드의 루트에 하나를 추가하므로 편집기와 tsc -p ./first-mod는 추가 설정 없이 모드를 타입 확인합니다.
이벤트 및 메서드는 릴리스 간에 변경될 수 있으므로 불일치할 때 이 페이지를 포함한 모든 페이지보다 이 파일을 신뢰하세요.
claude-code/index.d.ts는 모든 mods API 메서드에 대한 주석 및 예제가 있는 빌드의 가장 완전한 참조입니다. 무언가를 찾으려면 파일에서 이름(예: 'tool.call')을 검색하세요.
Claude Code가 모드에서 읽는 것 확인하기
모드를 Claude Code가 보는 방식으로 보려면, 코드를 실행하거나 세션을 시작하지 않고claude plugin validate를 사용하세요. 매니페스트를 확인하고 Claude Code가 모드를 로드할 때 실행하는 hooks 모듈의 소스에 대해 동일한 정적 분석을 실행합니다. 셸에서 모드의 디렉토리에서 실행하세요:
first-mod의 경우 출력에는 다음 줄이 포함됩니다.
hooks: 줄은 모듈이 hook하는 이벤트를 나열하며, 각각은 중괄호에 필터가 있습니다. calls: 줄은 호출하는 모든 mods API 메서드를 나열합니다. 환경 변수를 읽거나 설정하는 모듈도 env reads: 및 env writes: 줄을 가지며, $.state를 사용하는 모듈은 state reads: 및 state writes: 줄을 가집니다.
hook하려고 한 이벤트가 첫 번째 줄에서 누락되면 Claude Code도 해당 hook을 호출하지 않습니다. 일반적인 원인은 철자가 잘못된 이벤트 이름이며, 명령은 "tool.calls" is not an event와 같은 오류로 보고합니다.
정적 분석이 모든 hook과 호출을 찾을 수 있도록 다음 규칙을 따르세요:
- 각 mods API 호출을 완전히 철자하세요:
$, 네임스페이스, 메서드. 예를 들어$.store.get('notes').$를 동일한 파일의 최상위 수준에서 선언된 함수로 전달할 수 있으며,loadNotes라는 함수의 경우calls:줄은$.store.get (via loadNotes)를 읽습니다.$를 메서드, 함수 내부에서 정의된 함수, 또는 파일의 다른 부분에서 가져온 함수로 전달하면 검증이 실패합니다.$.state가 사용하는read및update함수는 이를 취할 수 있는 가져오기입니다.$또는 네임스페이스 중 하나를 변수에 할당하거나, 구조 분해하거나, 계산된 이름으로 인덱싱하지 마세요.const ui = $.ui는$.ui is used as a value로 실패합니다. - 각
on호출에서 이벤트 이름을 문자열 리터럴로 작성하세요. 예를 들어'tool.call'. 변수 또는 이름 목록에 대한 루프는the event name passed to on() is not a string literal로 실패합니다. register내부에서on이라는 두 번째 변수 또는 매개변수를 선언하지 마세요. 검증은"on" is declared again (shadowed)로 실패합니다.- 상대 경로로 플러그인 디렉토리 내 파일에서만 가져오세요. 허용되는 유일한 베어 가져오기는 타입 및 몇 가지 도우미를 위한
claude-code입니다. - 파일의 맨 위에
import선언을 사용하세요. 예를 들어import { name } from './file.js'. 동적import()는a dynamic import(); a hooks module imports its own files with an import declaration로 실패합니다. - 모든 파일을 ES 모듈로 작성하세요.
import를 사용하고require는 사용하지 마세요. 참조는 Claude Code가 로드하는 파일 확장자를 나열합니다.
모드 테스트하기
모드에 대한 자동화된 테스트를 작성하고 세션, 로그인 또는 네트워크 없이 셸에서claude plugin test로 실행할 수 있습니다. 테스트는 hooks가 처리하는 이벤트를 발생시키고 hooks가 수행한 작업을 확인합니다.
이 테스트는 두 개의 도구 호출을 발생시키고, /tally를 실행하고, 회신이 둘 다 세는지 확인합니다. 이를 first-mod/tests/first-mod.test.ts로 저장하세요:
first-mod/tests/first-mod.test.ts
first-mod 디렉토리에서 테스트를 실행하세요:
모드 공유
모드는 플러그인이므로 매니페스트에서 버전을 지정하고 사람들은/plugin 명령으로 설치하고 업데이트합니다. 다른 사람들에게 제공하려면 마켓플레이스에 추가하세요.
그 전에 플러그인의 name을 확인하세요: claude plugin validate는 Anthropic의 자체 것처럼 보이는 이름(예: claude-로 시작하는 이름)을 실패합니다. 이벤트 및 메서드는 릴리스 간에 변경될 수 있으므로 README는 테스트한 Claude Code 버전을 말하는 곳입니다.
설치된 복사본이 아닌 --plugin-dir이 있는 디렉토리에 대해 계속 개발하세요. Claude Code는 설치된 플러그인을 버전별로 캐시하므로 버전을 올리고 다시 설치할 때까지 편집 사항이 설치된 복사본에 도달하지 않습니다.
다음 단계
- 인터페이스에 그리기: 창을 열고, 프롬프트 위에 그리고, 버튼 및 텍스트 필드 추가
- 이벤트에 반응: 도구 호출, 프롬프트 및 턴 hook
- mods API 사용: 명령 및 도구 추가, 모델 호출, 타이머에서 작업 실행
- 모드 테스트: Claude Code가 답변할 것을 스텁하고, 타이머 및 그리기 테스트
- 모드 문제 해결: 모드가 아무것도 하지 않는 이유 및 디버그 로그
- 내장 모드의 소스 읽기: 완전한 플러그인. 각각 hooks 모듈 및 테스트 포함