SpyBara
Go Premium

plugins/mods/admin.md 2026-10-07 23:59 UTC to 2026-10-08 06:58 UTC

This page contains 57 additions and 57 deletions.

2026
Thu 1 23:59 Fri 2 22:59 Tue 6 23:59 Thu 8 07:59

Управление модами для вашей организации

Контролируйте Claude Code mods с помощью управляемых параметров: остановите установленные пользователем моды, разрешите только свои, просмотрите возможности мода и обеспечьте политику с помощью собственного мода.

Мод — это плагин, который выполняет код внутри Claude Code с разрешениями пользователя, который его установил. Моды не изолированы в песочнице. Через управляемые параметры вы решаете, будут ли моды работать на машинах ваших пользователей, какие именно и в каком порядке. Вы также можете установить собственный мод, который отслеживает или отказывает в том, что делают другие моды.

Эта страница предназначена для человека, который развертывает управляемые настройки для Claude Code, будь то в виде файла, через MDM или из консоли администратора claude.ai. Моды включены по умолчанию в Claude Code v2.1.286 и более поздних версиях. Начните с раздела, который соответствует тому, что вы хотите сделать:

Остановить загрузку установленных пользователем модов

Чтобы ни один мод, который приносят ваши пользователи, не запускал свои хуки, установите параметр allowManagedModsOnly для встроенного стража — мода политики, который Claude Code загружает перед каждым модом, установленным пользователем. Параметр задаётся в управляемых настройках в pluginConfigs с ключом cc-plugin-sec-default@builtin:

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

Когда параметр установлен в управляемых настройках:

  • Ни один мод, который приносит пользователь, не запускает свои хуки: это касается мода в плагине, установленном пользователем, мода, загруженного с помощью --plugin-dir, и мода, который Claude написал во время сессии
  • Моды вашей организации по-прежнему работают: мод, который считается модом вашей организации, не проверяется. Все остальные моды считаются модами пользователя и отклоняются. Это включает мод в плагине, который вы включаете из GitHub или другого удаленного маркетплейса, и мод, который ваша организация включает для своих участников на claude.ai. Если ни один мод не считается вашим, ни один установленный мод не запускает свои хуки.
  • Пользователи не могут это отменить: страж читает параметр только из управляемых настроек, поэтому та же запись в файле настроек пользователя, проекта или локальных настроек или в файле, переданном с помощью --settings, ничего не меняет
  • Файл или политика MDM охватывают каждого поставщика: когда вы доставляете параметр в виде файла или через MDM, он работает одинаково на Amazon Bedrock, Google Cloud's Agent Platform и Microsoft Foundry. Для доставки из консоли администратора claude.ai см. Доступность платформы
  • Другие настройки пользователей продолжают работать: их хуки в файлах настроек и в hooks/hooks.json плагинов, строки состояния и /goal не затрагиваются
  • Встроенные моды продолжают работать: у каждого из модов, встроенных в Claude Code, таких как поддержка AGENTS.md, есть свой собственный переключатель

Чтобы проверить параметр на машине пользователя, запустите там Claude Code с --plugin-dir и путём к каталогу, который содержит мод, например claude --plugin-dir ./first-mod. Хуки мода не запускаются, а транскрипт и отладочный лог содержат сообщение стража, в котором указаны мод и allowManagedModsOnly. Если сообщения нет, см. Проверить, что политика действует и правила, которые определяют, вступает ли параметр в силу.

Если вы установили CLAUDE_CODE_ENABLE_FUNCTION_HOOKS в 0 во время раннего доступа, замените его этим параметром. Claude Code v2.1.287 и более поздние версии игнорируют переменную при любом значении, поэтому 0 в ней оставляет моды включёнными.

Узнать, что происходит по умолчанию

Без собственных параметров модов вот что получают ваши пользователи:

  • Моды включены. Пользователь может установить плагин, содержащий мод из любого маркетплейса, который разрешают ваши параметры плагинов, или загрузить его из каталога с помощью --plugin-dir.

  • Встроенная защита работает первой. Claude Code загружает встроенный мод с именем sec-default@builtin перед каждым модом, установленным пользователем. Пользователи не могут его отключить. /plugin и журнал отладки указывают его как cc-plugin-sec-default. Защита загружается, когда верно одно из следующих условий:

    • На машине есть управляемые параметры
    • Пользователь вошел в Claude Code с планом Team или Enterprise

    Пользователь, который аутентифицируется с помощью ключа API или через Amazon Bedrock, Google Cloud's Agent Platform или Microsoft Foundry, получает защиту только на машине с управляемыми параметрами.

  • Защита защищает то, что вы управляете. Мод пользователя не может изменить то, что получают или решают ваши управляемые hooks, системный запрос, ваши управляемые CLAUDE.md и другие управляемые инструкции, то, что любой мод читает как параметры, или инструменты и описания ваших управляемых MCP серверов.

  • Все остальное разрешено. Защита не добавляет других ограничений. Мод пользователя по-прежнему может читать и писать файлы, запускать процессы, делать сетевые запросы, переписывать вызовы инструментов и запросы, отказывать в вызове инструмента, одобрять вызов, который иначе потребовал бы подтверждения, и рисовать в интерфейсе, все с разрешениями этого пользователя.

  • Правила отказа и ваши управляемые хуки имеют приоритет. Где загружается защита, мод пользователя не может одобрить вызов, который отклоняет правило deny, независимо от того, какой файл настроек содержит правило. Блокировка из хука PreToolUse в управляемых настройках также окончательна. Оба применяются к вызовам инструментов Claude. Ни один не применяется к собственным вызовам мода $.fs и $.process: при запрещенном Read(.env) мод все еще может прочитать этот файл с помощью $.fs.read или запустить программу, которая это делает. Чтобы ограничить эти вызовы, не позволяйте моду загружаться или обработайте вызов в политическом моде.

  • Другие проверки разрешений могут быть переопределены. Мод пользователя, который одобряет вызовы инструментов, может одобрить вызов, который правило ask потребовало бы подтверждения, или который hook PreToolUse вне управляемых параметров заблокировал. В автоматическом режиме вызов, одобренный модом, выполняется без проверки классификатора.

Исходный код защиты является общедоступным в каталоге mods/sec-default репозитория Claude Code.

Узнать, какие элементы управления по-прежнему применяются

Моды не заменяют элементы управления, которые у вас уже есть:

  • Hooks параметров продолжают работать. Hooks команд, HTTP, запросов и агентов в файлах параметров и в hooks/hooks.json плагинов работают как раньше, наряду с модами. Ничего в них не устарело.
  • Правила отказа имеют приоритет, где загружается защита. Мод пользователя не может одобрить вызов, который правило deny отказывает, если вы не установите allowModsToOverrideDenyRules.
  • Управляемые hooks работают первыми. Hook PreToolUse в управляемых параметрах работает перед тем, как любой мод увидит вызов инструмента, и его блокировка окончательна. Если мод затем переписывает вызов, ваши управляемые hooks работают снова на переписанном вызове, поэтому блокировка по-прежнему применяется. Hooks PreToolUse из других файлов параметров и из плагинов работают после последнего мода, поэтому мод, который возвращает свой собственный результат вместо запуска инструмента, не позволяет им работать. См. Порядок, в котором работают моды.
  • Политика сети охватывает $.http.fetch. Если ваша организация отключает веб-выборку или отключен несущественный сетевой трафик для сеанса, Claude Code отказывает в сетевом запросе, который мод делает с помощью $.http.fetch. Политика не охватывает программу, которую мод запускает с помощью $.process.run. Эта программа достигает сети с собственным доступом пользователя.
  • Элементы управления плагинами охватывают моды. Мод — это плагин, поэтому параметры, которые ограничивают то, что пользователи могут установить, такие как strictKnownMarketplaces, определяют, может ли он быть установлен вообще.
  • Моды не могут изменить запрос разрешения. Мод может переделать большую часть интерфейса Claude Code, но не запрос разрешения, поэтому он не может изменить то, что показывает запрос. Мод все еще может одобрить или отказать в вызове инструмента перед появлением запроса, как описано в Узнать, что происходит по умолчанию.
  • Запросы доверия идут первыми. В интерактивном сеансе в каталоге, который пользователь еще не доверил, ни один мод не загружается, пока они не ответят на запрос доверия.
  • --safe-mode отключает установленные моды, включая ваши. Запустите сеанс с claude --safe-mode, чтобы проверить, вызвал ли мод проблему.

Ни один из этих элементов управления не изолирует мод в песочнице. Мод, который вы разрешаете, работает как пользователь, с доступом пользователя к файлам, процессам и сети.

Решить, оставить ли моды включенными

Мод может делать больше, чем другие части плагина, потому что он работает внутри Claude Code. Он видит каждый запрос и вызов инструмента, может их изменять и может разрешить или отказать в вызове инструмента перед появлением запроса разрешения.

То, что пользователь может загрузить как мод, зависит от элементов управления плагинами, которые у вас уже есть:

Ваши элементы управления плагинами сегодня Что пользователь может загрузить как мод
Нет Мод из любого маркетплейса, из любого каталога с --plugin-dir или который Claude пишет во время сеанса
Список разрешений маркетплейса Мод из маркетплейсов, которые вы разрешаете, или из любого каталога с --plugin-dir. Мод, который Claude пишет во время сеанса, загружается только когда список разрешений включает skills-dir.
Список разрешений маркетплейса и disableSideloadFlags Мод из маркетплейсов, которые вы разрешаете

Управление плагинами для вашей организации перечисляет способы загрузки плагина и настройку, которая управляет каждым из них.

Чтобы проверить моды в маркетплейсе перед тем, как ваши пользователи их установят, см. Просмотреть возможности мода. Чтобы исключить моды пользователей, пока вы это делаете, см. Остановить загрузку установленных пользователем модов.

Просмотреть возможности мода

Вы можете увидеть, что может делать мод, не запуская его. В вашей оболочке запустите claude plugin validate в каталоге плагина:

claude plugin validate ./some-mod

Строки hooks: и calls: в выводе описывают код мода:

  ❯ ./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 отказывается загружать мод, который использует 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 означает, что мод может одобрить или отказать в вызове инструмента перед появлением запроса разрешения. Узнать, что происходит по умолчанию перечисляет, какие из ваших правил и hooks имеют приоритет над его ответом.

Выбрать, сколько разрешить

Политики модов варьируются от полного отсутствия установленных модов до любого мода, который выбирает пользователь, при этом ваш собственный мод проверяет остальные, и каждая из них — это несколько управляемых настроек. Найдите нужную политику в первом столбце и задайте то, что указано во втором столбце. В разделе Развертывание управляемых настроек описано, где находятся управляемые настройки.

Что вы хотите Настройки
Не выполняется ни один установленный мод, хуки настроек не затронуты Задайте allowManagedModsOnly и не развертывайте собственных модов
Нет установленных модов и вообще нет хуков, включая ваши управляемые хуки Установите disableAllHooks в true
Только моды вашей организации Задайте параметр стража allowManagedModsOnly и установите ваши моды, чтобы они считались вашими
Любой мод из маркетплейсов, которые вы одобряете Сохраните ваши ограничения маркетплейсов и установите disableSideloadFlags в true
Любой мод, при этом ваш собственный мод проверяет остальные Установите ваш мод и перечислите его вместе с sec-default@builtin в prependPlugins

Что делает каждая настройка:

  • allowManagedModsOnly: параметр встроенного стража. Claude Code отклоняет собственные моды пользователей, поэтому ни один из их хуков не выполняется. Хуки настроек пользователей, строки состояния и /goal продолжают работать. В разделе Остановить загрузку установленных пользователем модов перечислено, что он охватывает.
  • allowManagedHooksOnly: более широкая настройка. Загружаются только моды вашей организации и моды, встроенные в Claude Code. Мод, который пользователь установил сам, не загружается. Настройка также блокирует хуки в собственных файлах настроек пользователей. Прочитайте Что выполняется при allowManagedHooksOnly, прежде чем задавать её.
  • disableAllHooks: самая широкая настройка. В управляемых настройках она останавливает моды в каждом установленном плагине, включая ваши, и отключает все хуки в файлах настроек, поэтому хук PreToolUse в ваших управляемых настройках больше ничего не блокирует. Пользовательские строки состояния и /goal также перестают работать. Прочитайте disableAllHooks, прежде чем задавать её.
  • disableSideloadFlags: отклоняет --plugin-dir и --plugin-url при запуске и не позволяет загружаться модам, которые Claude пишет во время сессии. Настройка также отклоняет --agents и --mcp-config. Прочитайте disableSideloadFlags, прежде чем задавать её.

Моды, встроенные в Claude Code, такие как поддержка AGENTS.md, не затрагиваются этими настройками. У каждого из них есть свой собственный переключатель.

Пользователь, чей мод был отклонён или не загрузился, найдёт причину в своём логе отладки. В разделе Сообщения об отказе перечислены строки для allowManagedHooksOnly и disableAllHooks, а в разделе Сообщения от встроенного стража приведена строка для allowManagedModsOnly.

Разрешить только моды вашей организации

Чтобы запускать моды вашей организации и блокировать моды, которые приносят пользователи, разверните настройки из строки Только моды вашей организации таблицы политик, а также disableSideloadFlags. С этим полным managed-settings.json Claude Code отклоняет собственные моды пользователей, поэтому ни один из их хуков не выполняется, а ваш мод политики запускается раньше других модов:

{
  "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"],
  "pluginConfigs": {
    "cc-plugin-sec-default@builtin": {
      "options": { "allowManagedModsOnly": true }
    }
  },
  "disableSideloadFlags": true
}

Каждая группа ключей выполняет одну задачу:

  • extraKnownMarketplaces, enabledPlugins и prependPlugins: устанавливают ваш мод так, чтобы он считался вашим, и запускают его первым, а стража — после него. В разделе Установить моды вашей организации и задать порядок описан каталог, на который указывают эти ключи.
  • pluginConfigs: задаёт параметр стража allowManagedModsOnly, поэтому Claude Code отклоняет собственные моды пользователей. Их хуки настроек, строки состояния и /goal продолжают работать.
  • disableSideloadFlags: см. disableSideloadFlags, чтобы узнать, какие флаги она отклоняет при запуске

Чтобы проверить политику на тестовой машине, запустите в оболочке сессию с claude --debug и прочитайте лог отладки:

  • Ваш мод: его строка hooks module содержит tier prepend
  • Мод, установленный пользователем: есть строка refused by cc-plugin-sec-default: mods are limited to your organization's by policy (allowManagedModsOnly). Более ранняя строка сообщает, что модуль хуков этого мода loaded, поэтому ищите именно отказ.
  • Каталог плагина: claude --plugin-dir ./any-mod завершается с сообщением, которое начинается с --plugin-dir is disabled by your organization's managed settings (disableSideloadFlags)

Чтобы также ограничить, какие маркетплейсы могут добавлять пользователи, объедините этот файл с вашими ограничениями маркетплейсов.

Применить ваши средства управления плагинами к модам

Мод — это плагин, поэтому способы управления плагинами для вашей организации применимы и к плагину, содержащему мод:

Задать параметры встроенного стража

Встроенный страж принимает параметры. Задайте их в управляемых настройках в pluginConfigs под ключом cc-plugin-sec-default@builtin, как это сделано в примере в разделе Остановить загрузку установленных пользователем модов.

В таблице показано, что получают ваши пользователи, когда каждый параметр не задан и когда он установлен в true:

Параметр Не задан true
allowManagedModsOnly Собственные моды пользователей выполняются Только моды вашей организации и моды, встроенные в Claude Code, выполняют свои хуки. Claude Code отклоняет все остальные моды, включая мод, установленный пользователем или указанный с помощью --plugin-dir.
allowModsToOverrideDenyRules Правила запрета имеют приоритет над модами пользователей Мод пользователя, который одобряет вызовы инструментов, может одобрить вызов, отклоняемый правилом deny

Эти правила определяют, вступает ли параметр в силу:

  • Здесь id имеет только одну форму: Claude Code читает параметры только под cc-plugin-sec-default@builtin. prependPlugins также принимает sec-default@builtin, а pluginConfigs — нет.
  • Учитываются только управляемые настройки: та же запись в файле настроек пользователя, проекта или локальных настроек либо в файле, переданном с помощью --settings, не задаёт параметр и не ослабляет его
  • Страж должен загружаться: если вы задаёте prependPlugins, укажите стража в списке. Там, где страж не загружается, не применяется ни один из параметров.
  • При сбое страж отказывает: если страж не может прочитать управляемые настройки, он отклоняет все моды пользователей при загрузке. Если он не может проверить правила запрета для вызова, который одобрил мод пользователя, он отклоняет этот вызов.

Сообщения от встроенного стража — это то, что видят ваши пользователи, когда применяется любой из параметров.

Развертывание собственных модов вашей организации

Вы можете развертывать собственные моды для каждого пользователя, выбирать, где они выполняются относительно модов пользователей, и использовать один из них для обеспечения политики.

Установка модов вашей организации и установка порядка

Моды вашей организации загружаются там, где не загружаются моды пользователей, и могут выполняться перед ними, поэтому Claude Code должен иметь возможность определить, что мод поступил от вас. Он рассматривает мод как принадлежащий вашей организации только в том случае, если все следующие условия верны:

  • Управляемый enabledPlugins устанавливает плагин мода в true
  • Управляемые настройки называют маркетплейс плагина как каталог на машине пользователя по абсолютному пути. Запись extraKnownMarketplaces делает это и также регистрирует маркетплейс для пользователя.
  • Маркетплейс указывает плагин по относительному пути, поэтому Claude Code загружает его на месте из этого каталога

Чтобы выполнить эти условия, скопируйте каталог маркетплейса на одинаковый путь на каждой машине с помощью управления устройствами. Сделайте каталог и каждый каталог выше него доступными для записи только администратором, как и файл управляемых настроек. Любой, кто может писать туда, может переписать ваш мод. Управляемые настройки, которые вы доставляете из консоли администратора 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. Его мод выполняется среди модов пользователей, prependPlugins и appendPlugins его пропускают, allowManagedModsOnly отказывает ему, а allowManagedHooksOnly не дает ему загрузиться. В логе отладки пользователя есть строка, которая начинается с идентификатора плагина и is enabled by managed settings, but.

Claude Code вызывает событие каждый раз, когда он собирается действовать, например запустить инструмент, и передает его каждому моду по очереди. Мод, который считается вашим, выполняется перед модами пользователей, даже если вы его нигде не указываете. Чтобы задать его место, укажите его идентификатор в одной из двух настроек. Идентификатор — это имя плагина, @ и имя маркетплейса, например acme-guard@acme-tools.

  • prependPlugins: ваш мод видит каждое событие перед любым модом пользователя и каждый результат после. Он может изменить событие, отказать в нем или пропустить моды пользователей.
  • appendPlugins: ваш мод выполняется после каждого мода пользователя, поэтому он видит только события, которые эти моды передают, в форме, в которой они их передают

Этот пример объявляет маркетплейс acme-tools в /opt/acme/claude-plugins, включает acme-guard из него и запускает этот мод первым, со встроенным стражем после него:

{
  "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 первым и встроенного стража вторым, оба впереди любого мода, который устанавливает пользователь. Claude Code следует порядку, который вы указываете.

Чтобы подтвердить, что машина пользователя получила настройки, см. Проверка того, что политика действует.

Чтобы подтвердить, где выполняется мод, запустите сессию на этой машине с claude --debug и найдите в логе отладки идентификатор мода:

  • hooks module acme-guard@acme-tools loaded, с tier prepend: мод считается принадлежащим вашей организации и выполняется первым
  • Та же строка с tier user: Claude Code рассматривает его как мод пользователя. Вторая строка, prependPlugins names acme-guard@acme-tools, which is not an enabled managed plugin with a hooks module; skipped, говорит, что список его пропустил.

Эти правила определяют, какие идентификаторы в двух списках вступают в силу:

  • Список заменяет значение по умолчанию: когда вы задаете prependPlugins в управляемых настройках, укажите в нем sec-default@builtin, чтобы сохранить встроенного стража. Страж встроен и не требует записи enabledPlugins.
  • Ваши собственные идентификаторы должны считаться вашими: в управляемых настройках Claude Code пропускает идентификатор, чей плагин не соответствует условиям для мода организации
  • Репозитории не могут их задавать: Claude Code читает обе настройки из управляемых настроек и никогда из файла настроек репозитория. Пользователь может задать их в ~/.claude/settings.json, чтобы упорядочить только свои моды на машине без управляемых настроек, и только если он не вошел в систему с планом Team или Enterprise. В любом другом месте Claude Code игнорирует оба ключа в пользовательских настройках. Список там не добавляет и не удаляет встроенного стража.

Обеспечение политики с помощью собственного мода

Чтобы не допустить загрузку любого мода пользователя, вам не нужен собственный мод. Установите allowManagedModsOnly. Напишите мод политики, когда вы хотите допустить некоторые моды пользователей и отказать другим или чтобы записывать, что делают моды.

Каждый раз, когда другой мод собирается загрузиться, ваш мод получает список, который печатает claude plugin validate, в событии с именем plugin.register. Мод в prependPlugins может прочитать этот список и отказать в загрузке мода. Он также может обработать любой вызов API модов по имени, чтобы записать этот вызов или отказать в нем для каждого другого мода. Имя — это метод без $., поэтому хук на fs.write видит каждый вызов $.fs.write.

Этот мод политики отказывает любому моду пользователя, чей собственный код вызывает $.process.run или $.process.spawn. Он также ведет журнал аудита, записывая каждый вызов инструмента и каждый файл, который мод записывает, в лог отладки. Поскольку он выполняется первым, лог записывает то, что было запрошено, перед тем как любой мод пользователя это изменит. Сохраните его как acme-guard/hooks/register.js:

// The methods no user's mod may call, each spelled namespace.method
const BLOCKED_CALLS = ['process.run', 'process.spawn']

export function register(on) {
  // Runs each time another mod is about to load
  on('plugin.register', async ($, e, next) => {
    // Keep the calls in that mod's code that are on the blocked list
    const blocked = e.uses.calls.filter((call) => BLOCKED_CALLS.includes(call))
    if (e.tier === 'user' && blocked.length > 0) {
      // Returning refuse keeps the mod from loading, and the text is the reason
      return { refuse: 'Acme policy: mods may not call ' + blocked.join(', ') }
    }
    // Let every other mod load
    return next(e)
  })

  // Record each tool call, then let it go ahead unchanged
  on('tool.call', async ($, e, next) => {
    $.ui.log('audit tool.call ' + e.tool, { to: 'debug' })
    return next(e)
  })

  // Record which mod wrote a file, then the path, quoted because the mod chose it
  on('fs.write', async ($, e, next) => {
    $.ui.log('audit fs.write by ' + next.origin.plugin + ' ' + JSON.stringify(e.path), { to: 'debug' })
    return next(e)
  })
}

Файл регистрирует три хука:

  • plugin.register: решает, загружается ли другой мод. Он отказывает моду пользователя, который вызывает заблокированный метод, и передает каждый другой мод дальше.
  • tool.call: записывает строку, такую как audit tool.call Bash, в лог отладки для каждого вызова инструмента и ничего не изменяет
  • fs.write: записывает строку, такую как audit fs.write by reader "/tmp/notes.md", для каждого вызова $.fs.write, который делает другой мод, и ничего не изменяет. Имя мода идет первым, а путь заключен в кавычки, поэтому путь, который выбирает мод, не может выдать себя за другое поле строки.

Хук plugin.register читает два поля события:

  • e.tier: где будет выполняться мод, один из prepend, user, append или builtin. Каждый мод, который устанавливает человек, — это user.
  • e.uses.calls: методы API модов, которые вызывает мод, каждый записан как namespace.method, например process.run, без $., который печатает claude plugin validate

Когда пользователь устанавливает мод, который вызывает $.process.run, мод не загружается, и в его логе отладки есть строка, которая заканчивается на refused by acme-guard: и вашу причину. Отказ также попадает в транскрипт в сессии, которая выполняет горячую перезагрузку каталога плагина. Чтобы заблокировать вызов без отказа всему моду, верните { deny: 'your reason' } из хука на имя этого вызова.

Чтобы отправить строки аудита куда-то, кроме лога отладки, вызовите $.http.fetch из тех же хуков.

Сессия может выполняться без вашего мода. Если рабочий поток, который запускает установленные моды, падает три раза, Claude Code выгружает каждый мод, который не встроен, включая ваш, пока пользователь не запустит /reload-plugins или не начнет новую сессию. А пользователь, который запускает Claude Code с --safe-mode, работает без установленных модов, включая ваш.

Создание мода описывает файлы, которые нужны моду. Тестирование мода политики содержит файл теста для этого мода политики.

Отказ в загрузке модов при сбое вашей проверки

Если ваш хук plugin.register выбросит исключение или превысит лимит времени, Claude Code пропускает хук, поэтому при сбое проверка остается открытой (fail open), и мод, который она проверяла, загружается. Чтобы при сбое закрывать доступ (fail closed) и отказывать в загрузке модов пользователей, переместите проверку в именованную функцию и добавьте обработчик .catch, который возвращает отказ. Эта версия файла показывает только хук plugin.register, поэтому сохраните два хука аудита из первой версии в register:

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

// The same check as before, moved into a function of its own
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) {
  // The handler runs only when checkMod throws or exceeds its time limit
  on('plugin.register', checkMod).catch(async ($, e, next) => {
    // Let your organization's mods and built-in mods load
    if (e.tier !== 'user') return next(e)
    // Refuse the user's mod that couldn't be checked
    return { refuse: 'Acme policy check failed, so this mod was not loaded' }
  })
}

С обработчиком на месте мод, который проверялся, когда проверка выбросила исключение или истекло время, не загружается, и строка отказа содержит вторую причину, как в refused by acme-guard: Acme policy check failed, so this mod was not loaded. Обработчик передает каждый мод вне уровня user в next(e), поэтому неудачная проверка не останавливает моды, которые указывает ваша организация. Обработка хука, завершившегося сбоем описывает .catch для других событий.

Следующие шаги