본문 바로가기

Coding, Testing, Challenge

Claude Code Mods란? 스피너에 숫자 하나 띄워 보고 알게 된 기존 기능과의 차이

Claude Mods 연재 01편 대표 이미지

Claude Code 2.1.287부터 Mod라는 것이 생겼습니다. 이름만 보면 게임 모드 같은데, 실제로 해 보니 Claude Code 화면과 동작에 직접 손을 대는 기능이었습니다.

설명을 읽는 것보다 한 번 띄워 보는 쪽이 빨랐습니다. 공식 문서에 나오는 가장 작은 예제를 그대로 올려 보고, 화면이 어떻게 바뀌는지부터 보겠습니다.

실습 환경: Windows 11, Claude Code 2.1.296, 2026-10-11 확인. 화면은 개인 설정(user settings)을 싣지 않은 깨끗한 상태로 찍었습니다.

Mod를 한 줄로 말하면

공식 문서는 Mod를 "Claude Code가 어떻게 보이고 어떻게 동작하는지 바꾸는 플러그인"이라고 설명합니다.

조금 풀면 이렇습니다. Claude Code 안에서는 쉬지 않고 일이 생깁니다. Claude가 파일을 읽으려 하고, 내가 프롬프트를 보내고, 화면 아래 스피너가 다시 그려집니다. Mod는 이런 일(이벤트)이 생길 때마다 Claude Code가 불러 주는 JavaScript 또는 TypeScript 함수입니다. 그리고 그 함수는 Claude Code 프로세스 안에서 돕니다.

"안에서 돈다"는 점이 다른 기능들과 갈리는 지점입니다. 이 얘기는 뒤에서 다시 하겠습니다.

직접 띄워 본 결과: 스피너 옆에 숫자가 생겼다

연습용으로 아주 작은 할 일 목록 프로젝트(todo-cli)를 만들고, Claude에게 같은 부탁을 두 번 했습니다. "파일 목록을 보고 README와 package.json을 읽어 줘. 아무것도 바꾸지 말고."

먼저 Mod 없이 실행한 화면입니다. Claude가 일하는 동안 아래쪽에 익숙한 스피너가 돕니다.

Mod 없이 실행한 Claude Code, 스피너에는 작업 문구와 경과 시간만 보인다
Mod 없이 실행. 스피너에는 작업 문구와 경과 시간만 나온다

다음은 공식 예제 Mod(first-mod)를 올리고 똑같이 부탁한 화면입니다.

first-mod를 올린 Claude Code, 스피너에 tool calls: 3 이 붙었다
first-mod를 올린 뒤. 스피너 글자 뒤에 「tool calls: 3」이 붙었다

스피너 문구 뒤에 tool calls: 3이 붙었습니다. Claude가 이번 작업에서 도구를 세 번 썼다는 뜻입니다. 파일 목록을 한 번 보고, 파일 두 개를 읽었으니 맞는 숫자입니다.

별것 아닌 숫자처럼 보여도, 예전에는 이 자리에 내가 무언가를 끼워 넣을 방법이 없었습니다. 상태줄(status line)은 화면 맨 아래 한 줄을 스크립트 출력으로 채우는 기능이라 스피너를 건드리지 못합니다.

이 Mod는 파일 세 개, 코드 20줄이다

Mod는 플러그인 폴더 하나입니다. 가장 작은 형태는 이렇습니다.

first-mod/
├── .claude-plugin/
│   └── plugin.json      ← 이름·버전·설명
└── hooks/
    ├── hooks.json       ← 코드 파일 위치
    └── register.js      ← 실제 코드

hooks.json에는 { "modules": ["./register.js"] } 한 줄만 있으면 됩니다. 실제 동작은 register.js에 들어 있습니다. 공식 문서 예제 그대로입니다.

let calls = 0

export function register(on) {
  // Claude가 도구를 쓰려 할 때마다
  on('tool.call', async ($, e, next) => {
    calls += 1
    $.ui.invalidate('ui.render')   // 화면을 다시 그려 달라고 요청
    return next(e)                  // 도구는 원래대로 실행
  })

  // 스피너를 그릴 때마다
  on('ui.render', { component: 'Spinner' }, async ($, e, next) => {
    return next({ ...e, props: { ...e.props, suffix: ' · tool calls: ' + calls + '…' } })
  })
}

훅이 두 개입니다. tool.call 훅은 숫자를 하나 올리고 도구를 그대로 보냅니다. ui.render 훅은 스피너를 그리기 직전에 끼어들어 글자 뒤에 숫자를 붙입니다. 두 훅은 맨 위의 calls 변수를 같이 씁니다. 한 훅이 센 것을 다른 훅이 보여 주는 구조입니다.

저는 이 폴더를 만든 뒤 claude --plugin-dir D:\lab\mods\first-mod로 실행했습니다. --plugin-dir는 설치하지 않고 그 세션에만 플러그인을 올리는 옵션이라, 시험해 보기에 부담이 없습니다.

Mod가 이벤트를 받으면 할 수 있는 일은 세 가지

이벤트가 생기면 Mod의 훅이 먼저 받아 지켜보기·바꾸기·대신 답하기 중 하나를 한 뒤 Claude Code가 이어서 동작한다
Claude Code는 무언가 하기 직전에 Mod의 훅을 먼저 부른다

훅의 모양은 모두 ($, e, next)입니다. e는 지금 일어난 일이고, next(e)를 부르면 원래 하려던 동작이 이어집니다. 그래서 훅이 고를 수 있는 길은 셋입니다.

  • 지켜보기: 기록만 하고 next(e)로 그대로 보냅니다. 위 예제의 tool.call 훅이 이렇습니다.
  • 바꾸기: e를 고쳐서 next에 넘깁니다. 스피너에 글자를 붙인 ui.render 훅이 이쪽입니다.
  • 대신 답하기: next를 부르지 않고 직접 결과를 돌려줍니다. 위험한 명령을 막는 Mod가 이런 식으로 만들어집니다.

기존 Claude Code와 무엇이 달라졌나

Claude Code에는 원래도 손댈 수 있는 곳이 많았습니다. 설정 파일의 훅(hooks), 스킬(Skill), 상태줄, MCP 서버. 공식 문서는 이것들이 모두 Claude Code 바깥에서 일한다고 정리합니다. 스크립트를 돌리거나, Claude에게 글이나 도구를 건네는 방식입니다.

Mod는 안에서 돌기 때문에 바깥 도구로는 못 하던 일을 할 수 있습니다. 문서에 나온 것을 추리면 이렇습니다.

할 수 있는 일예
직접 쓰는 화면 만들기대화 옆 패널, 프롬프트 위 띠, 버튼·입력칸
Claude Code가 그리는 화면 고치기도구 호출 줄, 스피너, 질문 창
도구 호출·요청에 끼어들기실행 전에 나에게 묻기, 실행 없이 답하기
Claude 턴 없이 도는 명령Claude가 일하는 중에도 바로 실행되는 /명령
훅끼리 데이터 나누기위 예제처럼 세고, 보여 주기

참고로 Claude Code의 /diff 화면도 Mod로 만들어져 있습니다. 내장 Mod는 다음 편에서 /plugin 화면으로 직접 확인합니다.

먼저 알고 시작할 위험

안에서 돈다는 것은 그만큼 많이 만질 수 있다는 뜻이기도 합니다. 공식 문서가 경고하는 내용을 옮기면, Mod는 내 권한으로 실행됩니다. 파일을 읽고 쓰고, 프로그램을 띄우고, 네트워크 요청을 보낼 수 있습니다. 환경변수에 넣어 둔 API 키도 읽을 수 있고, 내가 보내는 프롬프트와 Claude의 도구 호출도 모두 봅니다.

샌드박스 안에 있지도 않습니다. 샌드박스를 켜도 그건 Claude가 실행하는 Bash 명령에만 걸립니다.

그래서 남이 만든 Mod는 믿을 수 있는 곳에서만 받고, 설치 전에 claude plugin validate <폴더>로 그 Mod가 어떤 이벤트를 잡고 무엇을 호출하는지 먼저 보는 습관을 들이는 게 좋습니다. 이 명령의 출력은 3편에서 자세히 봅니다.

다음 편

오늘은 Mod가 무엇이고 기존 기능과 어디가 다른지를 화면 하나로 확인했습니다. 다음 편에서는 Mod를 쓰기 전에 확인할 것, 즉 버전과 /plugin 화면, 내장 Mod 목록을 순서대로 보겠습니다.

참고한 공식 문서: Mods overview (code.claude.com)

그러면 오늘도 모두 스테이블 하세요.