Claude Code Mods는 Claude Code 프로세스 안에서 도는 JavaScript, TypeScript 함수로 화면에 창을 그리고, 도구 호출을 붙잡고, 슬래시 명령을 더하는 플러그인입니다. 2026년 10월 1일 2.1.287에서 "Added Claude Mods"라는 한 줄로 나왔고(Claude Code changelog), 별도 설정 없이 기본으로 켜져 있습니다. 같은 날 Anthropic 블로그는 mod가 "이벤트 전에, 뒤에, 또는 이벤트 대신 실행될 수 있다"고 소개했습니다(Customize Claude Code with mods in TypeScript, claude.com, 2026-10-01). 지금까지의 훅이 설정 파일에 적은 셸 명령을 밖에서 실행했다면, mod의 훅은 Claude Code가 직접 부르는 함수라서 사용자 인터페이스와 모델 요청 한가운데까지 들어갑니다. 이 글은 공식 문서 10개 페이지와 Anthropic 공식 샘플 3개를 읽고, 필자의 PC에서 예제 mod를 만들어 validate와 test를 돌린 결과로 구조를 정리한 뒤 바로 써먹을 수 있는 10가지 활용을 코드와 함께 소개합니다.
필자는 『클로드 코드 제대로 시작하기』를 썼고, 어비스 블로그 글도 Claude Code 스킬과 설정 훅으로 만든 파이프라인으로 씁니다. 이 글의 validate, test 출력은 필자가 macOS의 Claude Code 2.1.292에서 2026년 10월 7일에 직접 실행한 결과이고, 활용 예시의 코드는 공식 문서의 예제를 옮기거나 줄인 것입니다. Claude Code의 기본 사용법은 Claude Code 팁 11가지에 따로 정리해 두었습니다.
핵심 요약
- mod는 함수 훅으로 된 플러그인입니다.
plugin.json,hooks/hooks.json, 훅 모듈(register.js) 세 파일이면 되고, 빌드 단계 없이.js,.ts를 바로 읽습니다. 터미널은 2.1.287, 데스크톱 앱 Code 탭은 2.1.286부터 동작합니다.- 훅은
$,e,next세 인자를 받는 미들웨어입니다.next(e)로 그대로 넘기면 관찰, 고친 사본을 넘기면 재작성,next를 부르지 않고 값을 돌려주면 응답입니다.- 설정 훅, 스킬, MCP와 다른 점은 "안에서 돈다"는 것입니다. 창과 띠 영역을 그리고, 스피너나 도구 호출 행을 다시 그리고, 턴 없이 도는 명령을 만들고, 요청마다 모델을 바꿀 수 있습니다.
- 10가지 활용은 컨텍스트 게이지, 위험 명령 보류, 편집 다시 보기, 브랜치별 허용 규칙, 프롬프트 맥락 주입, 즉시 실행 명령, 사용자 정의 도구, 작은 모델 호출, 백그라운드 감시, 조직 정책 mod입니다.
- mod는 샌드박스 없이 사용자 권한으로 돕니다. 공개 mod 2,685개를 세어 보니 51%가 파일 쓰기나 프로세스 실행에 닿았습니다. 설치 전에
claude plugin validate로calls:줄을 읽고, 막는 훅에는.catch를 붙여야 실패할 때 명령이 그냥 실행되지 않습니다.
목차
- Claude Code Mods는 무엇인가요?
- 설정 훅, 스킬, MCP와 무엇이 다른가요?
- mod의 구조: 파일 세 개와 register 함수
- 직접 만들어 보니: validate와 test
- Claude Code Mods 10가지 활용
- 설치하기 전에 확인할 보안
- 어디서 동작하고 어디서 안 보이나요?
- 이 글의 자료를 고른 방법
- 자주 묻는 질문
- 마치며
- 출처
Claude Code Mods는 무엇인가요?
mod는 Claude Code의 모양과 동작을 바꾸는 플러그인이고, 그 본체는 이벤트가 생길 때 Claude Code가 호출하는 함수입니다. 공식 개요는 mod를 "JavaScript 또는 TypeScript 이벤트 핸들러로 구성된 플러그인"이라고 정의하고, 도구 호출, 프롬프트 제출, 인터페이스 일부의 렌더링 같은 이벤트가 생기면 핸들러가 그 이벤트를 관찰하거나, 바꾸거나, 직접 처리한다고 설명합니다(Mods overview 한국어판).
공식 문서가 꼽는 mod만의 능력은 다섯 가지입니다(Mods overview).
- 직접 쓸 수 있는 인터페이스 그리기: 트랜스크립트 옆의 창(pane)이나 프롬프트 위의 띠 영역(band)에 탭, 버튼, 입력란을 둡니다.
- Claude Code 자체 화면 다시 그리기: 도구 호출 행, 스피너, Claude가 질문할 때 쓰는 대화 상자를 바꾸거나 꾸밉니다.
- 도구 호출과 요청에 개입하기: 사용자에게 묻는 동안 도구 호출을 붙잡거나, 도구를 실행하지 않고 대신 답하거나, 한 요청만 다른 모델로 보냅니다.
- 명령으로 내 코드 실행하기: Claude 턴을 거치지 않고, Claude가 일하는 중에도 바로 도는
/명령을 만듭니다. - 훅 사이에서 데이터 공유하기: 한 파일의 변수를 여러 훅이 같이 쓰므로, 한 훅이 센 값을 다른 훅이 화면에 그립니다.
이름 때문에 헷갈리기 쉽습니다. 공식 한국어 문서는 "mod"를 번역하지 않고 그대로 쓰는데, 국내 기사와 블로그 대부분은 "모드"라고 적어서 auto mode, plan mode, 권한 모드와 검색 결과가 섞입니다. 한 국내 블로그는 아예 "Shift+Tab으로 바꾸는 권한 모드와는 다른 기능"이라고 첫머리에 밝혀 두었습니다(부컴, 2026-10-03). 이 글은 공식 문서를 따라 mod로 씁니다.
Claude Code의 일부 기능은 이미 mod로 만들어져 있습니다. /plugin의 Installed 탭에서 Built-in으로 보이는 cc-plugin-diff(/diff 창), cc-plugin-agents-md(AGENTS.md 읽기), cc-plugin-sec-default(조직이 관리하는 설정을 지키는 가드)가 그 예이고, 2.1.287에는 옆에서 따로 도는 에이전트가 사용자나 Claude가 놓친 것을 프롬프트 위에 알려 주는 You should know가 기본 꺼진 상태로 함께 들어왔습니다(Claude Code changelog).
설정 훅, 스킬, MCP와 무엇이 다른가요?
나머지 셋은 Claude Code 밖에서 스크립트를 돌리거나 Claude에게 글과 도구를 주는 방식이고, mod만 Claude Code 안에서 돕니다. 그래서 화면에 그릴 수 있는 것은 mod뿐이고, 고칠 수 있는 범위도 가장 넓습니다. 공식 비교표를 한국어로 옮기면 다음과 같습니다(Mods overview).
| 구분 | mod | 설정 훅 | 스킬 | MCP 서버 |
|---|---|---|---|---|
| 정체 | Claude Code 프로세스 안에서 부르는 플러그인 함수 | 생명주기 이벤트에 도는 셸 명령, HTTP 요청, 프롬프트 | Claude가 읽는 SKILL.md 지침 |
Claude에게 도구를 주는 외부 프로세스 |
| 바꿀 수 있는 것 | 도구 호출, 프롬프트, 명령, 턴, 화면 | 도구 호출과 프롬프트의 진행 여부, 인자와 결과, 추가 맥락 | Claude가 아는 것과 하는 일 | Claude가 가진 도구 |
| 화면에 그리기 | 가능 | 불가 | 불가 | 불가 |
| 작성 언어 | JavaScript, TypeScript | 스크립트와 settings.json |
Markdown | 아무 언어 |
| 고를 때 | 창, 띠 영역, 사용자 명령, 이벤트 재작성이 필요할 때 | 이미 있는 스크립트로 막거나 허용하거나 기록할 때 | 같은 지시를 계속 붙여 넣을 때 | Claude가 외부 시스템에 닿아야 할 때 |
설정 훅이 사라지는 것은 아닙니다. 조직 관리 문서는 "설정 훅은 계속 동작하며 폐기되는 것은 없다"고 적고 있습니다(Manage mods for your organization). 필자의 블로그 파이프라인처럼 "커밋 안 된 변경이 있으면 끝내지 못하게 막기" 정도는 셸 스크립트 하나로 된 설정 훅이 더 단순합니다. 화면에 무언가를 띄우거나, 한 이벤트에서 센 값을 다른 이벤트에서 쓰거나, 도구를 실행하지 않고 대신 답해야 할 때 mod를 고르면 됩니다.
mod의 구조: 파일 세 개와 register 함수
작은 mod는 매니페스트, 훅 목록, 훅 모듈 세 파일로 끝납니다. hooks/hooks.json에 modules 키가 있으면 그 플러그인이 mod가 됩니다(Create a mod).
first-mod/
├── .claude-plugin/
│ └── plugin.json # 플러그인 매니페스트 (mod 전용 필수 필드 없음)
└── hooks/
├── hooks.json # { "modules": ["./register.js"] }
└── register.js # 훅 모듈: register(on)을 export
훅 모듈은 register 함수 하나를 내보냅니다. mod가 로드되면 Claude Code가 이 함수를 한 번 부르면서 on을 넘기고, on('이벤트 이름', 매처, 훅)을 부를 때마다 훅 하나가 등록됩니다. 다음은 공식 개요의 예제로, Claude의 도구 호출 수를 세어 스피너 옆에 Thinking · tool calls: 3…처럼 보여 줍니다.
// 두 훅이 함께 쓰는 값
let calls = 0
export function register(on) {
// Claude가 도구를 쓰기 직전마다 실행
on('tool.call', async ($, e, next) => {
calls += 1
$.ui.invalidate('ui.render') // 화면을 다시 그려 달라고 요청
return next(e) // 도구는 평소대로 실행
})
// Claude Code가 스피너를 그릴 때마다 실행
on('ui.render', { component: 'Spinner' }, async ($, e, next) => {
return next({ ...e, props: { ...e.props, suffix: ' · tool calls: ' + calls + '…' } })
})
}
모든 훅은 같은 세 인자를 받습니다(Mods reference).
$(mods API): 훅이 자기 코드 밖으로 나가는 유일한 길입니다. 그리기($.ui), 명령($.command), 모델 호출($.model), 파일($.fs), 프로세스($.process), 네트워크($.http) 같은 네임스페이스가 있습니다.e(이벤트): 도구 이름과 인자 같은 이벤트 입력이 깊게 얼린(frozen) 순수 데이터로 들어옵니다. 바꾸려면 사본을 만들어next에 넘깁니다.next(다음 핸들러): 미들웨어처럼 뒤의 mod들을 거쳐 Claude Code 본래 동작까지 이어 주고 결과를 돌려줍니다.
훅이 이벤트를 다루는 방식은 세 가지뿐입니다. next(e)를 그대로 부르면 관찰, 고친 사본으로 부르면 재작성, next를 부르지 않고 { deny: '...' }나 { result: '...' }를 돌려주면 응답입니다. 위 예제의 tool.call 훅은 관찰, ui.render 훅은 재작성입니다.
mod가 그릴 수 있는 자리는 공식 화면 지도에 정리되어 있습니다. 창과 토스트, 로그 줄, 띠 영역, 상태줄은 mod가 새로 더하는 자리이고, 메시지, 도구 호출 행, 스피너는 Claude Code가 그리는 것을 mod가 다시 그릴 수 있는 자리입니다. 프롬프트 입력창만은 Claude Code의 것입니다.

여러 mod가 같은 이벤트를 훅하면 하나의 미들웨어 사슬이 됩니다. 순서는 출처로 정해지며, 먼저 오는 mod가 가장 바깥에서 이벤트를 먼저 보고 결과를 마지막에 봅니다(React to events).
이벤트는 도구(tool.call, tool.check), 프롬프트(prompt.submit, prompt.section), 명령(command.run), 턴(turn.start, turn.step, turn.complete), 세션(session.start, session.compact), 서브에이전트(agent.spawn), 인터페이스(ui.render, ui.press), 다른 mod(plugin.register)로 묶여 있고, 기존 설정 훅 이벤트도 classic.Stop처럼 classic. 접두사로 받을 수 있습니다(Mods reference). 버전마다 이벤트가 늘고 있어서, 정확한 목록은 mod를 로드할 때 .claude-plugin/types/에 생기는 .d.ts 파일을 보는 편이 안전합니다. 공식 문서도 "이 페이지와 다르면 이 파일을 믿으라"고 적어 두었습니다.
직접 만들어 보니: validate와 test
공식 튜토리얼을 따라 만든 mod는 validate를 통과했지만, 튜토리얼의 도구 호출 세기 훅과 필자가 덧붙인 위험 명령 가드 모두에 문서 예시에 없던 경고가 붙었습니다. 필자는 공식 first-mod(도구 호출 세기, 스피너 표시, /tally 명령)에 이벤트 가이드의 위험 명령 보류 훅을 더해 claude plugin validate .를 돌렸습니다. 출력은 다음과 같습니다(macOS, Claude Code 2.1.292, 2026-10-07).
❯ ./register.js hooks: session.start, tool.call{tool=Bash}, tool.call, command.run{command=tally}, ui.render{component=Spinner}
❯ ./register.js answers its own command: command.run{command=tally}
❯ ./register.js gating hook without .catch: tool.call{tool=Bash}
❯ ./register.js gating hook without .catch: tool.call
❯ ./register.js calls: $.command.register, $.ui.ask, $.ui.invalidate
✔ Validation passed
hooks: 줄은 mod가 받는 이벤트와 매처를, calls: 줄은 코드가 부르는 mods API를 나열합니다. Claude Code는 이 정적 분석으로 읽을 수 없는 방식으로 $를 쓰는 mod를 아예 로드하지 않습니다. 그래서 const ui = $.ui처럼 $를 변수에 담거나 이벤트 이름을 변수로 넘기면 검증이 실패합니다(Create a mod).
눈여겨볼 줄은 gating hook without .catch입니다. 문서에 따르면 .catch가 없는 훅이 next를 부르기 전에 예외를 던지거나 10초 한도를 넘기면 Claude Code는 그 훅을 건너뛰고 다음 핸들러를 실행합니다(React to events). 위험한 명령을 막으려고 만든 가드가 버그 한 번에 명령을 통과시키는 셈입니다. 공식 샘플인 blast-radius와 replay-theater도 같은 줄이 떴으니, 공식 예제조차 이 부분은 기본값에 맡기고 있습니다. 가드 훅에 다음처럼 .catch를 붙이자 해당 줄이 gating hook with .catch: tool.call{tool=Bash}로 바뀌었습니다.
on('tool.call', { tool: 'Bash' }, guard).catch(async ($, e, next) => {
// guard가 throw 또는 timeout으로 실패하면 이 핸들러가 대신 답한다
return { deny: 'The command guard failed, so this command was not run: ' + next.error.kind }
})
테스트도 세션이나 로그인 없이 돕니다. tests/first-mod.test.ts에 "도구 호출 두 번 뒤 /tally가 2를 말한다", "아무도 답하지 않으면 force push가 거부된다" 두 테스트를 쓰고 claude plugin test를 실행하자 둘 다 0.3초 안에 통과했습니다. 비대화형 실행인 claude -p "/tally" --plugin-dir .도 first-mod: Claude has made 0 tool calls since this mod loaded를 출력했습니다. 두 번째 테스트가 통과한 이유는 claude -p처럼 물어볼 사람이 없는 환경에서 $.ui.ask가 거부(reject)되고, 예제가 그 경우를 Refuse로 처리하기 때문입니다. 질문 대상이 없을 때 안전한 쪽으로 떨어지게 짜는 것이 가드 mod의 기본입니다.
Anthropic 공식 샘플 3개도 같은 방식으로 검사해 봤습니다. 모두 통과했고, 출력에서 각 mod의 크기와 쓰는 기능이 한눈에 보였습니다.
$.process.run이 들어 있습니다. 같은 이름의 mod라도 이 줄을 보면 무엇에 닿는지 알 수 있습니다. 출처: anthropics/claude-code-playground 커밋 569c528을 필자가 validate로 측정직접 짜지 않아도 됩니다. 세션에서 "현재 git 브랜치를 프롬프트 위에 보여 주는 mod를 만들어 줘"처럼 말하면, Claude가 내장 plugin-authoring 스킬을 읽고 ~/.claude/dev-mods/<세션 ID>/ 아래에 mod를 씁니다. 첫 파일을 저장할 때 이 세션에서 핫 리로드를 켤지 묻고, 켜면 턴이 끝날 때마다 바뀐 mod가 다시 로드됩니다. 이 폴더는 cleanupPeriodDays가 지나면 지워지므로, 계속 쓸 mod는 다른 곳에 복사해 claude --plugin-dir로 띄우거나 마켓플레이스에 올립니다(Create a mod).
Claude Code Mods 10가지 활용
아래 10가지는 공식 샘플과 공식 문서의 예제에서 골랐고, 앞의 셋은 화면, 가운데 넷은 Claude의 작업 흐름, 뒤의 셋은 바깥 세계와 조직을 다룹니다. 코드는 핵심만 남겨 줄였습니다.
1. 컨텍스트 사용량을 날씨처럼 띄우기
공식 샘플 token-weather는 턴이 끝날 때마다 $.session.usage()로 컨텍스트 사용률을 읽어 프롬프트 위 띠 영역에 "맑음, 소나기, 폭풍" 같은 예보로 그립니다. 훅은 session.start, turn.complete, ui.render{component=AbovePrompt} 세 개뿐이고, 훅 모듈은 122줄입니다. README에 만든 과정이 적혀 있는데, Claude가 써 준 mod 아이디어 10개 가운데 세 개를 골라 "implement 1,2,7"이라고 시킨 결과가 세 샘플입니다. 원래 아이디어는 Svg 요소로 차트를 그리는 것이었지만 터미널은 Svg를 못 그려서 블록 문자 한 줄로 바뀌었다고 합니다. usage()는 컨텍스트의 토큰 수, 창 크기, 사용률과 요금제 한도의 사용률, 초기화 시각을 돌려주므로(Mods reference), 같은 방식으로 주간 한도 게이지도 만들 수 있습니다.

2. 위험한 명령을 붙잡고 영향 범위 보여 주기
blast-radius는 rm -rf, git reset --hard, force push, 마이그레이션 같은 셸 명령을 tool.call에서 붙잡고, 실제로 무엇이 지워지는지 계산해 창에 보여 준 뒤 Proceed와 Cancel 버튼으로 결정을 받습니다. 권한 프롬프트의 "허용할까요?"는 명령 문자열만 보여 주지만, 이 mod는 "파일 9개, 1.1MB 삭제"처럼 결과를 보여 준다는 점이 다릅니다. 한계도 분명합니다. 공식 입문 글은 이 mod를 "권한 시스템이 아니라 안전망"이라고 부르면서, 명령 문자열을 읽는 방식이라 $(…), 별칭(alias), rm을 부르는 스크립트는 빠져나간다고 적었습니다. 확실히 막아야 할 명령은 권한 규칙으로 막으라는 것입니다(Getting started with Claude Code mods).

rm -rf build를 붙잡아 build 폴더의 파일 9개(1.1MB)가 지워진다고 보여 주고, 사용자가 고를 때까지 명령을 보류합니다. 출처: Anthropic, claude-code-playground blast-radius (Apache-2.0)이 정도로 꾸미지 않아도 됩니다. 공식 이벤트 가이드의 최소 버전은 $.ui.ask로 질문 대화 상자를 띄우는 짧은 훅 하나이고, 대기 시간은 mods API 호출 안에서 보내므로 10초 한도에 걸리지 않습니다(React to events). 앞 절의 .catch를 함께 붙이는 것을 잊지 마세요.
3. 마지막 턴의 편집을 한 단계씩 다시 보기
replay-theater는 /replay 명령을 더하고, 마지막 턴에서 Claude가 고친 파일을 한 편집씩 창에 diff로 보여 줍니다. turn.start와 turn.complete로 턴의 경계를 잡고, 그 사이의 tool.call에서 Edit, Write 호출을 모아 두는 구조입니다. 긴 트랜스크립트를 스크롤하지 않고 Prev, Next 버튼으로 변경만 훑을 수 있습니다.

4. 상황에 따라 허용과 거부를 바꾸기
권한 규칙 Bash(npm test)는 고정된 명령에는 충분하지만 "지금 main 브랜치라면"처럼 그 순간의 상태에 따라 달라지는 판단은 못 합니다. tool.check는 권한 규칙과 설정 훅이 내린 결정(allow, ask, deny)을 next(e)로 받은 뒤 바꿀 수 있는 이벤트입니다.
on('tool.check', { tool: 'Bash' }, async ($, e, next) => {
const decided = await next(e) // 규칙과 설정 훅의 결정
if (!e.input.command.includes('git push')) return decided
const branch = await $.process.run(['git', 'branch', '--show-current'])
if (branch.stdout.trim() !== 'main') return decided
return { decision: 'deny', reason: 'Push from a branch other than main' }
})
공식 문서는 이 훅이 명령 문자열을 보고 판단하므로 "Claude를 위한 알림"으로 다루고, 모두에게 main 푸시를 막으려면 Git 호스트에서 브랜치를 보호하라고 덧붙입니다(React to events).
5. 프롬프트에 맥락을 보이지 않게 붙이기
prompt.submit은 프롬프트가 턴을 시작하기 전에 받습니다. 사본의 text를 바꾸면 트랜스크립트에 보이는 문장이 바뀌고, context에 줄을 더하면 사용자 화면은 그대로 두고 Claude만 읽는 맥락이 붙습니다. 공식 예제는 프롬프트에 "PR"이나 "pull request"가 있을 때만 Current branch: feature/auth 같은 줄을 붙입니다. 매번 "지금 브랜치는..."이라고 쓰던 습관을 훅 하나로 없앨 수 있습니다. 다만 요청마다 바뀌는 글을 시스템 프롬프트 쪽(prompt.section, prompt.context)에 넣으면 프롬프트 캐시가 깨진다는 경고가 문서에 있습니다(React to events).
6. Claude 턴 없이 바로 도는 명령 만들기
스킬로 만든 슬래시 명령은 결국 Claude에게 지시를 건네 턴을 씁니다. mod의 명령은 내 함수가 바로 답하므로 토큰을 쓰지 않고, 등록할 때 immediate: true를 주면 Claude가 일하는 중에도 실행됩니다(Use the mods API).
on('session.start', async ($, e, next) => {
await $.command.register({ name: 'standup', description: 'Summarize what changed today', argumentHint: '[days]' })
return next(e)
})
on('command.run', { command: 'standup' }, async ($, e) => {
return { text: 'Summary for the last ' + (e.args || '1') + ' day(s): ...' }
})
돌려준 text는 트랜스크립트에 찍히고 Claude도 읽습니다. 창만 여는 명령처럼 아무것도 찍지 않으려면 {}를 돌려줍니다. 내장 명령과 이름이 겹치면 register가 예외를 던지고 그 훅의 나머지가 건너뛰어지므로, 명령 등록은 session.start 훅의 마지막에 두라는 것이 문서의 조언입니다.
7. Claude가 부를 도구를 직접 추가하기
MCP 서버를 따로 띄우지 않고도 도구를 하나 더 줄 수 있습니다. $.tool.register로 이름, 설명, 입력 JSON Schema를 등록하면 Claude는 mcp__<플러그인 이름>__<도구 이름>으로 이 도구를 보고, 호출은 같은 이름으로 걸러진 tool.call 훅이 처리합니다. 공식 예제는 사내 티켓 API를 $.http.fetch로 불러 제목과 상태를 돌려주는 ticket 도구입니다. 실패했을 때도 { result: 'Lookup failed with status 404' }처럼 결과를 돌려줘야 Claude가 실패를 알 수 있습니다(Use the mods API).
8. 작은 모델에게 잡일 맡기기
$.model.complete는 대화 기록 없이 프롬프트 하나를 모델에 보내고 답을 받습니다. 공식 예제의 /triage는 입력한 문장을 Haiku에게 보내 bug, feature, question 중 하나로 분류합니다.
on('command.run', { command: 'triage' }, async ($, e) => {
const r = await $.model.complete({
model: 'haiku',
system: 'Reply with one word: bug, feature, or question.',
prompt: e.args, maxTokens: 20, timeoutMs: 15000,
})
return { text: 'Label: ' + (r.isAnswered ? r.text.trim() : 'unknown') }
})
API 오류가 나도 호출은 거부되지 않으므로 r.isAnswered를 먼저 확인해야 합니다. 현재 대화를 바탕으로 한 번 묻고 싶다면 $.model.fork가 같은 모델과 시스템 프롬프트로 물어 프롬프트 캐시를 대부분 재사용합니다. 두 호출 모두 사용자의 요금제나 API 키를 씁니다(Use the mods API). 2.1.292에서는 $.model.complete에도 cache: true 블록으로 프롬프트 캐싱이 붙었습니다(Claude Code changelog).
9. 백그라운드에서 PR 체크 감시하기
훅 하나는 10초 안에 끝나야 하지만, session.start에서 $.clock.every로 타이머를 걸면 턴과 무관하게 계속 돌 수 있습니다. 공식 예제는 1분마다 gh pr checks를 실행해 결과를 프롬프트 아래 상태줄($.ui.status)에 한 줄로 바꿔 씁니다. 사용자에게 알리는 자리는 세 가지입니다. 계속 남는 상태줄($.ui.status), 4초 뒤 사라지는 오른쪽 위 토스트($.ui.toast), Claude는 읽지 않는 트랜스크립트의 흐린 줄($.ui.log)입니다. Claude가 직접 봐야 할 일이면 $.prompt.submit으로 세션이 한가해질 때 새 턴을 시작할 수 있습니다(Use the mods API).
10. 조직의 정책을 mod로 강제하기
plugin.register는 다른 mod가 로드되기 직전에 그 mod의 validate 결과(이벤트, API 호출, 환경 변수 목록)를 받습니다. 관리형 설정의 prependPlugins에 넣은 정책 mod는 이 목록을 보고 로드를 거부할 수 있습니다. 공식 예제 acme-guard는 $.process.run이나 $.process.spawn을 부르는 사용자 mod를 거부하고, 모든 도구 호출과 다른 mod의 $.fs.write를 디버그 로그에 감사 기록으로 남깁니다(Manage mods for your organization).
const BLOCKED_CALLS = ['process.run', 'process.spawn']
export function register(on) {
on('plugin.register', async ($, e, next) => {
const blocked = e.uses.calls.filter((call) => BLOCKED_CALLS.includes(call))
if (e.tier === 'user' && blocked.length > 0) {
return { refuse: 'Acme policy: mods may not call ' + blocked.join(', ') }
}
return next(e)
})
}
사용자 mod를 전부 막고 싶다면 정책 mod도 필요 없습니다. 내장 가드의 allowManagedModsOnly 옵션을 켜면 조직의 mod와 내장 mod만 로드됩니다.
국내 개발자들이 만든 mod
출시 사흘 만인 10월 4일부터 국내 개발자의 mod가 올라오기 시작했습니다. 한국 사용자에게 가장 직접 쓸모 있는 것은 Claude Code 화면을 한국어로 바꾸는 claude-code-ko-ui(MIT, 2026-10-04)입니다. command.describe로 슬래시 명령 설명을, config.describe로 /config 항목 44개를, ui.render의 Spinner, TurnDuration, ToolGroup 사이트로 작업 중 표시와 "Baked for 3s" 같은 줄을 고정 사전으로 바꿉니다. 모델 호출이 없어 토큰이 들지 않고, 권한 확인 창과 시작 화면처럼 훅이 없는 화면은 번역하지 못한다고 README에 적혀 있습니다. 필자가 받아 validate를 돌려 보니 calls: 줄에 $.fs.read, $.store, $.ui, $.command, $.config, $.clock 계열이 있고 $.http나 $.process는 없어서, "네트워크 요청이 없다"는 README의 설명과 맞았습니다.
이 밖에 답변을 타자기처럼 흘려 보여 주는 smooth-stream(ui.render와 turn.step 사용)이 긱뉴스에 소개됐고, 원화 요금 미터와 rm -rf를 멈추는 "과속 카메라"를 묶은 devbrothers-mods도 올라왔습니다. 한 국내 개발자는 API 키와 JWT를 가리고 위험 명령을 막는 mod를 TypeScript로 20~30분 만에 만들었다는 경험을 남기면서, 핫 리로드와 여러 mod의 실행 순서에서 헤맨 지점을 함께 적었습니다(피프티바이브, 2026-10-05).
설치하기 전에 확인할 보안
mod는 샌드박스 없이 사용자 권한으로 도는 코드이므로, 신뢰할 수 있는 작성자와 마켓플레이스의 것만 설치해야 합니다. 공식 개요는 로드된 mod가 할 수 있는 일을 이렇게 나열합니다(Mods overview).
- 사용자 계정이 닿는 모든 파일을 읽고 쓰고, 프로그램을 실행하고, 네트워크에 요청합니다.
- 환경 변수와 설정 파일에 둔 API 키를 읽습니다.
- 사용자가 보내는 모든 프롬프트와 Claude의 모든 도구 호출을 봅니다.
- 프롬프트와 도구 호출을 바꾸고, 사용자가 친 것처럼 프롬프트를 보내고, 다른 세션에 메시지를 보냅니다.
- 사용자에게 묻기 전에 도구 호출을 승인하고, 사용자의 요금제로 모델을 부릅니다.
"샌드박스"라는 말이 두 가지로 쓰여서 헷갈릴 수 있습니다. Addy Osmani의 공식 입문 글은 훅 모듈이 "DOM도 Node도 없는 자체 샌드박스에서 돌고, 밖의 모든 일은 $를 거친다"고 설명합니다(Getting started with Claude Code mods, claude.dev, 2026-10-01). 모듈 코드가 파일이나 네트워크에 직접 손대지 못한다는 뜻이지, 권한이 제한된다는 뜻은 아닙니다. $를 거치면 사용자가 할 수 있는 일은 다 할 수 있습니다. 또 Claude Code 샌드박스를 켜도 격리되는 것은 Claude가 실행하는 Bash 명령이고, mod가 시작한 프로세스는 그 밖에서 돕니다.
승인에 관한 규칙도 알아 둘 만합니다(Manage mods for your organization).
- mod가 넘어설 수 있는 것:
ask규칙이 물어볼 호출, 관리형이 아닌PreToolUse훅이 막은 호출. auto mode에서 mod가 승인한 호출은 분류기 검사를 거치지 않습니다. - mod보다 우선하는 것: 내장 가드가 로드되는 환경(관리형 설정이 있는 기기, Team이나 Enterprise 로그인)에서는
deny규칙과 관리형PreToolUse훅. 개인 요금제나 관리형 설정 없는 API 키 사용자는 이 가드가 없습니다. - 최근 수정: 2.1.289에서 복합 셸 명령의 일부에 걸린 deny, ask 규칙을 사용자 mod의 승인이 넘어서던 문제가 고쳐졌습니다(Claude Code changelog).
반대로 mod가 끝내 바꿀 수 없는 것은 권한 프롬프트입니다. 화면 대부분을 다시 그릴 수 있어도 권한 프롬프트가 보여 주는 내용은 못 바꿉니다.
공개된 mod는 실제로 어디까지 닿을까요?
공개된 mod의 절반은 파일을 쓰거나 프로그램을 실행합니다. 커뮤니티 카탈로그 awesome-claude-code-mods(CC0)는 GitHub의 공개 mod를 모아 claude plugin validate로 검사하고, calls: 줄을 바탕으로 mod마다 닿는 범위를 네 단계로 매깁니다. 필자가 이 카탈로그의 원본 데이터(data/mods.json, 2026-10-06 수집)를 내려받아 직접 세어 보니, 카탈로그가 mod로 분류한(kind=mod) 항목은 1,261개 저장소의 2,685개였습니다. 테스트 픽스처, 중복 사본, 카탈로그 저장소, 내장 mod는 카탈로그가 따로 분류해 두어 이 수에서 빠집니다. 출시 닷새 만의 숫자입니다. 카탈로그는 mod마다 닿는 범위 가운데 가장 넓은 것 하나로 등급을 매기는데, 51.0%(1,369개)가 "파일 쓰기나 프로세스 실행", 12.1%(326개)가 "네트워크" 등급이었고, 그리기와 저장만 하는 mod는 13.2%였습니다. 같은 작성자의 출시 직후 분석은 국내에서도 보도됐습니다(토큰포스트, 2026-10-02).
$.process.run을 부르는 mod만 1,065개(39.7%)였습니다. 공식 집계가 아닌 커뮤니티 카탈로그의 자동 검사 결과이고, 원본 데이터를 필자가 다시 셌습니다. 출처: karanb192/awesome-claude-code-mods$.process.run이 들어 있다고 위험한 mod는 아닙니다. 공식 샘플 blast-radius도 지워질 파일을 미리 계산하려고 이 API를 씁니다. 다만 그 줄이 있으면 코드를 직접 읽어야 할 이유가 생긴다는 뜻입니다.
필자가 설치 전에 하는 확인은 세 단계입니다.
- 저장소를 받아
claude plugin validate <폴더>를 돌립니다.calls:줄에$.process.run,$.process.spawn(프로그램 실행),$.http.fetch(네트워크),$.fs.write(파일 쓰기)가 있으면 그 이유를 README와 코드에서 찾습니다. - 가드 성격의 mod라면
gating hook without .catch줄을 봅니다. 실패할 때 명령이 그냥 통과되는 구조인지 확인합니다. - 처음에는
--plugin-dir로 한 세션에서만 써 봅니다. 문제가 생기면claude --safe-mode로 설치한 mod를 모두 끈 채 시작해 원인을 가립니다. 모든 세션에서 끄려면~/.claude/settings.json에"disableAllHooks": true를 두면 되는데, 이 설정은 설정 훅과 사용자 상태줄도 함께 끕니다.
어디서 동작하고 어디서 안 보이나요?
훅은 플러그인을 로드하는 모든 세션에서 돌지만, 그림은 터미널과 데스크톱 앱 Code 탭에서만 보입니다. VS Code 확장의 채팅 패널, claude -p, Agent SDK에서는 훅만 돌고 창이나 띠 영역은 나타나지 않습니다. 그래서 그리는 mod라면 $.session.surfaces() 같은 값으로 실행 환경을 확인하고, 그릴 수 없는 곳에서는 트랜스크립트 한 줄이나 명령의 텍스트 응답으로 대신하라는 것이 공식 권고입니다(Mods overview).
| 실행 환경 | 훅 실행 | 그림 표시 |
|---|---|---|
터미널의 claude (에디터 내장 터미널, JetBrains 플러그인 포함) |
예 | 예 |
| 데스크톱 앱 Code 탭 (WSL 세션 제외) | 예 | 예 (터미널 전용 요소 제외) |
| 데스크톱 앱의 WSL 세션 | 아니요 | 아니요 |
| VS Code 확장 채팅 패널 | 예 | 아니요 |
claude -p, Agent SDK |
예 | 아니요 |
| claude.ai나 모바일 앱의 Remote Control | 내 PC의 세션에서 예 | 내 PC의 터미널에서 |
| 클라우드 세션 | 플러그인이 클라우드에 전달된 경우 예 | 아니요 |
국내에서 가장 많이 나온 질문도 이 표와 관련이 있습니다. VS Code 확장에서 mod를 설치하면 훅은 돌지만 창과 띠 영역이 보이지 않아 설치에 실패한 것으로 오해하기 쉽다는 글이 있고(AI차림, 2026-10-05), Windows 사용자에게 특히 중요한 점으로, 데스크톱 앱의 WSL 세션에서는 mod가 아예 돌지 않는다는 점을 짚은 글도 여럿입니다(똥믈리에, 2026-10-04, 스쿱노트, 2026-10-03). 그리는 mod를 시험할 때는 VS Code 채팅 패널이 아니라 에디터의 내장 터미널에서 claude를 실행하면 됩니다.
출시 첫 주라 알려진 문제도 있습니다. 2026년 10월 7일 기준으로 Claude Code 저장소에 열려 있는 이슈 가운데 쓰기 전에 알아 둘 만한 것은 다음과 같습니다.
- VS Code 확장이 mod 화면을 그리지 않음: 엔진은 vscode 화면을 받아들이는데 창, 띠 영역, 상태줄, 토스트가 나타나지 않는다는 보고입니다(#99045, #99423).
- Bash에
tool.call훅을 걸면 worktree 격리가 깨짐:isolation: "worktree"로 띄운 에이전트의 모든 Bash 호출이 거부된다는 보고로, 출시 전인 9월 6일부터 열려 있습니다(#92533). 위험 명령 가드 mod를 쓰면서 서브에이전트를 worktree로 돌린다면 확인이 필요합니다. validate와test가 TypeScript 타입을 검사하지 않음: 타입 오류가 있어도 통과하므로, 타입 검사는 생성된tsconfig.json으로tsc를 따로 돌려야 합니다(#99771).
요소도 환경에 따라 다릅니다. 색 칸 격자를 그리는 Raster와 PNG를 그리는 Image는 터미널 전용이고, Svg는 데스크톱 전용입니다. 창은 터미널이 충분히 넓은 전체 화면일 때만 사이드바로 붙고, 그렇지 않으면 프롬프트 위의 틀 안에 나타납니다(Mods reference).
이 글의 자료를 고른 방법
이 글은 2026년 10월 7일에 확인한 자료로 썼습니다. 구조와 API, 한도, 보안 설명은 code.claude.com의 Mods 문서 10개 페이지(개요, 만들기, 레퍼런스, 이벤트, 인터페이스, API, 조직 관리, 테스트, 문제 해결, 갤러리)와 변경 기록을 원문으로 읽고 옮겼습니다. 레퍼런스 문서는 2.1.290 기준이라고 적혀 있고 필자의 설치본은 2.1.292이므로, 버전에 따라 이벤트와 메서드가 다를 수 있습니다.
활용 1~3의 샘플은 Anthropic의 claude-code-playground 저장소(커밋 569c528, 2026-10-01)를 받아 코드와 README를 읽고 validate를 직접 돌렸습니다. 활용 4~10의 코드는 공식 문서의 예제이고, 필자가 실행한 것은 앞 절의 first-mod와 그 테스트, 그리고 claude-code-ko-ui의 validate입니다. 공개 mod의 비율은 커뮤니티 카탈로그의 원본 JSON을 내려받아 필자가 다시 셌고, 알려진 문제는 GitHub 이슈를 직접 열어 상태를 확인했습니다.
국내 자료는 네이버 블로그, 티스토리, 긱뉴스, 국내 매체에서 찾았습니다. 출시 일주일 동안 기사 4건과 블로그, 커뮤니티 글 30건 안팎이 나왔는데, 대부분 공식 문서를 요약한 글이어서 본문에는 직접 만들어 본 경험담과 한국 사용자에게 해당하는 내용(용어 혼동, VS Code와 WSL에서 보이지 않는 문제, 한국어 UI mod)만 출처와 함께 옮겼습니다. 최근 30일의 Hacker News, dev.to, YouTube, X 반응도 따로 모았지만, 공식 문서보다 새로운 사실이 적어 본문에 직접 인용하지는 않았습니다. 본문 이미지는 필자가 만든 그림 3개와 섬네일을 빼면 Anthropic의 공식 문서와 샘플 저장소(Apache-2.0)의 원본이고, 캡션에 출처를 달았습니다.
필자의 한계. 필자는 macOS 터미널에서만 확인했고 데스크톱 앱과 Windows는 시험하지 않았습니다. 샘플 mod는 validate와 코드 읽기로 검토했고 실제 세션에서 오래 쓰지는 않았으므로, 성능과 안정성에 관한 판단은 이 글에 넣지 않았습니다.
자주 묻는 질문
mod를 쓰려면 Node.js나 빌드 도구가 필요한가요?
필요 없습니다. Claude Code가 .js, .mjs, .ts, .tsx 같은 훅 모듈을 직접 읽으므로 번들러나 빌드 단계가 없습니다. 다만 훅 모듈 안에는 Node.js API와 setTimeout 같은 타이머 전역이 없고, 파일과 프로세스, 네트워크는 모두 $.fs, $.process, $.http로만 닿습니다. 타입 검사가 필요하면 mod를 로드할 때 .claude-plugin/types/에 생기는 .d.ts와 tsconfig.json을 그대로 쓰면 됩니다.
기존 설정 훅을 mod로 옮겨야 하나요?
옮길 필요는 없습니다. 설정 훅은 폐기되지 않았고 mod와 나란히 돕니다. 이미 잘 도는 셸 스크립트 훅이라면 그대로 두고, 화면에 무언가를 보여 주거나 여러 이벤트에서 상태를 나눠 써야 할 때 mod를 더하면 됩니다. mod에서 classic.Stop처럼 설정 훅 이벤트를 받을 수도 있어서, 두 방식을 섞어 쓰기 쉽습니다.
설치한 mod를 잠깐 끄려면 어떻게 하나요?
한 mod만 끄려면 /plugin의 Installed 탭에서 그 플러그인을 비활성화합니다. 한 세션 동안 모두 끄려면 claude --safe-mode로 시작하고, 모든 세션에서 끄려면 ~/.claude/settings.json에 "disableAllHooks": true를 둡니다. 내장 mod는 이 설정들로 꺼지지 않으므로 /plugin에서 개별로 끕니다(가드인 sec-default는 사용자가 끌 수 없습니다). 조기 접근 때 쓰던 CLAUDE_CODE_ENABLE_FUNCTION_HOOKS는 2.1.287부터 무시되므로 지워도 됩니다.
mod가 아무것도 하지 않으면 어디부터 보나요?
/plugin을 열어 탭 아래 흐린 줄에 1 mod active · 이름처럼 mod가 보이는지 확인합니다. 없으면 버전(터미널 2.1.287 이상), 작업 폴더의 신뢰 프롬프트 수락 여부, --safe-mode나 disableAllHooks 설정을 차례로 봅니다. 로드는 됐는데 반응이 없으면 claude plugin validate의 hooks: 줄에 의도한 이벤트가 있는지 보세요. 이벤트 이름 오타는 "tool.calls" is not an event 같은 오류로 나옵니다(Troubleshoot a mod).
마치며
Claude Code Mods를 한 줄로 줄이면 Claude Code 안쪽의 이벤트에 미들웨어 함수를 꽂는 플러그인입니다. 파일 세 개와 register(on) 하나로 시작하고, 훅은 $, e, next로 관찰하거나 고치거나 대신 답합니다. 그 위에 컨텍스트 게이지, 위험 명령 보류, 편집 다시 보기 같은 화면을 얹을 수도 있고, 브랜치별 규칙과 프롬프트 맥락, 즉시 명령과 사용자 도구, 작은 모델 호출과 백그라운드 감시, 조직 정책까지 같은 구조로 만들 수 있습니다.
처음 해 볼 일은 공식 샘플 하나를 claude --plugin-dir로 띄워 보는 것입니다. 직접 만든 mod라면 공개하기 전에 claude plugin validate로 calls: 줄과 .catch 경고를 꼭 확인하세요. 이벤트와 API가 버전마다 늘고 있어서, 큰 변화가 생기면 이 글을 갱신하겠습니다. 최신 모델에게 일을 통째로 맡기는 방법은 Claude Opus 5.5 잘 쓰는 법에서 이어서 읽을 수 있습니다.
출처
- Claude Code changelog: code.claude.com/docs/en/changelog
- Customize Claude Code with mods in TypeScript, claude.com, 2026-10-01: claude.com/blog/claude-code-mods
- Mods overview 한국어판: code.claude.com/docs/ko/plugins/mods/overview
- Mods overview: code.claude.com/docs/en/plugins/mods/overview
- 부컴, 2026-10-03: blog.naver.com/bucom_/224430503033
- Mods overview: code.claude.com/docs/en/plugins/mods/overview
- Manage mods for your organization: code.claude.com/docs/en/plugins/mods/admin
- Create a mod: code.claude.com/docs/en/plugins/mods/create
- Mods reference: code.claude.com/docs/en/plugins/mods/reference
- Anthropic, Draw in the interface with a mod: code.claude.com/docs/en/plugins/mods/interface
- Anthropic, React to events: code.claude.com/docs/en/plugins/mods/events
- Mods reference: code.claude.com/docs/en/plugins/mods/reference
- Create a mod: code.claude.com/docs/en/plugins/mods/create
- React to events: code.claude.com/docs/en/plugins/mods/events
- anthropics/claude-code-playground: github.com/anthropics/claude-code-playground/tree/main/claude-code/mods
- Create a mod: code.claude.com/docs/en/plugins/mods/create
- Mods reference: code.claude.com/docs/en/plugins/mods/reference
- Anthropic, claude-code-playground token-weather: github.com/anthropics/claude-code-playground/tree/main/claude-code/mods…
- Getting started with Claude Code mods, claude.dev, 2026-10-01: claude.dev/blog/getting-started-with-claude-code-mods
- Anthropic, claude-code-playground blast-radius: github.com/anthropics/claude-code-playground/tree/main/claude-code/mods…
- React to events: code.claude.com/docs/en/plugins/mods/events
- Anthropic, claude-code-playground replay-theater: github.com/anthropics/claude-code-playground/tree/main/claude-code/mods…
- React to events: code.claude.com/docs/en/plugins/mods/events
- React to events: code.claude.com/docs/en/plugins/mods/events
- Use the mods API: code.claude.com/docs/en/plugins/mods/api
- Use the mods API: code.claude.com/docs/en/plugins/mods/api
- Use the mods API: code.claude.com/docs/en/plugins/mods/api
- Use the mods API: code.claude.com/docs/en/plugins/mods/api
- Manage mods for your organization: code.claude.com/docs/en/plugins/mods/admin
- claude-code-ko-ui: github.com/moduvoice/claude-code-ko-ui
- smooth-stream: news.hada.io/topic?id=34799
- devbrothers-mods: github.com/devbrother2024/devbrothers-mods
- 피프티바이브, 2026-10-05: blog.naver.com/coredxi/224432165449
- Mods overview: code.claude.com/docs/en/plugins/mods/overview
- Manage mods for your organization: code.claude.com/docs/en/plugins/mods/admin
- karanb192/awesome-claude-code-mods: github.com/karanb192/awesome-claude-code-mods
- 토큰포스트, 2026-10-02: tokenpost.kr/news/ai/417272
- Mods overview: code.claude.com/docs/en/plugins/mods/overview
- AI차림, 2026-10-05: blog.naver.com/leejiilab_tv/224431702662
- 똥믈리에, 2026-10-04: blog.naver.com/bsu98089/224430730003
- 스쿱노트, 2026-10-03: blog.naver.com/scoopnote/224430181344
- #99045: github.com/anthropics/claude-code/issues/99045
- #99423: github.com/anthropics/claude-code/issues/99423
- #92533: github.com/anthropics/claude-code/issues/92533
- #99771: github.com/anthropics/claude-code/issues/99771
- Mods reference: code.claude.com/docs/en/plugins/mods/reference
- Troubleshoot a mod: code.claude.com/docs/en/plugins/mods/troubleshoot
글쓴이
주홍철은 네이버 출신 개발자이자 AI 핀테크 스타트업 어비스(AVISS)의 대표입니다. 경제·증시 분석 AI, AI 에이전트, 데이터 파이프라인을 직접 설계하고 개발하며, 『면접을 위한 CS 전공지식 노트』와 『클로드 코드 제대로 시작하기』(길벗)를 썼습니다. 회사 소개는 어비스 홈페이지에, 다른 글은 어비스 블로그에 있으며, 글에 대한 정정 요청이나 문의는 [email protected]으로 보내 주세요.