SpyBara
Go Premium

plugins/mods/admin.md 2026-09-30 23:00 UTC to 2026-10-01 21:02 UTC

This page contains 375 additions and 0 deletions.

2026
Thu 1 21:02

조직의 mod 관리

관리되는 설정으로 Claude Code mod를 제어합니다: 사용자가 설치한 mod 중지, 자신의 mod만 허용, mod가 수행할 수 있는 작업 검토, 자신의 mod로 정책 적용.

mod는 Claude Code 내에서 실행되는 플러그인으로, 이를 설치한 사용자의 권한으로 코드를 실행합니다. Mod는 샌드박스 처리되지 않습니다. 관리되는 설정을 통해 사용자의 머신에서 mod가 실행되는지 여부, 어떤 mod가 실행되는지, 그리고 어떤 순서로 실행되는지를 결정할 수 있습니다. 또한 다른 mod가 수행하는 작업을 감시하거나 거부하는 자신의 mod를 설치할 수 있습니다.

이 페이지는 파일, MDM 또는 claude.ai 관리자 콘솔을 통해 Claude Code의 관리되는 설정을 배포하는 담당자를 위한 것입니다. Mod는 Claude Code v2.1.287 이상에서 기본적으로 활성화되어 있습니다. 수행하려는 작업과 일치하는 섹션부터 시작하세요:

사용자가 설치한 mod가 로드되지 않도록 중지

사용자가 가져오는 모든 mod가 로드되지 않도록 하려면 기본 제공 가드인 정책 mod에서 allowManagedModsOnly 옵션을 설정하세요. Claude Code는 사용자가 설치한 모든 mod 앞에 이 mod를 로드합니다. 옵션은 pluginConfigs 아래의 관리되는 설정에 cc-plugin-sec-default@builtin으로 키가 지정되어 있습니다:

{
  "pluginConfigs": {
    "cc-plugin-sec-default@builtin": {
      "options": {
        "allowManagedModsOnly": true
      }
    }
  }
}

관리되는 설정에서 옵션을 설정하면:

  • 사용자가 가져오는 mod는 로드되지 않습니다: 사용자가 설치한 플러그인의 mod, --plugin-dir로 로드된 mod, 세션 중에 Claude가 작성한 mod를 포함합니다
  • 조직의 mod는 계속 로드됩니다: 조직의 것으로 간주되는 mod는 확인되지 않습니다. 다른 모든 mod는 사용자의 것으로 간주되며 로드되지 않습니다. 여기에는 GitHub 또는 다른 원격 마켓플레이스에서 활성화하는 플러그인의 mod와 조직이 claude.ai의 구성원을 위해 활성화하는 mod가 포함됩니다. 조직의 것으로 간주되는 mod가 없으면 설치된 mod는 로드되지 않습니다.
  • 사용자는 이를 실행 취소할 수 없습니다: 가드는 관리되는 설정에서만 옵션을 읽으므로 사용자, 프로젝트 또는 로컬 설정 파일의 동일한 항목이나 --settings로 전달된 파일의 항목은 아무것도 변경하지 않습니다
  • 파일 또는 MDM 정책은 모든 공급자를 포함합니다: 옵션을 파일로 또는 MDM을 통해 전달하면 Amazon Bedrock, Google Cloud의 Agent Platform, Microsoft Foundry에서 동일한 방식으로 작동합니다. claude.ai 관리자 콘솔에서 전달하는 경우 플랫폼 가용성을 참조하세요
  • 사용자의 다른 사용자 정의는 계속 작동합니다: 설정 파일의 hook, 상태 줄, /goal은 영향을 받지 않습니다
  • 기본 제공 mod는 계속 실행됩니다: AGENTS.md 지원과 같이 Claude Code에 기본 제공되는 mod는 각각 자신의 스위치를 가집니다

사용자의 머신에서 옵션을 확인하려면 --plugin-dir과 mod를 보유한 디렉터리의 경로(예: claude --plugin-dir ./first-mod)를 사용하여 Claude Code를 시작하세요. mod의 hook은 실행되지 않으며 트랜스크립트와 디버그 로그에는 가드의 메시지가 있으며, 이는 mod의 이름과 allowManagedModsOnly를 나타냅니다. mod가 로드되면 정책이 적용 중인지 확인 및 옵션이 적용되는지 결정하는 규칙을 참조하세요.

초기 액세스 중에 CLAUDE_CODE_ENABLE_FUNCTION_HOOKS를 0으로 설정한 경우 이 옵션으로 바꾸세요. Claude Code v2.1.287 이상은 모든 값에서 변수를 무시하므로 0이 있으면 mod가 활성화된 상태로 유지됩니다.

기본적으로 어떤 일이 발생하는지 알기

자신의 mod 설정이 없으면 사용자가 얻는 것은 다음과 같습니다:

  • Mod가 활성화되어 있습니다. 사용자는 플러그인 설정이 허용하는 모든 마켓플레이스에서 mod를 포함하는 플러그인을 설치하거나 --plugin-dir을 사용하여 디렉터리에서 로드할 수 있습니다.

  • 기본 제공 가드가 먼저 실행됩니다. Claude Code는 sec-default@builtin이라는 기본 제공 mod를 사용자가 설치한 모든 mod 앞에 로드합니다. 사용자는 이를 끌 수 없습니다. /plugin과 디버그 로그는 이를 cc-plugin-sec-default로 나열합니다. 가드는 다음 중 하나가 참일 때 로드됩니다:

    • 머신에 관리되는 설정이 있습니다
    • 사용자가 Team 또는 Enterprise 플랜으로 Claude Code에 로그인했습니다

    API 키로 인증하거나 Amazon Bedrock, Google Cloud의 Agent Platform, Microsoft Foundry를 통해 인증하는 사용자는 관리되는 설정이 있는 머신에서만 가드를 받습니다.

  • 가드는 관리하는 것을 보호합니다. 사용자의 mod는 관리되는 hook이 받거나 결정하는 것, 시스템 프롬프트, 관리되는 CLAUDE.md 및 기타 관리되는 지침, 모든 mod가 설정으로 읽는 것, 관리되는 MCP 서버의 도구 및 설명을 변경할 수 없습니다.

  • 다른 모든 것은 허용됩니다. 가드는 다른 제한을 추가하지 않습니다. 사용자의 mod는 여전히 파일을 읽고 쓰고, 프로세스를 시작하고, 네트워크 요청을 하고, 도구 호출 및 프롬프트를 다시 쓰고, 도구 호출을 거부하고, 그렇지 않으면 프롬프트할 도구 호출을 승인하고, 모두 해당 사용자의 권한으로 인터페이스에 그릴 수 있습니다.

  • 거부 규칙 및 관리되는 hook이 우선합니다. 가드가 로드되는 곳에서 사용자의 mod는 deny 규칙이 거부하는 호출을 승인할 수 없으며, 어느 설정 파일이 규칙을 보유하든 상관없습니다. 관리되는 설정의 PreToolUse hook의 블록도 최종입니다. 둘 다 Claude의 도구 호출에 적용됩니다. 둘 다 mod의 자체 $.fs 및 $.process 호출에는 적용되지 않습니다: Read(.env)가 거부되면 mod는 여전히 $.fs.read로 해당 파일을 읽거나 그렇게 하는 프로그램을 시작할 수 있습니다. 이러한 호출을 제한하려면 mod가 로드되지 않도록 하거나 정책 mod에서 호출을 hook하세요.

  • 다른 권한 확인을 재정의할 수 있습니다. 도구 호출을 승인하는 사용자의 mod는 ask 규칙이 프롬프트할 호출이나 관리되는 설정 외부의 PreToolUse hook이 차단한 호출을 승인할 수 있습니다. 자동 모드에서 mod가 승인하는 호출은 분류기 확인 없이 실행됩니다.

가드의 소스는 Claude Code 저장소의 mods/sec-default 디렉터리에서 공개적으로 사용 가능합니다.

여전히 적용되는 제어 알기

Mod는 이미 있는 제어를 대체하지 않습니다:

  • 설정 hook은 계속 작동합니다. 설정 파일 및 플러그인의 hooks/hooks.json의 Command, HTTP, prompt, agent hook은 mod와 함께 이전과 같이 실행됩니다. 이에 대해 더 이상 사용되지 않는 것은 없습니다.
  • 거부 규칙은 가드가 로드되는 곳에서 우선합니다. 사용자의 mod는 deny 규칙이 거부하는 호출을 승인할 수 없습니다. allowModsToOverrideDenyRules를 설정하지 않는 한 말입니다.
  • 관리되는 hook이 먼저 실행됩니다. 관리되는 설정의 PreToolUse hook은 모든 mod가 도구 호출을 보기 전에 실행되며 해당 블록은 최종입니다. mod가 호출을 다시 쓰면 관리되는 hook이 다시 쓴 호출에서 다시 실행되므로 블록이 여전히 적용됩니다. 다른 설정 파일 및 플러그인의 PreToolUse hook은 마지막 mod 후에 실행되므로 자신의 결과를 도구 실행 대신 반환하는 mod는 이들이 실행되지 않도록 합니다. Mod가 실행되는 순서를 참조하세요.
  • 네트워크 정책은 $.http.fetch를 포함합니다. 조직이 웹 가져오기를 끄거나 세션에 대해 필수가 아닌 네트워크 트래픽이 꺼져 있으면 Claude Code는 mod가 $.http.fetch로 만드는 네트워크 요청을 거부합니다. 정책은 mod가 $.process.run으로 시작하는 프로그램을 포함하지 않습니다. 해당 프로그램은 사용자 자신의 액세스로 네트워크에 도달합니다.
  • 플러그인 제어는 mod를 포함합니다. Mod는 플러그인이므로 사용자가 설치할 수 있는 것을 제한하는 설정(예: strictKnownMarketplaces)은 설치 가능 여부를 결정합니다.
  • Mod는 권한 프롬프트를 변경할 수 없습니다. Mod는 Claude Code 인터페이스의 대부분을 다시 스타일링할 수 있지만 권한 프롬프트는 할 수 없으므로 프롬프트가 표시하는 것을 변경할 수 없습니다. Mod는 여전히 프롬프트가 나타나기 전에 도구 호출을 승인하거나 거부할 수 있습니다. 기본적으로 어떤 일이 발생하는지 알기에서 설명합니다.
  • 신뢰 프롬프트가 먼저 나타납니다. 사용자가 아직 신뢰하지 않은 디렉터리의 대화형 세션에서 신뢰 프롬프트에 답할 때까지 mod는 로드되지 않습니다.
  • --safe-mode는 설치된 mod를 끕니다. 자신의 mod도 포함합니다. claude --safe-mode로 세션을 시작하여 mod가 문제를 일으켰는지 확인하세요.

이러한 제어 중 어느 것도 mod를 샌드박스 처리하지 않습니다. 허용하는 mod는 사용자로 실행되며 파일, 프로세스, 네트워크에 대한 사용자의 액세스 권한이 있습니다.

Mod를 활성화된 상태로 유지할지 결정

Mod는 플러그인의 다른 부분보다 더 많은 작업을 할 수 있습니다. Claude Code 내부에서 실행되기 때문입니다. 모든 프롬프트와 도구 호출을 보고, 변경할 수 있으며, 권한 프롬프트가 나타나기 전에 도구 호출을 승인하거나 거부할 수 있습니다.

사용자가 mod로 로드할 수 있는 것은 이미 있는 플러그인 제어에 따라 달라집니다:

현재 플러그인 제어 사용자가 mod로 로드할 수 있는 것
없음 모든 마켓플레이스의 mod, --plugin-dir이 있는 모든 디렉터리, 또는 Claude가 세션 중에 작성하는 mod
마켓플레이스 허용 목록 허용하는 마켓플레이스의 mod 또는 --plugin-dir이 있는 모든 디렉터리. Claude가 작성하는 mod는 허용 목록이 skills-dir을 포함할 때만 로드됩니다.
마켓플레이스 허용 목록 및 disableSideloadFlags 허용하는 마켓플레이스의 mod

조직의 플러그인 관리는 플러그인이 로드되는 모든 방법과 각각을 제어하는 설정을 나열합니다.

사용자가 설치하기 전에 마켓플레이스의 mod를 확인하려면 mod가 할 수 있는 작업 검토를 참조하세요. 사용자의 mod를 그렇게 할 때까지 제외하려면 사용자가 설치한 mod가 로드되지 않도록 중지를 참조하세요.

mod가 할 수 있는 작업 검토

실행하지 않고도 mod가 할 수 있는 작업을 볼 수 있습니다. 셸에서 플러그인의 디렉터리에 대해 claude plugin validate를 실행하세요:

claude plugin validate ./some-mod

출력의 두 줄은 mod의 코드를 설명합니다:

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

hooks: 줄은 mod가 받는 이벤트를 나열합니다. calls: 줄은 코드가 호출하는 mod API 메서드를 나열합니다. mod API(mod의 코드에서 $로 작성됨)는 mod가 파일, 프로세스, 네트워크에 도달하는 방법입니다. Claude Code는 이 명령이 읽을 수 없는 방식으로 mod API를 사용하는 mod를 로드하기를 거부합니다.

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 다른 세션 또는 subagent의 Claude가 읽는 메시지를 보냅니다

hooks: 줄에서 tool.call 및 prompt.submit은 mod가 모든 도구 호출 및 모든 프롬프트를 보고 변경할 수 있음을 의미합니다. session.append는 mod가 저장되기 전에 대화의 각 행을 다시 쓸 수 있음을 의미합니다. ui.render{component=AskUserQuestion}는 mod가 Claude가 사용자에게 질문하는 데 사용하는 대화를 다시 그릴 수 있음을 의미합니다. tool.check는 mod가 권한 프롬프트가 나타나기 전에 도구 호출을 승인하거나 거부할 수 있음을 의미합니다. 기본적으로 어떤 일이 발생하는지 알기는 해당 답변보다 우선하는 규칙 및 hook을 나열합니다.

허용할 범위 선택

Mod 정책은 설치된 mod가 없는 것부터 사용자가 선택하는 모든 mod까지 다양하며, 자신의 mod가 다른 mod를 확인하고 각각은 몇 가지 관리되는 설정입니다. 원하는 정책을 첫 번째 열에서 찾고 두 번째 열이 이름을 지정하는 것을 설정하세요. 관리되는 설정 배포는 관리되는 설정이 있는 위치를 다룹니다.

원하는 것 설정
설치된 mod 없음, hook은 건드리지 않음 allowManagedModsOnly를 설정하고 자신의 mod를 배포하지 않음
설치된 mod 없음, hook도 없음. 관리되는 hook 포함 disableAllHooks를 true로 설정
조직의 mod만 가드의 allowManagedModsOnly 옵션을 설정하고 mod를 설치하여 조직의 것으로 간주되도록 함
승인하는 마켓플레이스의 모든 mod 마켓플레이스 제한을 유지하고 disableSideloadFlags를 true로 설정
모든 mod, 자신의 mod가 다른 mod를 확인 mod를 설치하고 prependPlugins에서 sec-default@builtin과 함께 나열

각 설정이 하는 작업:

  • allowManagedModsOnly: 기본 제공 가드의 옵션입니다. 사용자의 자체 mod는 로드되지 않으며 설정 hook, 상태 줄, /goal은 계속 작동합니다. 사용자가 설치한 mod가 로드되지 않도록 중지는 포함하는 것을 나열합니다.
  • allowManagedHooksOnly: 더 넓은 설정입니다. 조직의 mod 및 Claude Code에 기본 제공되는 mod만 로드됩니다. 사용자가 자신이 설치한 mod는 로드되지 않습니다. 설정은 또한 사용자의 자체 설정 파일의 hook을 차단합니다. 설정하기 전에 allowManagedHooksOnly 아래에서 실행되는 것을 읽으세요.
  • disableAllHooks: 가장 넓은 설정입니다. 관리되는 설정에서 설치된 모든 플러그인의 mod(자신의 포함)를 중지하고 설정 파일의 모든 hook을 끕니다. 따라서 관리되는 설정의 PreToolUse hook은 더 이상 아무것도 차단하지 않습니다. 사용자 정의 상태 줄 및 /goal도 작동을 중지합니다. 설정하기 전에 disableAllHooks를 읽으세요.
  • disableSideloadFlags: 시작 시 --plugin-dir 및 --plugin-url을 거부하므로 아무도 디렉터리에서 mod를 로드하지 않으며 Claude가 세션 중에 작성하는 mod가 로드되지 않도록 합니다. 설정은 또한 --agents 및 --mcp-config를 거부합니다. 설정하기 전에 disableSideloadFlags를 읽으세요.

Claude Code에 기본 제공되는 mod(예: AGENTS.md 지원)는 이러한 설정의 영향을 받지 않습니다. 각각은 자신의 스위치를 가집니다.

mod가 로드되지 않은 사용자는 디버그 로그에서 이유를 찾습니다. 거부 메시지는 allowManagedHooksOnly 및 disableAllHooks의 줄을 나열하고 기본 제공 가드의 메시지는 allowManagedModsOnly의 줄을 가집니다.

기본 제공 가드에서 옵션 설정

기본 제공 가드는 두 가지 옵션을 사용합니다. 사용자가 설치한 mod가 로드되지 않도록 중지의 예제처럼 pluginConfigs 아래의 관리되는 설정에서 cc-plugin-sec-default@builtin으로 키가 지정되어 있습니다.

표는 각 옵션이 설정되지 않았을 때와 true로 설정되었을 때 사용자가 얻는 것을 제공합니다:

옵션 설정되지 않음 true
allowManagedModsOnly 사용자의 자체 mod가 로드됨 조직의 mod 및 Claude Code에 기본 제공되는 mod만 로드됩니다. Claude Code는 사용자가 설치했거나 --plugin-dir로 이름을 지정한 mod를 포함한 다른 모든 mod를 거부합니다.
allowModsToOverrideDenyRules 거부 규칙이 사용자의 mod보다 우선합니다 도구 호출을 승인하는 사용자의 mod는 deny 규칙이 거부하는 호출을 승인할 수 있습니다

이러한 규칙은 옵션이 적용되는지 결정합니다:

  • ID는 여기서 한 가지 철자입니다: Claude Code는 cc-plugin-sec-default@builtin 아래에서만 옵션을 읽습니다. prependPlugins는 sec-default@builtin도 허용하고 pluginConfigs는 허용하지 않습니다.
  • 관리되는 설정만 계산됩니다: 사용자, 프로젝트 또는 로컬 설정 파일의 동일한 항목이나 --settings로 전달된 파일의 항목은 옵션을 설정하거나 느슨하게 하지 않습니다
  • 가드가 로드되어야 합니다: prependPlugins를 설정하면 목록에서 가드의 이름을 지정하세요. 가드가 로드되지 않는 곳에서 옵션도 적용되지 않습니다.
  • 가드는 닫힌 상태로 실패합니다: 가드가 관리되는 설정을 읽을 수 없으면 로드 시 모든 사용자의 mod를 거부합니다. 사용자의 mod가 승인한 호출에 대해 거부 규칙을 확인할 수 없으면 호출을 거부합니다.

기본 제공 가드의 메시지는 옵션이 적용될 때 사용자가 보는 것입니다.

조직의 자체 mod 실행

모든 사용자에게 자신의 mod를 배포하고, 사용자의 mod에 상대적으로 실행되는 위치를 선택하고, 정책을 적용하는 데 사용할 수 있습니다.

조직의 mod를 설치하고 순서를 설정합니다

조직의 mod는 사용자의 mod가 로드되지 않는 곳에 로드되고 그 앞에서 실행될 수 있으므로 Claude Code는 mod가 조직에서 왔다는 것을 알 수 있어야 합니다. 다음이 모두 참일 때만 mod를 조직의 것으로 취급합니다:

  • 관리되는 enabledPlugins는 mod의 플러그인을 true로 설정합니다
  • 관리되는 설정은 플러그인의 마켓플레이스를 사용자의 머신의 디렉터리로 절대 경로로 이름을 지정합니다. extraKnownMarketplaces 항목이 그렇게 하고 사용자를 위해 마켓플레이스를 등록합니다.
  • 마켓플레이스는 플러그인을 상대 경로로 나열하므로 Claude Code는 해당 디렉터리에서 로드합니다

이를 충족하려면 장치 관리가 마켓플레이스 디렉터리를 모든 머신의 동일한 경로에 복사하도록 합니다. 관리되는 설정 파일처럼 디렉터리 및 그 위의 모든 디렉터리를 관리자만 쓸 수 있도록 만드세요. 거기에 쓸 수 있는 사람은 누구든 mod를 다시 쓸 수 있습니다. claude.ai 관리자 콘솔에서 전달하는 관리되는 설정은 키를 전달할 수 있지만 머신에 디렉터리를 넣을 수 없습니다.

디렉터리는 마켓플레이스의 매니페스트 및 플러그인을 보유합니다:

/opt/acme/claude-plugins/
├── .claude-plugin/
│   └── marketplace.json
└── plugins/
    └── acme-guard/
        ├── .claude-plugin/
        │   └── plugin.json
        └── hooks/
            ├── hooks.json
            └── register.js

매니페스트는 플러그인을 해당 디렉터리에 상대적인 경로로 나열합니다:

{
  "name": "acme-tools",
  "owner": { "name": "Acme" },
  "plugins": [
    { "name": "acme-guard", "source": "./plugins/acme-guard", "description": "Acme policy mod" }
  ]
}

Claude Code가 캐시에 복사하는 플러그인은 관리되는 enabledPlugins가 활성화하더라도 사용자의 것으로 간주됩니다. 이는 GitHub, git, URL 또는 npm 소스의 모든 플러그인을 포함합니다. 해당 mod는 사용자의 mod 중에서 실행되고 prependPlugins 및 appendPlugins는 이를 건너뛰고 allowManagedModsOnly 또는 allowManagedHooksOnly 아래에서 로드되지 않습니다. 사용자의 디버그 로그에는 플러그인의 ID로 시작하고 is enabled by managed settings, but인 줄이 있습니다.

Claude Code는 도구를 실행하는 것과 같이 행동하려고 할 때마다 이벤트를 발생시키고 각 mod에 차례로 전달합니다. 조직의 것으로 간주되는 mod는 어디에도 나열하지 않아도 사용자의 mod 전에 실행됩니다. 위치를 설정하려면 ID를 두 가지 설정 중 하나에 나열하세요. ID는 플러그인의 이름, @, 마켓플레이스의 이름입니다. 예: acme-guard@acme-tools.

  • prependPlugins: mod는 모든 사용자의 mod 전에 모든 이벤트를 보고 모든 결과 후에 봅니다. 이벤트를 변경하거나 거부하거나 사용자의 mod를 건너뛸 수 있습니다.
  • appendPlugins: mod는 모든 사용자의 mod 후에 실행되므로 해당 mod가 전달하는 이벤트만 해당 형식으로 봅니다

이 예제는 /opt/acme/claude-plugins에서 acme-tools 마켓플레이스를 선언하고 acme-guard를 활성화하고 해당 mod를 먼저 실행하고 기본 제공 가드를 그 다음에 실행합니다:

{
  "extraKnownMarketplaces": {
    "acme-tools": {
      "source": { "source": "directory", "path": "/opt/acme/claude-plugins" }
    }
  },
  "enabledPlugins": { "acme-guard@acme-tools": true },
  "prependPlugins": ["acme-guard@acme-tools", "sec-default@builtin"]
}

각 키는 한 가지 작업을 합니다:

  • extraKnownMarketplaces: acme-tools 마켓플레이스를 보유하는 디렉터리의 이름을 지정합니다. path는 .claude-plugin/marketplace.json을 포함하는 디렉터리의 절대 경로입니다.
  • enabledPlugins: 이러한 관리되는 설정을 받는 모든 사용자에 대해 acme-guard를 켭니다
  • prependPlugins: acme-guard를 먼저, 기본 제공 가드를 두 번째로 배치하고 사용자가 설치한 모든 mod 앞에 배치합니다. Claude Code는 나열하는 순서를 따릅니다.

사용자의 머신이 설정을 받았는지 확인하려면 정책이 적용 중인지 확인을 참조하세요.

mod가 실행되는 위치를 확인하려면 해당 머신에서 claude --debug로 세션을 시작하고 디버그 로그에서 mod의 ID를 검색하세요:

  • hooks module acme-guard@acme-tools loaded, tier prepend 포함: mod는 조직의 것으로 간주되고 먼저 실행됩니다
  • tier user가 있는 동일한 줄: Claude Code는 이를 사용자의 mod로 취급합니다. 두 번째 줄 prependPlugins names acme-guard@acme-tools, which is not an enabled managed plugin with a hooks module; skipped는 목록이 이를 건너뛰었다고 말합니다.

이러한 규칙은 두 목록의 어떤 ID가 적용되는지 결정합니다:

  • 목록은 기본값을 대체합니다: 관리되는 설정에서 prependPlugins를 설정할 때 기본 제공 가드를 유지하려면 sec-default@builtin을 이름을 지정하세요. 가드는 기본 제공되며 enabledPlugins 항목이 필요하지 않습니다.
  • 자신의 ID는 조직의 것으로 간주되어야 합니다: 관리되는 설정에서 Claude Code는 플러그인이 조직의 mod에 대한 세 가지 조건을 충족하지 않는 ID를 건너뜁니다
  • 저장소는 이들을 설정할 수 없습니다: Claude Code는 두 설정을 관리되는 설정에서만 읽고 저장소의 설정 파일에서는 읽지 않습니다. 사용자는 ~/.claude/settings.json에서 설정하여 관리되는 설정이 없는 머신에서만 자신의 mod를 정렬할 수 있으며 Team 또는 Enterprise 플랜으로 로그인하지 않은 경우에만 가능합니다. 다른 곳에서 Claude Code는 사용자 설정의 두 키를 무시합니다. 거기의 목록은 기본 제공 가드를 추가하거나 제거하지 않습니다.

자신의 mod로 정책 적용

모든 사용자의 mod를 제외하려면 자신의 mod가 필요하지 않습니다. allowManagedModsOnly를 설정하세요. 일부 사용자의 mod를 허용하고 다른 mod를 거부하거나 mod가 하는 작업을 기록하려는 경우 정책 mod를 작성하세요.

다른 mod가 로드되려고 할 때마다 mod는 claude plugin validate가 인쇄하는 목록을 plugin.register라는 이벤트에서 받습니다. prependPlugins의 mod는 해당 목록을 읽고 mod를 거부할 수 있습니다. 또한 이름으로 모든 mod API 호출을 hook하여 다른 모든 mod에 대해 해당 호출을 기록하거나 거부할 수 있습니다. 이름은 $. 없는 메서드이므로 fs.write의 hook은 모든 $.fs.write 호출을 봅니다.

이 정책 mod는 자신의 코드가 $.process.run 또는 $.process.spawn을 호출하는 모든 사용자의 mod를 거부합니다. 또한 감사 로그를 유지하여 각 도구 호출 및 mod가 쓰는 각 파일을 디버그 로그에 씁니다. 먼저 실행되므로 로그는 사용자의 mod가 변경하기 전에 요청된 것을 기록합니다. acme-guard/hooks/register.js로 저장하세요:

// 사용자의 mod가 호출할 수 없는 메서드, 각각 namespace.method로 철자
const BLOCKED_CALLS = ['process.run', 'process.spawn']

export function register(on) {
  // 다른 mod가 로드되려고 할 때마다 실행됨
  on('plugin.register', async ($, e, next) => {
    // 해당 mod의 코드에서 차단 목록에 있는 호출을 유지
    const blocked = e.uses.calls.filter((call) => BLOCKED_CALLS.includes(call))
    if (e.tier === 'user' && blocked.length > 0) {
      // 거부를 반환하면 mod가 로드되지 않으며 텍스트가 이유입니다
      return { refuse: 'Acme policy: mods may not call ' + blocked.join(', ') }
    }
    // 다른 모든 mod를 로드하도록 허용
    return next(e)
  })

  // 각 도구 호출을 기록한 다음 변경되지 않은 상태로 진행
  on('tool.call', async ($, e, next) => {
    $.ui.log('audit tool.call ' + e.tool, { to: 'debug' })
    return next(e)
  })

  // 파일을 쓴 mod를 기록한 다음 경로를 기록합니다. mod가 선택했으므로 인용됨
  on('fs.write', async ($, e, next) => {
    $.ui.log('audit fs.write by ' + next.origin.plugin + ' ' + JSON.stringify(e.path), { to: 'debug' })
    return next(e)
  })
}

파일은 세 가지 hook을 등록합니다:

  • plugin.register: 다른 mod가 로드되는지 결정합니다. 차단된 메서드를 호출하는 사용자의 mod를 거부하고 다른 모든 mod를 전달합니다.
  • tool.call: 각 도구 호출에 대해 audit tool.call Bash와 같은 줄을 디버그 로그에 쓰고 아무것도 변경하지 않습니다
  • fs.write: 다른 mod가 만드는 각 $.fs.write 호출에 대해 audit fs.write by reader "/tmp/notes.md"와 같은 줄을 씁니다. mod의 이름이 먼저 나오고 경로가 인용되므로 mod가 선택하는 경로는 줄의 다른 필드로 전달될 수 없습니다.

plugin.register hook은 이벤트의 두 필드를 읽습니다:

  • e.tier: mod가 실행될 위치, prepend, user, append, builtin 중 하나입니다. 사람이 설치하는 모든 mod는 user입니다.
  • e.uses.calls: mod가 호출하는 mod API 메서드, 각각 process.run과 같이 namespace.method로 철자, claude plugin validate가 인쇄하는 $. 없음

사용자가 $.process.run을 호출하는 mod를 설치하면 mod가 로드되지 않으며 디버그 로그에는 refused by acme-guard:로 끝나고 이유가 있는 줄이 있습니다. 거부는 또한 플러그인 디렉터리를 핫 리로드하는 세션의 트랜스크립트에 도달합니다. 전체 mod를 거부하지 않고 호출을 차단하려면 해당 호출의 이름에 대한 hook에서 { deny: 'your reason' }을 반환하세요.

감사 줄을 디버그 로그 이외의 다른 곳으로 보내려면 동일한 hook에서 $.http.fetch를 호출하세요.

세션은 mod 없이 실행될 수 있습니다. 설치된 mod를 실행하는 워커 스레드가 3번 충돌하면 Claude Code는 기본 제공되지 않은 모든 mod(자신의 포함)를 언로드합니다. 사용자가 /reload-plugins를 실행하거나 새 세션을 시작할 때까지입니다. 그리고 --safe-mode로 Claude Code를 시작하는 사용자는 설치된 mod 없이 실행되며 자신의 mod도 포함됩니다.

mod 만들기는 mod가 필요한 파일을 다룹니다. 다른 mod를 판단하는 mod 테스트는 이 정책 mod에 대한 테스트 파일을 가집니다.

확인이 실패할 때 mod 거부

plugin.register hook이 throw하거나 시간 제한을 초과하면 Claude Code는 hook을 건너뛰므로 확인이 열린 상태로 실패하고 확인 중인 mod가 로드됩니다. 닫힌 상태로 실패하고 사용자의 mod를 거부하려면 확인을 명명된 함수로 이동하고 거부를 반환하는 .catch 핸들러를 추가하세요. 이 파일 버전은 plugin.register hook만 표시하므로 첫 번째 버전의 두 감사 hook을 register에 유지하세요:

const BLOCKED_CALLS = ['process.run', 'process.spawn']

// 이전과 동일한 확인, 자신의 함수로 이동됨
async function checkMod($, 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)
}

export function register(on) {
  // 핸들러는 checkMod가 throw하거나 시간 제한을 초과할 때만 실행됨
  on('plugin.register', checkMod).catch(async ($, e, next) => {
    // 조직의 mod 및 기본 제공 mod를 로드하도록 허용
    if (e.tier !== 'user') return next(e)
    // 확인할 수 없었던 사용자의 mod를 거부
    return { refuse: 'Acme policy check failed, so this mod was not loaded' }
  })
}

핸들러가 있으면 확인이 throw하거나 시간 초과될 때 확인 중인 mod가 로드되지 않으며 거부 줄은 두 번째 이유를 전달합니다. 예: refused by acme-guard: Acme policy check failed, so this mod was not loaded. 핸들러는 user 계층 외부의 모든 mod를 next(e)로 전달하므로 실패한 확인이 조직이 나열하는 mod를 중지하지 않습니다. 실패하는 hook 처리는 다른 이벤트에 대해 .catch를 다룹니다.

다음 단계

  • 플러그인 보안: 모든 플러그인이 사용자의 머신에서 할 수 있는 것과 설치 전에 검토하는 방법
  • Mod 개요: mod가 무엇이고 hook, skill, MCP 서버와 어떻게 비교되는지
  • Mod가 실행되는 순서: prependPlugins 및 appendPlugins가 사용자의 mod와 어떻게 맞는지
  • 설정 및 환경 변수: 이 페이지에서 이름이 지정된 모든 설정을 한 표에서