Claude Code mods 시작하기: 설치 전 validate 점검과 첫 mod 만들기
Claude Code mods는 샌드박스 없이 내 권한으로 도는 JS/TS 플러그인입니다. 2.1.287 이상에서 기본으로 켜지니 설치 전 validate의 calls 줄과 소스를 확인하세요.
목차

Claude Code mod(모드)는 Claude Code가 자기 프로세스 안에서 직접 호출하는 JavaScript·TypeScript 함수를 담은 플러그인입니다. 프롬프트가 모델로 가기 전에 고치고, 도구 호출을 막거나 다시 쓰고, 스피너나 도구 호출 행 같은 화면 요소를 바꾸고, 트랜스크립트 옆에 버튼 달린 창을 띄울 수 있습니다. Anthropic의 Claude Code mods 발표 글은 2026년 10월 1일에 나왔고, 터미널 Claude Code 2.1.287 이상(데스크톱 앱에 내장된 Claude Code는 2.1.286 이상)에서는 따로 켜지 않아도 기본으로 동작합니다.
설치 전에 기억할 점은 하나입니다. mod는 샌드박스 없이 내 계정 권한으로 실행되므로 파일, 프로그램 실행, 네트워크, API 키에 Claude Code와 같은 수준으로 접근합니다. 남이 만든 mod는 claude plugin validate로 어떤 기능을 부르는지 먼저 보고, $.process.run이나 $.fs.read처럼 범위가 넓은 호출이 보이면 소스까지 연 다음 설치하는 순서가 안전합니다.
아래 명령 출력은 2026년 10월 6일 macOS에서 Claude Desktop 앱에 포함된 Claude Code 2.1.288 CLI로 실행한 결과입니다. CLI는 로그인하지 않은 상태였고, 로그인 없이 되는 명령만 실행했습니다. 튜토리얼 mod의 validate·test·claude -p "/tally", 빈 디렉터리에서 mod 로드 가능 여부 점검, Anthropic 샘플 mod 3개의 validate와 소스 확인, 샘플 마켓플레이스 추가부터 설치·비활성화·삭제까지, 일부러 망가뜨린 파일의 오류 메시지가 그 범위입니다. 대화형 세션은 열지 않았으므로 창이나 띠가 실제로 그려지는 모습, 핫 리로드, /plugin의 mods active 줄, Claude가 mod를 써 줄 때 뜨는 승인 창은 보지 못했습니다. 데스크톱 앱 Code 탭, VS Code, Windows, Team·Enterprise용 내장 가드, 커뮤니티 mod도 실행하지 않았고, 이 부분의 설명은 공식 문서 내용입니다.
Claude Code mod란? 설정 훅·스킬·MCP로 안 되는 일
mod는 이벤트가 생길 때 Claude Code가 호출하는 함수 묶음입니다. 도구 호출, 프롬프트 제출, 화면 일부를 그리는 순간 같은 이벤트마다 함수가 실행되고, 그 함수는 이벤트를 지켜보기만 하거나, 내용을 바꿔서 넘기거나, Claude Code 대신 직접 답할 수 있습니다. Claude Code 공식 문서의 Mods 개요는 settings.json에 적는 기존 훅을 "설정 훅", mod 안의 이벤트 핸들러를 "훅"이라고 나눠 부르며, 아래에서도 같은 뜻으로 씁니다. 이름만 같을 뿐 마인크래프트 같은 게임 mod와는 관계가 없고, claudemod.com도 Anthropic과 무관한 설정 모음 사이트입니다.
설정 훅, 스킬, 상태줄(statusline), MCP 서버는 Claude Code 바깥에서 스크립트를 실행하거나 Claude에게 텍스트와 도구를 건네는 방식입니다. mod는 안에서 실행되기 때문에 다음 일을 할 수 있습니다.
- 트랜스크립트 옆 창이나 프롬프트 위 띠 영역에 탭, 버튼, 텍스트 필드를 그립니다.
- 도구 호출 행, 스피너, Claude가 질문할 때 뜨는 대화 상자처럼 Claude Code가 원래 그리는 부분을 바꿉니다.
- 도구 호출을 잠시 붙잡아 두거나, 도구를 실행하지 않고 대신 답하거나, 특정 요청을 다른 모델로 보냅니다.
- Claude 턴 없이 바로 실행되는
/명령을 만듭니다. Claude가 작업하는 중에도 실행됩니다. - 같은 파일 안의 훅끼리 변수를 공유합니다. 한 훅이 도구 호출 수를 세고 다른 훅이 그 수를 스피너 옆에 표시하는 식입니다.
그래서 아이디어가 떠올랐을 때 먼저 물어볼 것은 "이게 화면을 그리거나 이벤트를 안에서 바꿔야 하는 일인가"입니다.
| 하려는 일 | 먼저 쓸 것 |
|---|---|
| 이미 있는 스크립트로 도구 호출을 막거나 허용하고 기록하기 | 설정 훅 |
| 모델, 비용, git 브랜치 같은 정보를 화면 아래 한 줄로 보기 | 상태줄 스크립트 |
| 매번 같은 지침을 채팅에 붙여 넣는 일 줄이기 | 스킬 |
| Claude가 데이터베이스나 이슈 트래커 같은 외부 시스템에 접근하기 | MCP 서버 |
| 버튼과 입력칸이 있는 창, 스피너·도구 호출 행 변경, 턴 없이 도는 명령, 도구 실행 대신 직접 답하기 | mod |
설정 훅은 폐지되지 않았고 mod와 나란히 계속 동작합니다. 플러그인 하나에 mod, 스킬, MCP 서버를 함께 담아 배포할 수도 있습니다. 설정 훅·스킬·슬래시 명령어 사이에서 고르는 문제는 Claude Code Hooks·Skills·슬래시 명령어 차이와 사용 예제에서, 한 줄 표시면 충분한 경우는 Claude Code Statusline 설정: 경로, 필드, 스크립트, 문제 해결에서 다룹니다. 어떤 스킬과 MCP부터 넣을지는 Claude Code에서 먼저 써야 할 Skills와 Claude Code에서 먼저 추가할 MCP를 참고하세요.
내 환경에서 mod가 도는지: 버전 2.1.287과 화면별 지원
터미널에서는 claude --version으로 버전을 확인합니다. 2.1.287보다 낮으면 업데이트가 먼저입니다. 설치와 업데이트 방법은 Claude Code 설치 방법: 전 플랫폼 완벽 설정 가이드에 정리되어 있습니다. 데스크톱 앱은 자체 Claude Code를 내장하고 있어서, Code 탭의 로컬 세션에서 /status를 입력해 Claude Code 행이 2.1.286 이상인지 봅니다.
얼리 액세스 때 CLAUDE_CODE_ENABLE_FUNCTION_HOOKS를 설정해 두었다면 지워도 됩니다. 2.1.287부터는 이 값을 무시하므로 0으로 두어도 mod가 꺼지지 않습니다.
버전이 맞아도 그리기까지 되는지는 Claude Code를 어디서 실행하느냐에 따라 다릅니다. 훅은 플러그인을 로드하는 거의 모든 곳에서 실행되지만, 창이나 띠가 화면에 나타나는 곳은 터미널과 데스크톱 앱뿐입니다.
| 실행 위치 | 훅 실행 | mod가 그린 화면 |
|---|---|---|
터미널의 claude (에디터 통합 터미널, JetBrains 플러그인 포함) | 예 | 예 |
| 데스크톱 앱 Code 탭 (WSL 세션 제외) | 예 | 예, 터미널 전용 요소는 제외 |
| 데스크톱 앱의 WSL 세션 | 아니요, 플러그인 미지원 | 아니요 |
| VS Code 확장 프로그램의 채팅 패널 | 예 | 아니요 |
claude -p, Agent SDK | 예 | 아니요 |
| claude.ai·모바일 앱의 Remote Control | 예, 내 컴퓨터의 세션에서 | 내 컴퓨터의 터미널에 표시 |
| 클라우드 세션 | 플러그인이 클라우드 세션에 전달될 때만 | 아니요 |
VS Code 채팅 패널에서 쓰는 사람이라면 도구 호출을 고치거나 막는 mod는 의미가 있지만, 창을 그리는 mod는 아무것도 보이지 않습니다. 같은 mod를 쓰려면 VS Code 통합 터미널에서 claude를 실행하면 됩니다.
조직 설정까지 포함해 mod가 로드될 수 있는 상태인지는, mod가 없는 빈 디렉터리에서 claude plugin test를 실행하면 세션 없이 알 수 있습니다.
mkdir empty-check
cd empty-check
claude plugin test2.1.288에서는 다음처럼 나오고 종료 코드는 0이었습니다.
claude plugin test: .../empty: no hooks module to load; there is no hooks/hooks.json naming one in "modules"메시지에 따라 의미가 다릅니다.
| 메시지에 포함된 문구 | 뜻 |
|---|---|
no hooks module to load | mod를 로드할 수 있음. 이 디렉터리에 테스트할 mod가 없을 뿐 |
hooks modules are turned off here | 내 설정의 disableAllHooks나 조직 정책이 mod를 막고 있음 |
hooks modules are turned off in this process | Anthropic이 설치된 mod를 원격으로 끈 상태. 내 컴퓨터 설정으로는 다시 켤 수 없음 |
조직이 allowManagedModsOnly로 조직 mod만 허용한 경우는 이 점검에 나타나지 않습니다. 회사 계정이라면 첫 메시지가 나와도 내가 설치한 mod가 로드되지 않을 수 있고, 그 이유는 디버그 로그에 남습니다.
남이 만든 mod 설치 전 점검: validate의 calls 줄과 소스
mod 코드는 파일을 읽고 쓰거나 프로그램을 실행하거나 네트워크에 접근하려면 반드시 mods API(코드에서 $)를 거쳐야 합니다. 그래서 실행하지 않고도 무엇을 부르는지 목록으로 뽑을 수 있습니다. 플러그인 파일을 클론 등으로 받은 뒤 셸에서 실행합니다.
claude plugin validate ./some-modvalidate는 Claude Code가 mod를 로드할 때 쓰는 것과 같은 정적 분석을 코드를 실행하지 않고 돌립니다. 출력의 hooks: 줄은 mod가 받는 이벤트(중괄호 안은 필터), calls: 줄은 mod가 부르는 mods API 메서드입니다. Claude Code는 이 분석으로 읽을 수 없는 방식으로 API를 쓰는 mod는 아예 로드하지 않으므로, calls: 줄에 없는 API 호출이 몰래 실행되지는 않습니다.
calls: 줄에서 볼 항목은 다음과 같습니다.
| 호출 | 의미 |
|---|---|
$.fs.read, $.fs.write | 내 계정이 접근할 수 있는 모든 위치의 파일을 읽고 씀 |
$.process.run, $.process.spawn | 내 권한으로 프로그램을 실행함 |
$.http.fetch | 네트워크 요청을 보냄 |
$.env.get, $.settings.read | API 키가 들어 있을 수 있는 환경 변수와 설정을 읽음. 출력의 env reads: 줄에 변수 이름이 나옴 |
$.env.set | 이후 Claude Code가 실행하는 명령과 MCP 서버의 환경 변수를 바꿈. env writes: 줄에 나옴 |
$.mcp.call | 연결된 MCP 서버의 도구를 호출함 |
$.model.complete | 내 플랜이나 API 키로 모델을 호출해 사용량을 씀 |
$.prompt.submit | 내가 입력한 것처럼 프롬프트를 보낼 수 있음 |
$.session.send | 다른 세션이나 서브에이전트의 Claude에게 메시지를 보냄 |
hooks: 줄에서는 tool.call과 prompt.submit(모든 도구 호출과 프롬프트를 보고 바꿀 수 있음), session.append(대화 기록이 저장되기 전에 고칠 수 있음), ui.render{component=AskUserQuestion}(Claude의 질문 대화 상자를 다시 그림), tool.check(권한 확인 창이 뜨기 전에 승인·거부)를 눈여겨봅니다.
Anthropic 샘플 mod 3개의 실제 validate 출력
Anthropic이 anthropics/claude-code-playground 저장소의 샘플 mod 폴더에 공개한 샘플 3개(2026년 10월 1일 커밋 569c5283 기준)를 2.1.288로 검사한 결과입니다. 세 개 모두 ✔ Validation passed였습니다.
$ claude plugin validate claude-code/mods/token-weather
❯ ./token-weather.mjs hooks: session.start, turn.complete, ui.render{component=AbovePrompt}
❯ ./token-weather.mjs calls: $.session.usage (via takeReading), $.ui.invalidate (via takeReading), $.ui.resolve
$ claude plugin validate claude-code/mods/blast-radius
❯ ./blast-radius.mjs hooks: tool.call{tool=Bash}, ui.render{component=Pane}, ui.render{component=AbovePrompt}
❯ ./blast-radius.mjs calls: $.clock.now, $.process.run, $.session.cwd, $.ui.close, $.ui.invalidate, $.ui.open, $.ui.resolve, $.ui.toast
$ claude plugin validate claude-code/mods/replay-theater
❯ ./replay-theater.mjs hooks: session.start, command.run{command=replay}, tool.call, turn.start, turn.complete, ui.render{component=AbovePrompt}, ui.render{component=Pane}, ui.close
❯ ./replay-theater.mjs calls: $.clock.sleep (via openReplay), $.command.register, $.fs.exists (via stepsFor), $.fs.read (via stepsFor), $.session.cwd (via stepsFor), $.ui.close (via replayView), $.ui.invalidate, $.ui.open (via openReplay), $.ui.resolve읽는 법은 이렇습니다. 프롬프트 위에 컨텍스트 사용량 예보를 그리는 token-weather는 세션 사용량을 읽고 화면을 그리는 호출뿐이라 접근 범위가 좁습니다. 지난 턴의 파일 편집을 되짚는 replay-theater는 $.fs.read로 파일을 읽습니다. 셋 다 $.http.fetch, $.env.get, $.model.complete는 부르지 않습니다.
blast-radius는 $.process.run이 있어서 validate만으로는 "프로그램을 실행한다"까지만 알 수 있습니다. 소스(hooks/blast-radius.mjs)를 열어 보면 실제로 실행하는 것은 두 종류입니다. 하나는 Proceed/Cancel 버튼을 기다리는 동안 도는 sleep 반복이고, 소스 주석에 따르면 훅 자체 실행 시간은 10초로 제한되지만 $ 호출 안에서 보내는 시간은 여기에 들어가지 않아서 이렇게 기다립니다. 다른 하나는 cd 대상을 확인하고 rm이 지울 파일 수와 용량을 미리 세는 bash -c 스크립트 두 개입니다. 붙잡는 명령은 -r/-f가 붙은 rm, git reset --hard, git push --force(-f, --force-with-lease, +ref 포함), alembic upgrade, rails db:migrate, prisma migrate, manage.py migrate입니다.
$.process.run으로 실행된 프로그램은 그 자체로 네트워크에 접근할 수 있고, 이것은 $.http.fetch처럼 calls: 줄에 따로 드러나지 않습니다. 그래서 validate는 어떤 능력을 쓰는지 알려 주고, 어떤 프로그램을 돌리는지는 소스를 봐야 압니다.
소스까지 열어 볼 기준
설치 여부는 다음 순서로 정하면 됩니다.
- 작성자와 마켓플레이스를 신뢰할 수 있는지 봅니다. Anthropic 샘플 저장소도 샘플을 지원 없이 있는 그대로 공유합니다.
claude plugin validate가 통과하는지,hooks:·calls:줄이 mod 설명과 맞는지 봅니다. 스피너를 바꾸는 mod가$.http.fetch를 부른다면 설명과 어긋납니다.$.process.run/$.process.spawn이 있으면 소스에서 실행하는 프로그램 이름과 인자를 찾습니다.$.fs.read/$.fs.write가 있으면 어떤 경로를 다루는지 찾습니다.$.env.get·$.settings.read처럼 비밀을 읽는 호출과$.http.fetch·$.process.run이 함께 있으면, 읽은 값이 어디로 나가는지 소스에서 따라가 봅니다.tool.check훅이 있으면 어떤 호출을 승인하는지 확인합니다. 다음 절의 권한 우선순위와 직접 관련이 있습니다.$.model.complete가 있으면 내 사용량을 쓰는 mod라는 점을 알고 설치합니다.

mod가 권한 확인을 대신 승인할 때: ask·deny 규칙과 내장 가드
tool.check 훅을 가진 mod는 권한 확인 창이 뜨기 전에 도구 호출을 허용하거나 거부할 수 있습니다. 문제는 이 승인이 어떤 규칙보다 앞서느냐입니다. 공식 관리자 문서 기준으로 정리하면 다음과 같습니다.
| 상황 | mod가 할 수 있는 일 |
|---|---|
ask 규칙이면 확인 창이 떴을 호출 | 먼저 승인할 수 있음. 확인 창 없이 실행됨 |
관리형이 아닌 PreToolUse 설정 훅이 막은 호출 | 승인할 수 있음 |
| auto mode에서 mod가 승인한 호출 | 분류기 검사 없이 실행됨 |
deny 규칙이 거부하는 호출, 내장 가드가 로드된 경우 | 승인할 수 없음. 관리자가 allowModsToOverrideDenyRules를 켠 경우는 예외 |
관리형 설정의 PreToolUse 훅이 막은 호출 | 차단이 최종 |
mod 자신의 $.fs·$.process 호출 | deny 규칙이 적용되지 않음 |
| 샌드박스를 켠 경우 | Claude의 Bash 명령만 격리됨. mod가 실행한 프로세스는 샌드박스 밖에서 실행 |
| 권한 확인 창 자체 | mod가 바꿀 수 없음 |
deny 규칙을 지켜 주는 것은 cc-plugin-sec-default라는 내장 가드입니다. 이 가드는 사용자가 설치한 mod보다 먼저 로드되지만, 다음 둘 중 하나일 때만 로드됩니다.
- 기기에 관리형 설정(managed settings)이 있음
- Team 또는 Enterprise 플랜으로 Claude Code에 로그인함
API 키, Amazon Bedrock, Google Cloud Agent Platform, Microsoft Foundry로 인증하는 경우는 관리형 설정이 있는 기기에서만 가드를 받습니다. 이 두 조건을 그대로 읽으면, 관리형 설정이 없는 개인 기기에서 Pro나 Max로 로그인한 경우에는 가드가 로드되지 않고, deny 규칙이 mod의 승인보다 앞선다는 보장도 문서에 나오지 않습니다. 이것은 문서 조건에서 끌어낸 해석이며, 개인 계정으로 실제 동작을 시험한 결과는 아닙니다.
가드가 있어도 빈틈은 남습니다. Read(.env)를 deny로 막아 두었더라도 mod는 $.fs.read로 .env를 읽거나 그 파일을 읽는 프로그램을 실행할 수 있습니다. 조직의 네트워크 정책은 $.http.fetch에는 적용되지만 $.process.run으로 실행한 프로그램에는 적용되지 않습니다. 결국 deny 규칙과 샌드박스는 Claude의 도구 호출을 제한하는 장치이고, mod를 제한하는 장치는 "설치하지 않거나, 설치 전에 읽어 보는 것"입니다.

권한 모드 자체가 궁금하다면 Claude Code Auto Mode: 어떻게 작동하고, 무엇을 막고, 언제 써야 하나와 Claude Code --dangerously-skip-permissions: 기능, 금지선, 더 안전한 대안을 보세요.
샘플 mod 써 보기와 설치·비활성화·삭제 명령
설치 없이 한 세션만: --plugin-dir
가장 가벼운 방법은 설치하지 않고 한 세션에만 mod 디렉터리를 로드하는 것입니다.
git clone https://github.com/anthropics/claude-code-playground
cd claude-code-playground/claude-code/mods
claude plugin validate ./token-weather
claude --plugin-dir ./token-weather--plugin-dir는 여러 번 붙여 여러 mod를 함께 로드할 수 있고, 저장할 때마다 훅 모듈을 핫 리로드합니다. 플래그를 넘길 수 없는 앱에서는 CLAUDE_CODE_PLUGIN_DIRS 환경 변수로 같은 일을 합니다. 마지막 줄은 대화형 세션을 여는 명령이라 2.1.288 실행 기록에는 들어 있지 않고, 프롬프트 위에 예보가 그려지는지는 직접 확인해야 합니다.
계속 쓰려면 마켓플레이스로 설치
mod는 플러그인이므로 마켓플레이스를 통해 설치합니다. 클론한 claude-code/mods 폴더를 마켓플레이스로 추가하고 token-weather를 설치한 뒤 끄고 지우는 과정을, 실제 설정을 건드리지 않도록 별도 설정 디렉터리에서 실행한 출력입니다.
$ claude plugin marketplace add ./
✔ Successfully added marketplace: claude-code-playground-mods (declared in user settings)
$ claude plugin install token-weather@claude-code-playground-mods --scope user
✔ Successfully installed plugin: token-weather@claude-code-playground-mods (scope: user)
$ claude plugin list
Installed plugins:
❯ token-weather@claude-code-playground-mods
Version: 0.1.0
Scope: user
Status: ✔ enabled
$ claude plugin disable token-weather@claude-code-playground-mods
✔ Successfully disabled plugin: token-weather (scope: user)
$ claude plugin uninstall token-weather@claude-code-playground-mods
✔ Successfully uninstalled plugin: token-weather (scope: user)몇 가지 알아 둘 점이 있습니다.
- 로컬 클론을 마켓플레이스로 추가하면 마켓플레이스가 그 폴더를 가리킵니다. 클론을 옮기거나 지우면 mod가 더 이상 로드되지 않습니다.
- 마켓플레이스 소스로는 GitHub의
owner/repo(뒤에#ref가능), 임의의 git URL,./나../로 시작하는 로컬 경로, 호스팅된 marketplace.json URL을 쓸 수 있습니다. - 설치 범위 기본값은 user이고,
--scope project나--scope local로 바꿀 수 있습니다. - 세션 안에서는
/plugin install <플러그인>@<마켓플레이스>로 설치합니다. 세션이 열린 채로 셸에서 설치했다면 그 세션에서/reload-plugins를 실행해야 바로 로드되고, 아니면 다음 실행 때 로드됩니다. - 세션 안에서 관리하려면
/plugin을 실행하고 Tab 키로 Installed 탭으로 가서 활성화·비활성화·업데이트·제거를 합니다. 문서에 따르면 터미널 세션에서는 탭 아래에1 mod active · first-mod같은 흐린 줄로 로드된 mod가 표시되고, 내장 mod는 이 줄에서 빠집니다.
mod를 끄는 세 가지 범위
| 끄려는 범위 | 방법 | 같이 일어나는 일 |
|---|---|---|
| mod 하나 | /plugin의 Installed 탭에서 비활성화·제거, 또는 claude plugin disable·uninstall | 그 플러그인만 영향 |
| 설치한 mod 전부, 이번 세션만 | claude --safe-mode로 시작 | 다른 사용자 지정도 함께 꺼짐 |
| 내가 설치한 mod 전부, 모든 세션 | ~/.claude/settings.json에 "disableAllHooks": true | 설정 훅과 사용자 지정 상태줄도 멈춤. 조직이 관리하는 항목은 계속 실행 |
disableAllHooks는 mod 코드만 멈추고, 같은 플러그인의 스킬, 명령, 에이전트, MCP 서버는 계속 로드합니다. 문제가 생겼을 때 원인이 mod인지 가르려면 --safe-mode로 한 번 실행해 보는 것이 빠릅니다.
Claude Code에는 처음부터 mod로 만들어진 기능도 있습니다. /plugin Installed 탭의 Built-in 아래에 cc-plugin-agents-md(AGENTS.md 로드), cc-plugin-diff(/diff 창), cc-plugin-plugin-authoring(mod 작성용 스킬만 제공), cc-plugin-sec-default(위의 가드), cc-plugin-telemetry, cc-plugin-you-should-know가 보입니다. 마지막 것은 긴 작업 중에 놓치기 쉬운 내용을 프롬프트 위에 알려 주는 보조 에이전트로, 기본은 꺼져 있고 /plugin enable cc-plugin-you-should-know@builtin으로 켭니다. 내장 mod는 disableAllHooks, --bare, --safe-mode로 꺼지지 않으며 각자 /plugin에서 끄는 방식입니다.
Claude에게 mod 만들어 달라고 하기: dev-mods 폴더와 보관
코드를 직접 쓰지 않아도 됩니다. 대화형 세션에서 make a mod that shows the current git branch above the prompt처럼 원하는 것을 설명하면, Claude가 내장 plugin-authoring 스킬을 바탕으로 mod를 씁니다. 스킬을 직접 불러오려면 /plugin-authoring을 실행합니다. 이 과정은 로그인한 대화형 세션이 필요해 2.1.288 실행 기록에는 없으며, 아래는 공식 문서의 흐름입니다.
- Claude는
~/.claude/dev-mods/<세션 ID>/<mod 이름>/에 파일을 만듭니다.~/.claude는 보호 경로라서default와acceptEdits권한 모드에서는 파일마다 승인을 요청합니다. - 첫 파일이 저장되면 이 세션에서 핫 리로드를 켤지 묻습니다. Enable for this session을 고르면 턴이 끝날 때 mod가 로드되고, 이후 파일이 바뀌는 턴마다 다시 로드됩니다. Not now를 고르면 지금은 로드되지 않고 그 세션을 다음에 시작할 때 로드됩니다.
/plugin의 Installed 탭에서 로드 여부를 확인하고, 마음에 들지 않으면 Claude에게 고칠 점을 말합니다.
Claude가 쓴 mod는 그 세션에서만 로드되고, 세션의 mod 폴더는 cleanupPeriodDays가 지나면 삭제됩니다. 계속 쓰려면 ~/mods/git-branch처럼 내 폴더로 복사한 뒤 claude --plugin-dir ~/mods/git-branch로 불러오거나 마켓플레이스에 올립니다. claude -p나 dontAsk 모드처럼 승인할 사람이 없는 세션, 신뢰하지 않은 작업 공간, mod가 꺼진 환경에서는 Claude가 쓴 mod가 로드되지 않습니다.
첫 mod 직접 만들기: first-mod 파일 3개와 validate·test
코드가 어떻게 돌아가는지 알고 싶다면 공식 튜토리얼의 first-mod가 출발점으로 좋습니다. Claude의 도구 호출 수를 세어 스피너 옆에 보여 주고, 그 수를 출력하는 /tally 명령을 추가합니다. Node.js, 번들러, 빌드 단계는 필요 없습니다. Claude Code가 .js와 .ts 파일을 바로 로드합니다.
first-mod/
├── .claude-plugin/
│ └── plugin.json
└── hooks/
├── hooks.json
└── register.jsfirst-mod/.claude-plugin/plugin.json은 플러그인 매니페스트입니다.
{
"name": "first-mod",
"version": "0.1.0",
"description": "Counts Claude's tool calls, shows the count beside the spinner, and adds a /tally command",
"author": { "name": "Your Name" }
}first-mod/hooks/hooks.json의 modules 키가 코드 파일을 가리킵니다. 이 키가 있어야 플러그인이 mod가 됩니다.
{
"description": "The first-mod hooks module",
"modules": ["./register.js"]
}first-mod/hooks/register.js가 실제 코드입니다. 주석만 한국어로 바꿨고 코드는 공식 튜토리얼 그대로입니다.
// 아래 훅들이 함께 쓰는 카운트
let calls = 0
// mod가 로드될 때 Claude Code가 한 번 호출
export function register(on) {
// 세션 시작 시, 첫 프롬프트 전에 실행
on('session.start', async ($, e, next) => {
// /tally 명령 추가
await $.command.register({
name: 'tally',
description: 'Show how many tool calls Claude has made',
})
// 세션은 평소대로 시작
return next(e)
})
// Claude가 도구를 쓰려 할 때마다 실행
on('tool.call', async ($, e, next) => {
calls += 1
// 새 카운트가 보이도록 화면을 다시 그려 달라고 요청
$.ui.invalidate('ui.render')
// 도구는 평소대로 실행
return next(e)
})
// /tally를 입력했을 때만 실행 (두 번째 인자가 필터)
on('command.run', { command: 'tally' }, async () => {
return { text: 'Claude has made ' + calls + ' tool calls since this mod loaded' }
})
// 스피너를 그릴 때마다 실행
on('ui.render', { component: 'Spinner' }, async ($, e, next) => {
// 원래 스피너는 유지하고 단어 뒤에 카운트를 붙임
return next({ ...e, props: { ...e.props, suffix: ' · tool calls: ' + calls + '…' } })
})
}모든 훅은 ($, e, next) 세 인자를 받습니다. $는 mods API, e는 이벤트 데이터, next는 이벤트를 다른 mod와 Claude Code 기본 동작으로 넘기는 함수입니다. session.start와 tool.call 훅은 next(e)를 그대로 돌려줘서 지켜보기만 하고, command.run 훅은 next를 부르지 않고 직접 답하며, ui.render 훅은 e를 고친 복사본을 넘겨 스피너를 바꿉니다.
validate, test, claude -p로 확인한 결과
먼저 정적 분석입니다.
$ claude plugin validate ./first-mod
Validating plugin manifest: .../first-mod/.claude-plugin/plugin.json
Validating hooks: .../first-mod/hooks/hooks.json
❯ ./register.js hooks: session.start, tool.call, command.run{command=tally}, ui.render{component=Spinner}
❯ ./register.js calls: $.command.register, $.ui.invalidate
✔ Validation passedhooks: 줄에 의도한 이벤트 4개가 모두 있으면 Claude Code도 그 훅을 호출합니다. 하나가 빠졌다면 대부분 이벤트 이름 오타입니다.
다음은 자동 테스트입니다. claude plugin test는 세션, 로그인, 네트워크 없이 이벤트를 발생시켜 훅의 동작을 확인합니다. 공식 튜토리얼의 테스트를 first-mod/tests/first-mod.test.ts로 저장합니다.
import { expect, test } from 'claude-code/testing'
test('/tally reports the tool calls the mod has seen', async ($, on) => {
// 도구 호출에 대신 답해서 실제 도구는 실행하지 않음
on('tool.call', () => ({ result: 'ok' }))
// 도구 호출 두 번 발생
await $.tool.call({ tool: 'Bash', command: 'ls' })
await $.tool.call({ tool: 'Read', file_path: 'README.md' })
// /tally를 실행하고 답을 확인
const answer = await $.command.run({ command: 'tally', args: '' })
expect(answer.text).toBe('Claude has made 2 tool calls since this mod loaded')
})first-mod 디렉터리에서 실행한 결과입니다. 시간은 실행할 때마다 달라집니다.
$ claude plugin test
tests/first-mod.test.ts:
(pass) /tally reports the tool calls the mod has seen [64.48ms]
1 pass
0 fail
Ran 1 test across 1 file. [0.34s]마지막으로 비대화형 모드에서 명령을 실행합니다. command.run 훅은 모델을 부르지 않고 답하기 때문에 CLI에 로그인하지 않은 상태에서도 결과가 나왔습니다. Claude Code가 명령 텍스트 앞에 플러그인 이름을 붙입니다.
$ claude -p "/tally" --plugin-dir ./first-mod
first-mod: Claude has made 0 tool calls since this mod loaded스피너 옆에 Thinking · tool calls: 2…처럼 숫자가 올라가는 모습은 claude --plugin-dir ./first-mod로 대화형 세션을 열어야 보입니다. 문서에 따르면 세션을 연 채 register.js를 저장하면 핫 리로드되고, 그때 register가 다시 실행되어 calls가 0으로 돌아갑니다. 리로드 사이에 값을 유지하려면 $.state를 씁니다.
정적 분석을 통과하는 코드 규칙과 제한
validate가 모든 훅과 호출을 찾을 수 있도록 다음 규칙을 지킵니다.
- mods API는
$.store.get('notes')처럼$, 네임스페이스, 메서드를 끝까지 씁니다.const ui = $.ui처럼 변수에 담거나 구조 분해하면 실패합니다. on호출의 이벤트 이름은'tool.call'같은 문자열 리터럴로 씁니다. 변수나 반복문으로 넘기면 실패합니다.import는 플러그인 디렉터리 안의 파일만 상대 경로로 가져옵니다. 예외는 타입과 도우미를 위한claude-code하나입니다. 동적import()와require는 쓸 수 없습니다.- 플러그인 이름이
claude-로 시작하는 등 Anthropic 것처럼 보이면validate가 실패합니다.
--plugin-dir로 로드하면 Claude Code가 mod 디렉터리의 .claude-plugin/types/에 현재 버전의 이벤트와 메서드를 담은 .d.ts 파일을 써 줍니다. 이벤트와 메서드는 릴리스마다 바뀔 수 있어서, 문서와 다르면 이 타입 파일을 믿으라는 것이 공식 안내입니다. 개발은 설치본이 아니라 --plugin-dir 디렉터리로 합니다. 설치된 플러그인은 버전별로 캐시되어서 버전을 올리고 다시 설치하기 전에는 수정이 반영되지 않습니다.
현재 문서에 적힌 주요 제한은 훅 자체 실행 시간이 이벤트당 10초(prompt.edit 훅은 50밀리초), $.process.run이 기본 30초에 최대 10분, $.fs.read·$.fs.write가 파일당 4MiB, $.store가 JSON 합계 4MiB, claude plugin test의 테스트 하나가 기본 5초입니다. 릴리스에 따라 달라질 수 있습니다.
mod가 아무것도 안 할 때 보는 오류 메시지
mod의 모듈이나 훅이 실패하면 Claude Code는 그 부분을 건너뛰고 세션을 계속하기 때문에, 고장 난 mod는 그냥 아무 일도 안 하는 것처럼 보입니다. 먼저 claude plugin validate로 이벤트 이름 오타, 잘못된 매니페스트, 읽을 수 없는 모듈을 잡습니다.
2.1.288에서 일부러 파일을 망가뜨려 본 결과는 다음과 같습니다.
# 이벤트 이름을 'tool.calls'로 잘못 쓴 경우
✘ Found 1 error:
❯ modules../register.js: bad-mod: .../hooks/register.js:7: "tool.calls" is not an event; $ is always spelled $.noun.event(...) at the call site, on is always on("<event>", hook), and next.to always next.to(e, "<tier>")
✘ Validation failed
# hooks.json에 "modules" 대신 "module"이라고 쓰고 "hooks" 키도 없는 경우
✘ Found 1 error:
❯ root: hooks.json must have `hooks` (the hook matchers) or `modules` (hooks modules), or both
✘ Validation failed공식 문제 해결 문서는 modules 키가 없거나 철자가 틀리면 validate가 통과하면서 hooks: 줄만 빠진다고 설명합니다. 2.1.288에서 hooks 키와 modules 키가 둘 다 없을 때는 위처럼 실패했으니, 문서의 경우는 hooks 키가 따로 있는 파일로 보입니다. 어느 쪽이든 고치는 방법은 "modules": ["./register.js"]를 넣는 것입니다.
validate가 통과하는데도 안 된다면 Claude Code가 남기는 한 줄짜리 메시지를 찾습니다. 위치는 세션 종류에 따라 다릅니다.
--plugin-dir로 연 대화형 세션처럼 핫 리로드하는 세션: 트랜스크립트에 흐린 줄로 표시- 마켓플레이스에서 설치한 mod를 쓰는 일반 대화형 세션: 디버그 로그에만 기록.
claude --debug로 시작해야 생김 --plugin-dir를 붙인claude -p실행: stderr
로드를 거부당하면 hooks module <이름> not loaded: 뒤에 이유가 붙습니다.
| 메시지 | 원인 |
|---|---|
disableAllHooks in managed settings | 조직이 설치된 플러그인의 훅을 끔 |
only managed plugins and built-in plugins run | allowManagedHooksOnly가 설정되었거나, 관리형이 아닌 설정 파일에 disableAllHooks가 있음 |
installed plugins that are not managed load no hooks module in this mode (--bare) | --bare로 시작함 |
another plugin of that name loads first | 같은 이름의 플러그인이 둘 있음 |
mods are limited to your organization's by policy (allowManagedModsOnly) | 조직이 자체 mod만 허용함 |
tried to lift a deny rule in your settings | mod의 tool.check 훅이 deny 규칙이 거부한 호출을 승인하려 함. 호출은 계속 거부됨 |
처음 여는 디렉터리에서는 신뢰 확인 창에 답하기 전까지 어떤 mod도 로드되지 않고, --safe-mode로 시작하면 설치된 플러그인이 하나도 로드되지 않습니다. 그 밖의 증상은 Claude Code 공식 문서의 mod 문제 해결 페이지에 메시지별로 정리되어 있습니다.
Claude Code mods 자주 묻는 질문
mod가 나왔으니 settings.json의 설정 훅은 없어지나요?
아니요. 공식 관리자 문서는 설정 훅에 대해 폐지되는 것이 없다고 밝히고 있고, 설정 훅과 mod는 함께 실행됩니다. 이미 있는 셸 스크립트로 막거나 기록하는 일이라면 설정 훅이 여전히 간단합니다.
남이 만든 Claude Code mod는 어디서 찾나요?
공식 경로는 /plugin으로 추가한 마켓플레이스, Anthropic 디렉터리, 그리고 anthropics/claude-code-playground 저장소의 샘플 mod 폴더입니다. 서드파티 목록으로는 GitHub의 awesome-claude-code-mods 목록이 2026년 10월 6일 기준 공개 mod 2,685개를 validate 출력과 함께 싣고 있습니다. 공식 디렉터리가 아닌 독립 스캔이고, 목록 스스로도 검증 통과가 안전한 동작을 보장하지 않는다고 적고 있으니 설치 전 점검은 똑같이 거쳐야 합니다.
내가 만든 mod를 팀원과 공유하려면?
몇 명이면 디렉터리나 .zip을 보내면 되고, 팀이라면 비공개 저장소로 자체 마켓플레이스를 만듭니다. 조직 전체라면 관리자가 관리형 설정으로 설치할 수 있고, 누구나 쓰게 하려면 저장소를 공개하거나 Anthropic 디렉터리에 제출합니다. 이벤트와 메서드가 릴리스마다 바뀔 수 있으니 README에 시험한 Claude Code 버전을 적어 두는 것이 좋습니다. 만드는 과정 전체는 Claude Code 공식 문서의 mod 만들기 페이지에 있습니다.
참고 자료6
이 글이 링크한 외부 페이지를 본문에 나온 순서대로 정리했습니다. 마지막 업데이트: 2026년 10월 6일.
참고 자료6
이 글이 링크한 외부 페이지를 본문에 나온 순서대로 정리했습니다. 마지막 업데이트: 2026년 10월 6일.
- 1.Anthropic의 Claude Code mods 발표 글claude.com/blog/claude-code-mods
- 2.Claude Code 공식 문서의 Mods 개요code.claude.com/docs/ko/plugins/mods/overview
- 3.anthropics/claude-code-playground 저장소의 샘플 mod 폴더github.com/anthropics/claude-code-playground/tree/main/claude-code/mods
- 4.Claude Code 공식 문서의 mod 문제 해결 페이지code.claude.com/docs/ko/plugins/mods/troubleshoot
- 5.GitHub의 awesome-claude-code-mods 목록github.com/karanb192/awesome-claude-code-mods
- 6.Claude Code 공식 문서의 mod 만들기 페이지code.claude.com/docs/ko/plugins/mods/create





