Devlery
Blog/Anthropic

Claude Code 안에서 실행되는 모드 공개, 도구 승인까지 바꾸는데 샌드박스는 없음

Anthropic이 10월 1일 Claude Code v2.1.287에 Claude Mods를 추가했습니다. 플러그인이 Claude Code 프로세스 안에서 화면을 다시 그리고 도구 호출을 붙잡거나 대신 승인합니다. 샌드박스는 없고 환경변수와 API 키를 읽을 수 있으며 기본값은 켜짐입니다.

Claude Code 안에서 실행되는 모드 공개, 도구 승인까지 바꾸는데 샌드박스는 없음
AI 요약
  • Claude Code v2.1.287에 모드 추가, 플러그인이 화면과 도구 호출을 바꿉니다.
  • 모드는 샌드박스 밖에서 돌고 환경변수와 API 키를 읽습니다.
  • 기본값은 켜짐이고, 설치 전 claude plugin validate로 권한을 봅니다.

Anthropic이 2026년 10월 1일 Claude Code v2.1.287을 내면서 Claude Mods를 추가했습니다. 모드는 Claude Code 프로그램 안에서 같이 돌아가는 남의 코드입니다. 지금까지 플러그인이 할 수 있던 일은 Claude에게 지시문을 더 주거나(스킬), 도구 호출 전후에 셸 스크립트를 한 번 돌리는 것(settings hook)까지였습니다. 모드는 Claude Code가 화면을 그리는 순간, 도구를 부르는 순간, 모델에 요청을 보내는 순간마다 자기 함수를 끼워 넣습니다.

릴리스 노트의 해당 줄은 한 문장입니다. "Added Claude Mods: plugins may now modify deeper behavior." 같은 날 올라온 공식 문서 열 쪽이 그 "deeper"가 어디까지인지를 적었습니다. 그 목록에는 모드가 환경변수와 설정 파일에 둔 API 키를 읽는다는 항목도 들어 있습니다. 샌드박스는 없습니다.

설정 파일 밖에서 돌던 확장이 안으로 들어왔다

달라진 것은 확장 코드가 실행되는 위치입니다. settings hook은 Claude Code가 자식 프로세스로 띄우는 셸 명령이고, MCP 서버는 바깥에서 도는 별도 프로세스이며, 스킬은 Claude가 읽는 Markdown 파일입니다. 셋 다 Claude Code 바깥에 있어서 화면을 건드릴 수 없습니다. 모드의 함수는 Claude Code 프로세스 자체에서 호출됩니다.

공식 문서가 넷을 직접 비교한 표입니다.

항목모드settings hook스킬MCP 서버
실행 위치Claude Code 프로세스 안자식 셸 프로세스Claude가 읽는 파일외부 프로세스·서비스
바꿀 수 있는 것도구 호출, 프롬프트, 명령, 턴, 화면호출 진행 여부, 인자와 결과Claude가 아는 것Claude가 쓰는 도구
화면을 그리나그린다못 그린다못 그린다못 그린다
작성 언어JavaScript·TypeScript셸 스크립트 + settings.jsonMarkdown아무 언어

문서가 열거한 모드의 능력은 다섯 가지입니다. 대화 옆 패널(공식 문서 표기로 pane)이나 프롬프트 위 띠(band) 그리기, Claude Code가 그리던 도구 호출 줄·스피너·질문 대화상자를 자기 것으로 바꾸기, 도구 호출을 붙잡아 사용자에게 묻거나 도구를 돌리지 않고 대신 답하기, Claude 턴 없이 즉시 실행되는 /명령 등록, 훅끼리 변수 공유.

문서에 실린 가장 짧은 예제가 스피너를 바꿉니다. tool.call 훅이 호출 횟수를 세고, ui.render 훅이 Claude Code의 스피너 뒤에 그 숫자를 붙입니다.

let calls = 0

export function register(on) {
  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 + '…' } })
  })
}

Claude Code 터미널 화면에서 스피너가 Thinking · tool calls: 3…으로 표시된 모습

열세 줄짜리 파일이 Claude Code의 기본 화면을 덮어썼습니다. Anthropic은 자기 내장 기능도 같은 방식으로 다시 만들었습니다. /diff 패널, AGENTS.md를 프로젝트 지시문으로 읽는 로더, 분석 기록을 보내는 텔레메트리가 모두 지금은 모드이고, 그중 diff·agents-md·sec-default·telemetry 네 개는 claude-code 저장소의 mods 디렉터리에 소스가 공개돼 있습니다. AGENTS.md 지원이 들어온 것이 9월인데, 그 기능이 이제 플러그인 하나로 분리돼 사용자가 /plugin에서 끌 수 있습니다.

도구 호출 쪽 예제는 더 직접적입니다. 강제 푸시를 막는 훅이 여섯 줄입니다.

on('tool.call', { tool: 'Bash' }, async ($, e, next) => {
  if (/git push .*--force/.test(e.command)) {
    return { deny: 'Force pushes are not allowed in this repository. Push to a new branch instead.' }
  }
  return next(e)
})

여기서 next를 부르지 않으면 명령이 돌지 않고 권한 프롬프트도 뜨지 않습니다. 문서 원문이 그렇게 적었습니다. "the command doesn't run and no permission prompt appears, because the hook never calls next." 거부 문구는 Claude가 도구 결과로 읽습니다.

모드가 닿을 수 있는 곳

문서는 모드의 권한을 여섯 줄로 열거합니다. 보안 연구자가 역설계해서 밝혀낸 목록이 아니라, Anthropic이 설치 안내서 본문에 직접 적어 둔 목록입니다.

내 계정으로 기계에서 행동
내 계정이 닿는 모든 파일 읽기·쓰기, 프로그램 실행, 네트워크 요청
비밀 읽기
환경변수와 설정 파일, 거기 둔 API 키 포함
세션 보기
내가 보낸 모든 프롬프트와 Claude의 모든 도구 호출
세션 바꾸기
프롬프트·도구 호출 재작성, 내가 친 것처럼 프롬프트 제출, 내 다른 세션에 메시지 전송
묻지 않고 승인
사용자에게 묻기 전에 도구 호출을 승인
내 사용량 쓰기
내 요금제나 API 키로 모델 호출

샌드박스를 켜 둔 사람도 예외가 아닙니다. 문서는 "Mods aren't sandboxed"라고 적고, 샌드박싱은 Claude가 돌리는 Bash 명령만 격리하므로 모드가 띄운 프로세스는 그 밖에서 돈다고 덧붙였습니다.

조직이 걸어 둔 권한 규칙은 모드를 절반만 막습니다. 관리 설정에 넣은 deny 규칙과 관리 PreToolUse 훅이 모드보다 우선하긴 하는데, 그 우선순위는 Claude의 도구 호출에만 적용됩니다. 문서가 든 예가 명확합니다. Read(.env)를 거부해 뒀어도 모드는 $.fs.read로 그 파일을 읽거나, 그 파일을 읽는 프로그램을 띄울 수 있습니다. 모드 자신의 파일·프로세스 호출은 Claude의 도구 호출이 아니기 때문입니다.

모드가 못 하는 일은 하나 명시돼 있습니다. 권한 프롬프트 자체는 다시 그릴 수 없습니다. 화면 대부분을 바꿔도 승인을 묻는 창에 보이는 내용은 건드리지 못합니다.

설치 전 보는 두 줄, 조직이 막는 네 가지 설정

플러그인을 돌려보지 않고도 무엇을 하는지 볼 수 있습니다. 저장소를 받아 둔 상태에서 셸에 한 줄이면 됩니다.

claude plugin validate ./some-mod

출력에서 볼 곳은 두 줄입니다.

  ❯ ./register.js hooks: session.start, tool.call, ui.render{component=Pane}
  ❯ ./register.js calls: $.fs.read, $.http.fetch, $.store.set, $.ui.open

hooks:는 이 모드가 받는 이벤트이고, calls:는 코드가 호출하는 모드 API 메서드입니다. 모드는 파일·프로세스·네트워크에 닿을 다른 경로가 없어서 이 줄에 다 드러납니다. 문서는 이 명령이 읽지 못하는 방식으로 API를 쓰는 모드는 Claude Code가 아예 로드하지 않는다고 적었습니다.

문서가 특히 보라고 지목한 호출입니다.

호출뜻
$.env.get, $.settings.read환경변수·설정 읽기. API 키가 들어 있을 수 있고, env reads: 줄에 변수명이 나옵니다
$.env.setClaude Code와 이후 시작하는 모든 명령·MCP 서버의 환경변수 변경
$.process.run, $.process.spawn내 권한으로 프로그램 실행
$.http.fetch네트워크 요청
$.prompt.submit내가 직접 쓴 말처럼 프롬프트 제출
$.model.complete내 요금제·API 키로 모델 호출

조직은 네 가지 설정으로 범위를 좁힙니다. allowManagedModsOnly는 사용자가 설치한 모드만 막고 settings hook과 상태 표시줄은 살려 둡니다. allowManagedHooksOnly는 사용자 설정 파일의 훅까지 막습니다. disableAllHooks는 관리자 자신의 PreToolUse 훅까지 전부 끕니다. disableSideloadFlags는 --plugin-dir와 --plugin-url을 시작 단계에서 거부합니다.

기본값은 통제가 거의 없는 쪽입니다. 관리 설정을 두지 않은 조직에서는 플러그인 설정이 허용하는 마켓플레이스 어디서든 모드를 설치할 수 있습니다. 내장 가드 sec-default@builtin이 사용자 모드보다 먼저 로드되긴 하지만, 가드가 지키는 범위는 조직이 관리하는 것(관리 훅, 시스템 프롬프트, 관리 CLAUDE.md, 관리 MCP 서버의 도구 설명)으로 한정됩니다.

가드가 걸려 있어도 사용자 모드는 파일을 읽고 쓰고, 프로세스를 띄우고, 네트워크를 쓰고, 도구 호출을 거부하거나 승인합니다. 그 가드조차 기계에 관리 설정이 있거나 사용자가 Team·Enterprise 요금제로 로그인했을 때만 로드됩니다. API 키나 Bedrock·Vertex·Foundry로 인증하는 개인 사용자는 관리 설정이 깔린 기계에서만 가드를 받습니다.

지금 쓸 수 있나

버전 하나만 맞으면 됩니다. 요금제 구분도 지역 제한도 없습니다.

항목조건
대상Claude Code 사용자 전원. 요금제 구분 없음
가격추가 비용 없음. 모드가 $.model.complete를 쓰면 내 요금제·API 키 사용량으로 청구
필요 버전v2.1.287 이상, 기본값 켜짐. claude --version으로 확인
릴리스 채널autoUpdatesChannel 기본값 latest는 바로 받음. stable은 약 1주 지연
한국 사용가능. 지역 제한 없고 한국어 공식 문서도 함께 올라옴
조직 제약관리자가 관리 설정으로 차단 가능. 막힌 이유는 claude --debug 로그에 남음

채널 차이는 실제로 벌어져 있습니다. 2026년 10월 3일 06시 10분(KST) 기준 npm dist-tag를 조회하면 latest는 2.1.288인데 stable은 2.1.285입니다. 설정에서 autoUpdatesChannel을 stable로 바꿔 둔 사람과, 관리 설정으로 그 채널을 강제받는 조직 구성원은 아직 모드가 없는 버전을 쓰고 있습니다. Homebrew로 깔았다면 cask 이름이 채널을 정합니다. claude-code는 stable, claude-code@latest는 latest입니다.

내장 모드 중 cc-plugin-you-should-know만 조건이 다릅니다. 긴 작업 중 놓칠 만한 것을 사이드 에이전트가 프롬프트 위에 알려주는 기능인데, 기본 비활성이고 1차 세션에서 텔레메트리가 켜져 있어야 하며 조직에서 사용 가능할 때만 목록에 나옵니다. 켜는 명령은 /plugin enable cc-plugin-you-should-know@builtin입니다.

Claude Code를 이미 쓰고 있다면 오늘 할 일은 설치가 아니라 점검입니다. /plugin을 열어 탭 아래 흐린 줄에 적힌 활성 모드 수와 이름을 확인하면, 이번 업데이트로 내 세션에서 무엇이 돌기 시작했는지 바로 보입니다. 그다음에 새 모드를 넣을 생각이라면 저장소를 받아 claude plugin validate부터 돌리고 calls: 줄에 $.env.get이나 $.http.fetch가 같이 있는지 봅니다. 둘이 한 모드에 함께 있으면, 그 코드는 내 API 키를 읽고 바깥으로 보낼 수 있는 상태입니다.