SpyBara
Go Premium

plugins/mods/admin.md 2026-10-01 23:59 UTC to 2026-10-02 20:57 UTC

This page contains 196 additions and 145 deletions.

2026
Thu 1 23:59 Fri 2 22:00

Administra los mods de tu organización

Controla los mods de Claude Code con la configuración administrada: detén los mods instalados por los usuarios, permite solo los tuyos, revisa lo que puede hacer un mod y aplica políticas con tu propio mod.

Un mod es un plugin que ejecuta código dentro de Claude Code con los permisos del usuario que lo instaló. Los mods no están en un sandbox. A través de la configuración administrada, decides si los mods se ejecutan en las máquinas de tus usuarios, cuáles y en qué orden. También puedes instalar un mod propio que observe o rechace lo que hacen otros mods.

Esta página es para la persona que implementa la configuración administrada de Claude Code, ya sea como archivo, mediante MDM o desde la consola de administración de claude.ai. Los mods están activados de forma predeterminada en Claude Code v2.1.287 y versiones posteriores. Empieza por la sección que corresponda a lo que viniste a hacer:

Impedir que se carguen los mods instalados por los usuarios

Para evitar que se cargue cualquier mod que traigan tus usuarios, establece la opción allowManagedModsOnly en la protección integrada, un mod de políticas que Claude Code carga antes que cualquier mod que instale un usuario. La opción va en la configuración administrada dentro de pluginConfigs, con la clave cc-plugin-sec-default@builtin:

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

Con la opción establecida en la configuración administrada:

  • No se carga ningún mod que traiga un usuario: eso abarca un mod en un plugin que el usuario instaló, un mod cargado con --plugin-dir y un mod que Claude escribió durante una sesión
  • Los mods de tu organización se siguen cargando: un mod que cuenta como de tu organización no se revisa. Cualquier otro mod cuenta como de un usuario y no se carga. Eso incluye un mod en un plugin que habilitas desde GitHub u otro marketplace remoto, y uno que tu organización activa para sus miembros en claude.ai. Si ninguno cuenta como tuyo, no se carga ningún mod instalado.
  • Los usuarios no pueden revertirlo: la protección lee la opción solo desde la configuración administrada, así que la misma entrada en un archivo de configuración de usuario, de proyecto o local, o en un archivo pasado con --settings, no cambia nada
  • Un archivo o una política de MDM cubre a todos los proveedores: cuando entregas la opción como archivo o mediante MDM, funciona igual en Amazon Bedrock, Agent Platform de Google Cloud y Microsoft Foundry. Para la entrega desde la consola de administración de claude.ai, consulta Disponibilidad por plataforma
  • Las demás personalizaciones de los usuarios siguen funcionando: sus hooks en archivos de configuración, sus líneas de estado y /goal no se ven afectados
  • Los mods integrados siguen ejecutándose: los mods integrados en Claude Code, como el soporte de AGENTS.md, tienen cada uno su propio interruptor

Para confirmar la opción en la máquina de un usuario, inicia Claude Code allí con --plugin-dir y la ruta de un directorio que contenga un mod, como claude --plugin-dir ./first-mod. Los hooks del mod no se ejecutan, y la transcripción y el registro de depuración muestran el mensaje de la protección, que nombra el mod y allowManagedModsOnly. Si el mod se carga, consulta Comprobar que una política está en vigor y las reglas que deciden si una opción surte efecto.

Si estableciste CLAUDE_CODE_ENABLE_FUNCTION_HOOKS en 0 durante el acceso anticipado, reemplázala con esta opción. Claude Code v2.1.287 y posteriores ignoran la variable con cualquier valor, así que un 0 en ella deja los mods activados.

Conoce lo que ocurre de forma predeterminada

Sin ninguna configuración de mods propia, esto es lo que obtienen tus usuarios:

  • Los mods están activados. Un usuario puede instalar un plugin que contenga un mod desde cualquier marketplace que permita tu configuración de plugins, o cargar uno desde un directorio con --plugin-dir.

  • Una protección integrada se ejecuta primero. Claude Code carga un mod integrado llamado sec-default@builtin antes de cada mod que instala un usuario. Los usuarios no pueden desactivarlo. /plugin y el registro de depuración lo muestran como cc-plugin-sec-default. La protección se carga cuando se cumple cualquiera de estas condiciones:

    • La máquina tiene configuración administrada
    • El usuario ha iniciado sesión en Claude Code con un plan Team o Enterprise

    Un usuario que se autentica con una clave de API, o mediante Amazon Bedrock, Agent Platform de Google Cloud o Microsoft Foundry, obtiene la protección solo en una máquina que tenga configuración administrada.

  • La protección resguarda lo que administras. El mod de un usuario no puede cambiar lo que reciben o deciden tus hooks administrados, el prompt del sistema, tu CLAUDE.md administrado y otras instrucciones administradas, lo que cualquier mod lee como configuración, ni las herramientas y descripciones de tus servidores MCP administrados.

  • Todo lo demás está permitido. La protección no añade ninguna otra restricción. El mod de un usuario aún puede leer y escribir archivos, iniciar procesos, hacer solicitudes de red, reescribir llamadas a herramientas y prompts, denegar una llamada a herramienta, aprobar una que de otro modo pediría confirmación y dibujar en la interfaz, todo con los permisos de ese usuario.

  • Las reglas de denegación y tus hooks administrados tienen precedencia. Donde se carga la protección, el mod de un usuario no puede aprobar una llamada que rechaza una regla deny, sin importar qué archivo de configuración contenga la regla. Un bloqueo de un hook PreToolUse en la configuración administrada también es definitivo. Ambos se aplican a las llamadas a herramientas de Claude. Ninguno se aplica a las propias llamadas $.fs y $.process de un mod: con Read(.env) denegado, un mod aún puede leer ese archivo con $.fs.read o iniciar un programa que lo haga. Para limitar esas llamadas, impide que el mod se cargue o gestiona la llamada en un mod de políticas.

  • Otras comprobaciones de permisos pueden anularse. El mod de un usuario que aprueba llamadas a herramientas puede aprobar una llamada para la que una regla ask pediría confirmación, o que un hook PreToolUse fuera de la configuración administrada bloqueó. En modo automático, una llamada que el mod aprueba se ejecuta sin una comprobación del clasificador.

El código fuente de la protección es público en el directorio mods/sec-default del repositorio de Claude Code.

Conoce qué controles siguen aplicándose

Los mods no reemplazan los controles que ya tienes:

  • Los hooks de configuración siguen funcionando. Los hooks de comando, HTTP, prompt y agente en los archivos de configuración y en el hooks/hooks.json de los plugins se ejecutan como antes, junto con los mods. Nada de ellos está obsoleto.
  • Las reglas de denegación tienen precedencia donde se carga la protección. El mod de un usuario no puede aprobar una llamada que rechaza una regla deny, a menos que configures allowModsToOverrideDenyRules.
  • Los hooks administrados se ejecutan primero. Un hook PreToolUse en la configuración administrada se ejecuta antes de que cualquier mod vea la llamada a herramienta, y su bloqueo es definitivo. Si luego un mod reescribe la llamada, tus hooks administrados se ejecutan de nuevo sobre la llamada reescrita, por lo que un bloqueo sigue aplicándose. Los hooks PreToolUse de otros archivos de configuración y de plugins se ejecutan después del último mod, así que un mod que devuelve su propio resultado en lugar de ejecutar la herramienta impide que esos se ejecuten. Consulta El orden en que se ejecutan los mods.
  • La política de red cubre $.http.fetch. Si tu organización desactiva la obtención web, o el tráfico de red no esencial está desactivado para la sesión, Claude Code rechaza una solicitud de red que un mod hace con $.http.fetch. La política no cubre un programa que el mod inicia con $.process.run. Ese programa accede a la red con el propio acceso del usuario.
  • Los controles de plugins cubren los mods. Un mod es un plugin, así que la configuración que restringe lo que los usuarios pueden instalar, como strictKnownMarketplaces, decide si puede instalarse en absoluto.
  • Los mods no pueden cambiar la solicitud de permiso. Un mod puede cambiar el estilo de gran parte de la interfaz de Claude Code, pero no de la solicitud de permiso, así que no puede cambiar lo que muestra una solicitud. Un mod aún puede aprobar o denegar una llamada a herramienta antes de que aparezca la solicitud, como se describe en Conoce lo que ocurre de forma predeterminada.
  • Las solicitudes de confianza van primero. En una sesión interactiva en un directorio en el que el usuario aún no ha confiado, ningún mod se carga hasta que responde a la solicitud de confianza.
  • --safe-mode desactiva los mods instalados, incluidos los tuyos. Inicia una sesión con claude --safe-mode para comprobar si un mod causó un problema.

Ninguno de estos controles ejecuta un mod en un sandbox. Un mod que permites se ejecuta como el usuario, con el acceso del usuario a archivos, procesos y la red.

Decide si dejar los mods activados

Un mod puede hacer más que las otras partes de un plugin porque se ejecuta dentro de Claude Code. Ve cada prompt y cada llamada a herramienta, puede modificarlos y puede permitir o denegar una llamada a herramienta antes de que aparezca una solicitud de permiso.

Lo que un usuario puede cargar como mod depende de los controles de plugins que ya tienes:

Tus controles de plugins actuales Lo que un usuario puede cargar como mod
Ninguno Un mod de cualquier marketplace, de cualquier directorio con --plugin-dir, o que Claude escribe durante una sesión
Una lista de marketplaces permitidos Un mod de los marketplaces que permites, o de cualquier directorio con --plugin-dir. Un mod que Claude escribe durante una sesión solo se carga cuando la lista de permitidos incluye skills-dir.
Una lista de marketplaces permitidos y disableSideloadFlags Un mod de los marketplaces que permites

Administra plugins para tu organización enumera las formas en que se carga un plugin y el ajuste que controla cada una.

Para revisar los mods de un marketplace antes de que tus usuarios los instalen, consulta Revisa lo que puede hacer un mod. Para impedir que se carguen los mods de los usuarios hasta que lo hayas hecho, consulta Impide que se carguen los mods instalados por los usuarios.

Revisa lo que puede hacer un mod

Puedes ver lo que un mod es capaz de hacer sin ejecutarlo. En tu shell, ejecuta claude plugin validate en el directorio del plugin:

claude plugin validate ./some-mod

Dos líneas de la salida describen el código del mod:

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

La línea hooks: enumera los eventos que recibe el mod. La línea calls: enumera los métodos de la API de mods que llama su código. La API de mods, escrita como $ en el código de un mod, es la forma en que un mod accede a archivos, procesos y la red. Claude Code se niega a cargar un mod que usa la API de mods de una forma que este comando no puede leer.

Busca estos en la línea calls::

Llamada Qué significa
$.fs.read, $.fs.write Lee o escribe archivos en cualquier lugar donde el usuario pueda hacerlo
$.process.run, $.process.spawn Inicia programas como el usuario
$.http.fetch Realiza solicitudes de red
$.env.get, $.settings.read Lee variables de entorno y la configuración, que pueden contener claves de API. Una línea env reads: en la salida nombra cada variable.
$.env.set Establece una variable de entorno para Claude Code y para cada comando y servidor MCP que inicie después, lo que puede cambiar lo que ejecutan esos programas. Una línea env writes: nombra cada variable.
$.mcp.call Llama a una herramienta en un servidor MCP conectado, según las reglas de permisos de la sesión
$.model.complete Usa el plan o la clave de API del usuario para llamadas al modelo
$.prompt.submit Envía un prompt y puede enviarlo como si fueran las propias palabras del usuario
$.session.send Envía un mensaje que lee el Claude de otra sesión o de un subagente

En la línea hooks:, tool.call y prompt.submit significan que el mod ve cada llamada a herramienta y cada prompt, y puede modificarlos. session.append significa que el mod puede reescribir cada fila de la conversación antes de que se almacene. ui.render{component=AskUserQuestion} significa que el mod puede volver a dibujar el diálogo que Claude usa para hacerle una pregunta al usuario. tool.check significa que el mod puede aprobar o denegar una llamada a herramienta antes de que aparezca una solicitud de permiso. Conoce lo que sucede de forma predeterminada enumera cuáles de tus reglas y hooks tienen precedencia sobre su respuesta.

Elige cuánto permitir

Las políticas de mods van desde no tener ningún mod instalado hasta permitir cualquier mod que elija un usuario, con tu propio mod revisando los demás, y cada una consiste en unos pocos ajustes administrados. Busca la política que quieres en la primera columna y configura lo que indica la segunda columna. Implementar la configuración administrada explica dónde se encuentra la configuración administrada.

Lo que quieres Configuración
Ningún mod instalado, sin afectar los hooks Configura allowManagedModsOnly y no implementes ningún mod propio
Ningún mod instalado y ningún hook en absoluto, incluidos tus hooks administrados Establece disableAllHooks en true
Solo los mods de tu organización Configura la opción allowManagedModsOnly de la protección e instala tus mods para que cuenten como tuyos
Cualquier mod de los marketplaces que apruebes Mantén tus restricciones de marketplaces y establece disableSideloadFlags en true
Cualquier mod, con tu propio mod revisando los demás Instala tu mod y agrégalo junto con sec-default@builtin en prependPlugins

Lo que hace cada ajuste:

  • allowManagedModsOnly: una opción de la protección integrada. Los mods propios de los usuarios no se cargan, y sus hooks de configuración, líneas de estado y /goal siguen funcionando. Impedir que se carguen los mods instalados por los usuarios enumera lo que abarca.
  • allowManagedHooksOnly: un ajuste más amplio. Solo se cargan los mods de tu organización y los mods integrados en Claude Code. Un mod que un usuario instaló por su cuenta no se carga. El ajuste también bloquea los hooks de los archivos de configuración propios de los usuarios. Lee Qué se ejecuta con allowManagedHooksOnly antes de configurarlo.
  • disableAllHooks: el ajuste más amplio. En la configuración administrada, detiene los mods de todos los plugins instalados, incluidos los tuyos, y desactiva todos los hooks de los archivos de configuración, por lo que un hook PreToolUse en tu configuración administrada ya no bloquea nada. Las líneas de estado personalizadas y /goal también dejan de funcionar. Lee disableAllHooks antes de configurarlo.
  • disableSideloadFlags: rechaza --plugin-dir y --plugin-url al iniciar, e impide que se carguen los mods que Claude escribe durante una sesión. El ajuste también rechaza --agents y --mcp-config. Lee disableSideloadFlags antes de configurarlo.

Los mods integrados en Claude Code, como la compatibilidad con AGENTS.md, no se ven afectados por estos ajustes. Cada uno tiene su propio interruptor.

Un usuario cuyo mod no se cargó encuentra el motivo en su registro de depuración. Mensajes de rechazo enumera las líneas para allowManagedHooksOnly y disableAllHooks, y Mensajes de la protección integrada tiene la línea para allowManagedModsOnly.

Permitir solo los mods de tu organización

Para ejecutar los mods de tu organización y bloquear los que traen los usuarios, implementa la configuración de la fila Solo los mods de tu organización de la tabla de políticas, además de disableSideloadFlags. Con este managed-settings.json completo, Claude Code rechaza los mods propios de los usuarios, por lo que no se ejecuta ninguno de sus hooks, y tu mod de políticas se ejecuta antes que los demás mods:

{
  "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
}

Cada grupo de claves cumple una función:

  • extraKnownMarketplaces, enabledPlugins y prependPlugins: instalan tu mod para que cuente como tuyo y lo ejecutan primero, con la protección después. Instalar los mods de tu organización y definir el orden explica el directorio al que apuntan estas claves.
  • pluginConfigs: configura la opción allowManagedModsOnly de la protección, para que Claude Code rechace los mods propios de los usuarios. Sus hooks de configuración, líneas de estado y /goal siguen funcionando.
  • disableSideloadFlags: consulta disableSideloadFlags para ver los flags que rechaza al iniciar

Para confirmar la política en una máquina de prueba, inicia una sesión en tu shell con claude --debug y lee el registro de depuración:

  • Tu mod: su línea hooks module tiene tier prepend
  • Un mod que instaló el usuario: una línea dice refused by cc-plugin-sec-default: mods are limited to your organization's by policy (allowManagedModsOnly). Una línea anterior indica que el módulo de hooks de ese mod está loaded, así que busca el rechazo.
  • Un directorio de plugins: claude --plugin-dir ./any-mod termina con un mensaje que comienza con --plugin-dir is disabled by your organization's managed settings (disableSideloadFlags)

Para limitar también qué marketplaces pueden agregar los usuarios, combina este archivo con tus restricciones de marketplaces.

Aplicar tus controles de plugins a los mods

Un mod es un plugin, así que las formas en que administras los plugins para tu organización también se aplican a un plugin que contiene un mod:

Definir opciones en la protección integrada

La protección integrada admite opciones. Configúralas en la configuración administrada bajo pluginConfigs, con la clave cc-plugin-sec-default@builtin, como hace el ejemplo de Impedir que se carguen los mods instalados por los usuarios.

La tabla muestra lo que obtienen tus usuarios con cada opción sin configurar y con ella establecida en true:

Opción Sin configurar true
allowManagedModsOnly Se cargan los mods propios de los usuarios Solo se cargan los mods de tu organización y los mods integrados en Claude Code. Claude Code rechaza cualquier otro mod, incluido uno que un usuario instaló o indicó con --plugin-dir.
allowModsToOverrideDenyRules Las reglas de denegación tienen precedencia sobre los mods de los usuarios Un mod de un usuario que aprueba llamadas a herramientas puede aprobar una llamada que una regla deny rechaza

Estas reglas deciden si una opción surte efecto:

  • El id tiene una sola forma aquí: Claude Code lee las opciones solo bajo cc-plugin-sec-default@builtin. prependPlugins también acepta sec-default@builtin, y pluginConfigs no.
  • Solo cuenta la configuración administrada: la misma entrada en un archivo de configuración de usuario, de proyecto o local, o en un archivo pasado con --settings, no configura una opción ni la flexibiliza
  • La protección tiene que cargarse: si configuras prependPlugins, incluye la protección en la lista. Donde la protección no se carga, no se aplica ninguna de las dos opciones.
  • La protección falla de forma cerrada: si la protección no puede leer la configuración administrada, rechaza todos los mods de los usuarios al cargarlos. Si no puede comprobar las reglas de denegación para una llamada que aprobó el mod de un usuario, rechaza la llamada.

Los mensajes de la protección integrada son lo que ven tus usuarios cuando se aplica cualquiera de las dos opciones.

Ejecuta los mods propios de tu organización

Puedes implementar mods propios para todos los usuarios, elegir dónde se ejecutan en relación con los mods de los usuarios y usar uno para aplicar una política.

Instala los mods de tu organización y establece el orden

Los mods de tu organización se cargan donde los mods de los usuarios no lo hacen y pueden ejecutarse antes que ellos, por lo que Claude Code tiene que poder saber que un mod proviene de ti. Trata un mod como de tu organización solo cuando se cumplen todas estas condiciones:

  • enabledPlugins en la configuración administrada establece el plugin del mod en true
  • La configuración administrada nombra el marketplace del plugin como un directorio en la máquina del usuario, mediante una ruta absoluta. Una entrada de extraKnownMarketplaces hace eso y además registra el marketplace para el usuario.
  • El marketplace enumera el plugin mediante una ruta relativa, de modo que Claude Code lo carga en su lugar desde ese directorio

Para cumplirlas, haz que tu sistema de administración de dispositivos copie el directorio del marketplace a la misma ruta en cada máquina. Haz que el directorio y todos los directorios por encima de él sean modificables solo por un administrador, igual que el archivo de configuración administrada. Cualquiera que pueda escribir allí puede reescribir tu mod. La configuración administrada que entregas desde la consola de administración de claude.ai puede incluir las claves, pero no puede colocar el directorio en una máquina.

El directorio contiene el manifiesto del marketplace y el plugin:

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

El manifiesto enumera el plugin por su ruta relativa a ese directorio:

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

Un plugin que Claude Code copia en su caché cuenta como de un usuario, incluso cuando enabledPlugins en la configuración administrada lo habilita. Eso abarca todos los plugins de una fuente de GitHub, git, URL o npm. Su mod se ejecuta entre los mods de los usuarios, prependPlugins y appendPlugins lo omiten, y no se carga con allowManagedModsOnly ni con allowManagedHooksOnly. El registro de depuración del usuario tiene una línea que comienza con el id del plugin y is enabled by managed settings, but.

Claude Code dispara un evento cada vez que está a punto de actuar, por ejemplo, ejecutar una herramienta, y lo pasa a cada mod por turnos. Un mod que cuenta como tuyo se ejecuta antes que los mods de los usuarios incluso cuando no lo enumeras en ningún lugar. Para establecer su posición, enumera su id en uno de dos ajustes. El id es el nombre del plugin, @ y el nombre del marketplace, como acme-guard@acme-tools.

  • prependPlugins: tu mod ve cada evento antes que cualquier mod de usuario y cada resultado después. Puede cambiar el evento, rechazarlo u omitir los mods de los usuarios.
  • appendPlugins: tu mod se ejecuta después de todos los mods de los usuarios, por lo que solo ve los eventos que esos mods transmiten, en la forma en que los transmiten

Este ejemplo declara el marketplace acme-tools en /opt/acme/claude-plugins, habilita acme-guard desde él y ejecuta ese mod primero, con la protección integrada después:

{
  "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"]
}

Cada clave cumple una función:

  • extraKnownMarketplaces: nombra el directorio que contiene el marketplace acme-tools. path es la ruta absoluta del directorio que contiene .claude-plugin/marketplace.json.
  • enabledPlugins: activa acme-guard para cada usuario que recibe esta configuración administrada
  • prependPlugins: coloca acme-guard en primer lugar y la protección integrada en segundo, ambos antes de cualquier mod que instale un usuario. Claude Code sigue el orden que enumeras.

Para confirmar que la máquina de un usuario recibió la configuración, consulta Comprobar que una política está en vigor.

Para confirmar dónde se ejecuta el mod, inicia una sesión en esa máquina con claude --debug y busca el id del mod en el registro de depuración:

  • hooks module acme-guard@acme-tools loaded, con tier prepend: el mod cuenta como de tu organización y se ejecuta primero
  • La misma línea con tier user: Claude Code lo trata como un mod de usuario. Una segunda línea, prependPlugins names acme-guard@acme-tools, which is not an enabled managed plugin with a hooks module; skipped, indica que la lista lo omitió.

Estas reglas deciden qué ids de las dos listas surten efecto:

  • La lista reemplaza el valor predeterminado: cuando estableces prependPlugins en la configuración administrada, nombra sec-default@builtin en ella para conservar la protección integrada. La protección está integrada y no necesita una entrada en enabledPlugins.
  • Tus propios ids deben contar como tuyos: en la configuración administrada, Claude Code omite un id cuyo plugin no cumple las condiciones de un mod de organización
  • Los repositorios no pueden establecerlos: Claude Code lee ambos ajustes de la configuración administrada y nunca del archivo de configuración de un repositorio. Un usuario puede establecerlos en ~/.claude/settings.json para ordenar sus propios mods solo en una máquina sin configuración administrada, y solo cuando no ha iniciado sesión con un plan Team o Enterprise. En cualquier otro caso, Claude Code ignora ambas claves en la configuración de usuario. Una lista allí ni agrega ni quita la protección integrada.

Aplica una política con un mod propio

Para impedir que se cargue cualquier mod de usuario, no necesitas un mod propio. Establece allowManagedModsOnly. Escribe un mod de políticas cuando quieras permitir algunos mods de usuarios y rechazar otros, o para registrar lo que hacen los mods.

Cada vez que otro mod está a punto de cargarse, tu mod recibe la lista que imprime claude plugin validate, en un evento llamado plugin.register. Un mod en prependPlugins puede leer esa lista y rechazar el mod. También puede manejar cualquier llamada de la API de mods por nombre para registrar o rechazar esa llamada para todos los demás mods. El nombre es el método sin el $., por lo que un hook en fs.write ve cada llamada a $.fs.write.

Este mod de políticas rechaza cualquier mod de usuario cuyo propio código llame a $.process.run o $.process.spawn. También mantiene un registro de auditoría, escribiendo en el registro de depuración cada llamada a herramienta y cada archivo que escribe un mod. Como se ejecuta primero, el registro guarda lo que se solicitó, antes de que cualquier mod de usuario lo cambie. Guárdalo como 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)
  })
}

El archivo registra tres hooks:

  • plugin.register: decide si otro mod se carga. Rechaza un mod de usuario que llama a un método bloqueado y deja pasar todos los demás mods.
  • tool.call: escribe una línea como audit tool.call Bash en el registro de depuración para cada llamada a herramienta, y no cambia nada
  • fs.write: escribe una línea como audit fs.write by reader "/tmp/notes.md" para cada llamada a $.fs.write que hace otro mod, y no cambia nada. El nombre del mod va primero y la ruta va entre comillas, de modo que una ruta que elige un mod no puede hacerse pasar por otro campo de la línea.

El hook plugin.register lee dos campos del evento:

  • e.tier: dónde se ejecutaría el mod, uno de prepend, user, append o builtin. Todo mod que instala una persona es user.
  • e.uses.calls: los métodos de la API de mods que llama el mod, cada uno escrito como namespace.method, por ejemplo process.run, sin el $. que imprime claude plugin validate

Cuando un usuario instala un mod que llama a $.process.run, el mod no se carga, y su registro de depuración tiene una línea que termina con refused by acme-guard: y tu motivo. El rechazo también llega a la transcripción en una sesión que recarga en caliente un directorio de plugin. Para bloquear una llamada sin rechazar el mod completo, devuelve { deny: 'your reason' } desde un hook en el nombre de esa llamada.

Para enviar las líneas de auditoría a otro lugar que no sea el registro de depuración, llama a $.http.fetch desde los mismos hooks.

Una sesión puede ejecutarse sin tu mod. Si el hilo de trabajo que ejecuta los mods instalados falla tres veces, Claude Code descarga todos los mods que no están integrados, incluido el tuyo, hasta que el usuario ejecute /reload-plugins o inicie una nueva sesión. Y un usuario que inicia Claude Code con --safe-mode se ejecuta sin mods instalados, incluido el tuyo.

Crear un mod cubre los archivos que necesita un mod. Probar un mod de políticas tiene un archivo de prueba para este mod de políticas.

Rechaza mods cuando tu comprobación falla

Si tu hook plugin.register lanza una excepción o excede su límite de tiempo, Claude Code omite el hook, por lo que la comprobación falla en modo abierto y el mod que estaba comprobando se carga. Para fallar en modo cerrado y rechazar los mods de los usuarios, mueve la comprobación a una función con nombre y agrega un manejador .catch que devuelva el rechazo. Esta versión del archivo muestra solo el hook plugin.register, así que conserva en register los dos hooks de auditoría de la primera versión:

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' }
  })
}

Con el manejador en su lugar, un mod que se estaba comprobando cuando la comprobación lanzó una excepción o agotó el tiempo no se carga, y la línea de rechazo lleva el segundo motivo, como en refused by acme-guard: Acme policy check failed, so this mod was not loaded. El manejador pasa a next(e) todos los mods fuera del nivel user, de modo que una comprobación fallida no detiene los mods que enumera tu organización. Manejar un hook que falla cubre .catch para otros eventos.

Próximos pasos