SpyBara
Go Premium

plugins/components.md 2026-09-24 22:57 UTC to 2026-09-25 23:58 UTC

This page contains 1130 additions and 0 deletions.

2026
Fri 25 23:58

Agregar componentes a un plugin

Agrega skills, hooks, servidores MCP y todos los demás tipos de componentes a un plugin de Claude Code, con un ejemplo que valida cada uno.

export const Piece = ({id, children}) =>

{children}
;

export const PluginExplorer = ({children}) => { const PIECES = [{ id: 'manifest', name: 'Manifest', path: '.claude-plugin/plugin.json', required: "Required by Anthropic's directory", lines: [{ depth: 0, kind: 'folder', text: '.claude-plugin/' }, { depth: 1, kind: 'file', text: 'plugin.json' }], href: '/en/plugins/manifest-reference#manifest-file', linkText: 'Go to the manifest reference' }, { id: 'skills', name: 'Skills', path: 'skills/review/SKILL.md', lines: [{ depth: 0, kind: 'folder', text: 'skills/' }, { depth: 1, kind: 'folder', text: 'review/' }, { depth: 2, kind: 'file', text: 'SKILL.md' }], href: '/en/plugins/components#skills', linkText: 'Go to the Skills section' }, { id: 'commands', name: 'Commands', path: 'commands/about.md', lines: [{ depth: 0, kind: 'folder', text: 'commands/' }, { depth: 1, kind: 'file', text: 'about.md' }], href: '/en/plugins/components#commands', linkText: 'Go to the Commands section' }, { id: 'agents', name: 'Agents', path: 'agents/security-reviewer.md', lines: [{ depth: 0, kind: 'folder', text: 'agents/' }, { depth: 1, kind: 'file', text: 'security-reviewer.md' }], href: '/en/plugins/components#agents', linkText: 'Go to the Agents section' }, { id: 'hooks', name: 'Hooks', path: 'hooks/hooks.json', lines: [{ depth: 0, kind: 'folder', text: 'hooks/' }, { depth: 1, kind: 'file', text: 'hooks.json' }], href: '/en/plugins/components#hooks', linkText: 'Go to the Hooks section' }, { id: 'monitors', name: 'Monitors', path: 'monitors/monitors.json', lines: [{ depth: 0, kind: 'folder', text: 'monitors/' }, { depth: 1, kind: 'file', text: 'monitors.json' }], href: '/en/plugins/components#monitors', linkText: 'Go to the Monitors section' }, { id: 'output-styles', name: 'Output styles', path: 'output-styles/terse.md', lines: [{ depth: 0, kind: 'folder', text: 'output-styles/' }, { depth: 1, kind: 'file', text: 'terse.md' }], href: '/en/plugins/components#themes-and-output-styles', linkText: 'Go to the Themes and output styles section' }, { id: 'themes', name: 'Themes', path: 'themes/dracula.json', lines: [{ depth: 0, kind: 'folder', text: 'themes/' }, { depth: 1, kind: 'file', text: 'dracula.json' }], href: '/en/plugins/components#themes-and-output-styles', linkText: 'Go to the Themes and output styles section' }, { id: 'workflows', name: 'Workflows', path: 'workflows/audit-routes.js', lines: [{ depth: 0, kind: 'folder', text: 'workflows/' }, { depth: 1, kind: 'file', text: 'audit-routes.js' }], href: '/en/workflows#distribute-a-workflow-in-a-plugin', linkText: 'Go to Distribute a workflow in a plugin' }, { id: 'bin', name: 'Executables', path: 'bin/hello-plugin', lines: [{ depth: 0, kind: 'folder', text: 'bin/' }, { depth: 1, kind: 'file', text: 'hello-plugin' }], href: '/en/plugins/components#executables', linkText: 'Go to the Executables section' }, { id: 'scripts', name: 'Scripts', path: 'scripts/format.sh', lines: [{ depth: 0, kind: 'folder', text: 'scripts/' }, { depth: 1, kind: 'file', text: 'format.sh' }], href: '/en/plugins/components#hooks', linkText: 'Go to the Hooks section' }, { id: 'settings', name: 'Default settings', path: 'settings.json', lines: [{ depth: 0, kind: 'file', text: 'settings.json' }], href: '/en/plugins/components#default-settings', linkText: 'Go to the Default settings section' }, { id: 'mcp', name: 'MCP servers', path: '.mcp.json', lines: [{ depth: 0, kind: 'file', text: '.mcp.json' }], href: '/en/plugins/components#mcp-servers', linkText: 'Go to the MCP servers section' }, { id: 'lsp', name: 'LSP servers', path: '.lsp.json', lines: [{ depth: 0, kind: 'file', text: '.lsp.json' }], href: '/en/plugins/components#lsp-servers', linkText: 'Go to the LSP servers section' }]; const [selectedId, setSelectedId] = useState('manifest'); const [isFullscreen, setIsFullscreen] = useState(false); const rootRef = useRef(null); useEffect(() => { const onFsChange = () => setIsFullscreen(!!document.fullscreenElement); document.addEventListener('fullscreenchange', onFsChange); return () => document.removeEventListener('fullscreenchange', onFsChange); }, []); const toggleFullscreen = () => { if (!rootRef.current) return; if (document.fullscreenElement) document.exitFullscreen(); else rootRef.current.requestFullscreen().catch(() => {}); }; const selected = PIECES.find(p => p.id === selectedId) || PIECES[0]; const onTreeKeyDown = e => { const keys = ['ArrowDown', 'ArrowUp', 'Home', 'End']; if (keys.indexOf(e.key) === -1) return; const i = PIECES.findIndex(p => p.id === selectedId); let next = i; if (e.key === 'ArrowDown') next = Math.min(PIECES.length - 1, i + 1); if (e.key === 'ArrowUp') next = Math.max(0, i - 1); if (e.key === 'Home') next = 0; if (e.key === 'End') next = PIECES.length - 1; e.preventDefault(); if (next === i) return; const id = PIECES[next].id; setSelectedId(id); const el = document.getElementById('pe-node-' + id); if (el) el.focus(); }; const FolderIcon = () => ; const FileIcon = () => ; return <div ref={rootRef} className={isFullscreen ? 'pe-root pe-fullscreen not-prose' : 'pe-root not-prose'} data-selected={selected.id}>

  <div className="pe-head">
    <div className="pe-head-text">
      <div className="pe-title">What goes in a plugin</div>
      <div className="pe-sub">This example plugin, <code>my-plugin</code>, has one of every kind of component, each in its default location. Select a file or folder to read what it’s for and see what goes in it.</div>
    </div>
    <button type="button" className="pe-fs-btn" onClick={toggleFullscreen} aria-label={isFullscreen ? 'Exit fullscreen' : 'Fullscreen'} title={isFullscreen ? 'Exit fullscreen' : 'Fullscreen'}>
      {isFullscreen ? '⤡' : '⛶'}
    </button>
  </div>

  <div className="pe-body">
    <div className="pe-tree-pane">
      <div className="pe-caption" id="pe-tree-caption">Plugin directory</div>
      <div role="group" aria-labelledby="pe-tree-caption" onKeyDown={onTreeKeyDown}>
        <div className="pe-rootline"><FolderIcon /><span>my-plugin/</span></div>
        {PIECES.map(p => <button key={p.id} id={'pe-node-' + p.id} type="button" className="pe-node" aria-pressed={p.id === selected.id} aria-label={p.name + ', ' + p.path} onClick={() => setSelectedId(p.id)}>
            {p.lines.map((line, i) => <span key={i} className="pe-line pe-line-tree" style={{
paddingLeft: line.depth * 18 + 'px'

}}> {line.kind === 'folder' ? : } {line.text} {p.required && i === p.lines.length - 1 ? {p.required} : null} )} {p.path} {p.required ? {p.required} : null} )}

    <div className="pe-panel" role="region" aria-labelledby="pe-panel-caption" aria-live="polite" aria-atomic="true">
      <div className="pe-caption" id="pe-panel-caption">Selected piece</div>
      <div className="pe-name">{selected.name}{selected.required ? <span className="pe-req">{selected.required}</span> : null}</div>
      <div className="pe-path">{selected.path}</div>

      <div className="pe-block">{children}</div>

      <a className="pe-link" href={selected.href}>{selected.linkText}</a>
    </div>
  </div>
</div>;

};

Un plugin de Claude Code se construye a partir de componentes, como skills, agentes, hooks y servidores MCP. Cada componente tiene una carpeta predeterminada en el plugin, una clave de manifiesto opcional en .claude-plugin/plugin.json que reemplaza o se suma a esa carpeta, y un nombre que ve el usuario. Para la tabla de campos completa de cada clave, consulte la referencia de manifiesto.

Utilice esta página para agregar un componente a un plugin que ya se carga.

Después de agregar un componente, ejecute /reload-plugins en una sesión en ejecución o inicie una nueva para que Claude Code lo cargue. Para verificar el archivo del componente antes de cargarlo, ejecute claude plugin validate . en su shell desde el directorio del plugin.

Explorar el directorio del plugin

El explorador muestra un plugin de ejemplo, my-plugin, que tiene uno de cada tipo de componente en su ubicación predeterminada:

Cada archivo es el ejemplo válido más pequeño de su formato, presente para mostrar la forma en lugar de ser útil: una skill o agente real lleva instrucciones completas y a menudo archivos de apoyo, y un hook o monitor real realiza trabajo real. Las secciones después del explorador utilizan los mismos archivos que sus ejemplos y enlazan a otros más completos. Seleccione un archivo o carpeta para leer para qué sirve, ver qué va en él y encontrar la sección que lo cubre.

El [manifiesto](/docs/es/plugins/manifest-reference) es el archivo `plugin.json` en el directorio `.claude-plugin/` de un plugin. Contiene los metadatos del plugin y los valores de `userConfig` que Claude Code solicita al usuario. Solo `name` es obligatorio. En este, `description` es el texto que los usuarios ven para el plugin en `/plugin`, y `version` mantiene a los usuarios en esa versión hasta que la cambie:
```json theme={null}
{
  "name": "my-plugin",
  "version": "1.0.0",
  "description": "Review, formatting, and database tools for this team"
}
```
Una [skill](/docs/es/skills) es un archivo `SKILL.md`. Guarde cada skill en su propio directorio bajo `skills/`. Claude lee la `description` de cada skill, y cuando lo que el usuario pregunta coincide con ella, como pedirle a Claude que revise una solicitud de extracción aquí, Claude carga las instrucciones de la skill y las sigue. El usuario también puede ejecutarla directamente como `/my-plugin:review`:
```markdown theme={null}
---
description: Reviews a pull request for style and test coverage. Use when asked to review code.
---

Review the changed files. Report style problems first, then missing tests.
```
Un comando es un único archivo Markdown que el usuario ejecuta por nombre. Los comandos son el formato anterior: una skill se ejecuta por nombre de la misma manera y también puede llevar archivos de apoyo en su propio directorio, así que escriba los nuevos como skills y mantenga `commands/` para los archivos que ya tiene. Este archivo se convierte en `/my-plugin:about` y toma el mismo frontmatter que una skill:
```markdown theme={null}
---
description: Summarize the repository
---

Summarize what this repository does in three sentences.
```
Un [subagente](/docs/es/sub-agents) es un asistente separado, con sus propias instrucciones y su propia ventana de contexto, al que Claude puede delegar una tarea y obtener un resultado. Cada archivo Markdown bajo `agents/` define uno: el frontmatter lo nombra y dice cuándo usarlo, y el cuerpo es su indicación del sistema. Este se llama `my-plugin:security-reviewer`, y el usuario puede invocarlo con `@agent-my-plugin:security-reviewer`:
```markdown theme={null}
---
name: security-reviewer
description: Reviews code changes for security issues. Use after edits to authentication or input handling.
model: sonnet
---

You are a security reviewer. Read the changed files and report injection, authentication, and secrets-handling risks.
```
Un [hook](/docs/es/hooks-guide) ejecuta algo automáticamente en un punto del ciclo de vida de Claude Code, como después de cada edición de archivo: un comando de shell, una solicitud HTTP, una llamada a herramienta MCP, un indicador a un modelo o un subagente. Guarde los hooks del plugin en `hooks/hooks.json` en la raíz del plugin. Este ejecuta el script `scripts/format.sh` del plugin después de que Claude escribe o edita un archivo:
```json theme={null}
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "\"${CLAUDE_PLUGIN_ROOT}/scripts/format.sh\""
          }
        ]
      }
    ]
  }
}
```
Un monitor es un comando de shell que Claude Code inicia en segundo plano cuando la sesión comienza y mantiene en ejecución hasta que termina, utilizando la [herramienta Monitor](/docs/es/tools-reference#monitor-tool). Lo que imprime llega a Claude como notificaciones. Un campo `when` puede iniciarlo la primera vez que se ejecuta una skill nombrada. Este rastrea un registro de errores:
```json theme={null}
[
  {
    "name": "error-log",
    "command": "tail -F ./logs/error.log",
    "description": "Application error log"
  }
]
```
Un plugin puede incluir [estilos de salida](/docs/es/output-styles), que cambian cómo Claude formatea y expresa sus respuestas. Guarde cada estilo de salida como `output-styles/.md`. Este aparece en `/output-style` como `my-plugin:terse`:
```markdown theme={null}
---
name: terse
description: Answer in as few words as possible
keep-coding-instructions: true
---

Keep every reply short. Skip preambles and summaries.
```
Un plugin puede incluir [temas de color](/docs/es/terminal-config#create-a-custom-theme) para la interfaz de Claude Code. Guarde cada tema como `themes/.json`. Este aparece en `/theme` como `Dracula`, marcado como de `my-plugin`:
```json theme={null}
{
  "name": "Dracula",
  "base": "dark",
  "overrides": {
    "claude": "#bd93f9",
    "error": "#ff5555"
  }
}
```
La carpeta `workflows/` contiene archivos [workflow](/docs/es/workflows) `.js`: un bloque `meta`, luego un cuerpo de script que orquesta varios subagentes. Este se ejecuta como `/my-plugin:audit-routes`:
```javascript theme={null}
export const meta = {
  name: 'audit-routes',
  description: 'Audit every route handler for missing auth checks',
}

const found = await agent('List every .ts file under src/routes/.', {
  schema: { type: 'object', required: ['files'], properties: { files: { type: 'array', items: { type: 'string' } } } },
})

const audits = await pipeline(found.files, file =>
  agent(`Audit ${file} for missing authentication checks.`, { label: file }),
)

return audits.filter(Boolean)
```
`bin/` es cómo un plugin envía una herramienta de línea de comandos. Mientras el plugin está habilitado, Claude Code coloca esta carpeta en el `PATH` del shell en el que ejecuta comandos, para que Claude, o las instrucciones de una skill, puedan ejecutar la herramienta por nombre sin que el usuario instale nada. Con este [ejecutable](#executables) en su lugar, `hello-plugin` es un comando que Claude puede ejecutar:
```bash theme={null}
#!/bin/bash
echo "hello from my-plugin"
```
El hook en `hooks/hooks.json` ejecuta un script, y esta carpeta es donde el ejemplo lo mantiene. El nombre `scripts/` es una convención, no algo que Claude Code busque: el hook apunta al archivo por su ruta, `${CLAUDE_PLUGIN_ROOT}/scripts/format.sh`. Un script de formateador podría verse así:
```bash theme={null}
#!/bin/bash
npx prettier --write .
```
Un `settings.json` en la raíz del plugin contiene [configuración](/docs/es/settings-reference) que se aplica mientras el plugin está habilitado, para que un plugin pueda cambiar cómo se comporta la sesión y no solo agregar componentes. Solo dos claves tienen efecto desde un plugin, [`agent`](/docs/es/settings-reference#agent) y [`subagentStatusLine`](/docs/es/settings-reference#subagentstatusline); todas las demás claves se descartan. Consulte [Configuración predeterminada](#default-settings).
Este establece `agent`, que ejecuta el hilo principal de la sesión como el agente `security-reviewer` del plugin, para que el indicador del sistema de ese agente, las restricciones de herramientas y el modelo se apliquen a toda la sesión:

```json theme={null}
{
  "agent": "security-reviewer"
}
```
Un [servidor MCP](/docs/es/mcp) proporciona a Claude herramientas de un sistema externo. Declárelo en `.mcp.json` en la raíz del plugin. Este inicia un servidor local desde un script dentro del plugin y aparece en `/mcp` como `plugin:my-plugin:db`:
```json theme={null}
{
  "mcpServers": {
    "db": {
      "command": "node",
      "args": ["${CLAUDE_PLUGIN_ROOT}/server.js"]
    }
  }
}
```
Un servidor LSP proporciona a Claude [diagnósticos y navegación de código](/docs/es/plugins/code-intelligence) para un lenguaje. Declare el servidor en `.lsp.json` en la raíz del plugin. Este conecta el servidor de lenguaje Go para archivos `.go`:
```json theme={null}
{
  "gopls": {
    "command": "gopls",
    "args": ["serve"],
    "extensionToLanguage": {
      ".go": "go"
    }
  }
}
```

Agregar cada tipo de componente

Cada sección a continuación cubre un tipo de componente: dónde van sus archivos en el plugin, un ejemplo que valida, qué ve el usuario una vez que se carga el plugin, y la clave de manifiesto que cambia la ubicación predeterminada. Agregue los que su plugin necesite; ninguno es obligatorio.

Skills

Una skill es un archivo SKILL.md que Claude puede cargar cuando su descripción coincide con la tarea. El usuario también puede ejecutarla como un comando. Guarde cada skill en su propio directorio bajo skills/:

my-plugin/
├── .claude-plugin/
│   └── plugin.json
└── skills/
    └── review/
        └── SKILL.md

Dé al SKILL.md una description para que Claude sepa cuándo usarla:

---
description: Reviews a pull request for style and test coverage. Use when asked to review code.
---

Review the changed files. Report style problems first, then missing tests.

Después de cargar el plugin, /my-plugin:review ejecuta la skill. El nombre del comando y quién puede invocarlo siguen estas reglas:

También puede colocar skills fuera del directorio predeterminado skills/:

Para incluir instrucciones en un plugin, escríbalas como una skill. Claude Code no carga un CLAUDE.md en la raíz del plugin, y claude plugin validate advierte CLAUDE.md at the plugin root is not loaded as project context.

Para campos de frontmatter y archivos de apoyo, consulte Skills.

Comandos

Un comando es un único archivo Markdown que el usuario ejecuta por nombre, como /my-plugin:about.

Guarde un comando en commands/<file>.md y se convierte en /<plugin>:<file>. Un subdirectorio agrega un segmento, así que commands/db/migrate.md es /my-plugin:db:migrate.

Los archivos de comando toman el mismo frontmatter que las skills.

Definir comandos en el manifiesto

Solo necesita esto si desea mantener archivos de comando en algún lugar que no sea commands/, o para definir un comando corto dentro de plugin.json sin un archivo Markdown separado. Establezca la clave de manifiesto commands, y Claude Code la lee en lugar de escanear commands/. La clave toma una ruta, una matriz de rutas, u un objeto que asigna cada nombre de comando a un archivo source o contenido content en línea.

Este manifiesto define /my-plugin:about en línea, sin archivo Markdown:

{
  "name": "my-plugin",
  "commands": {
    "about": {
      "content": "Summarize what this repository does in three sentences.",
      "description": "Summarize the repository"
    }
  }
}

Cargue el plugin y ejecute /my-plugin:about en la sesión para confirmar que se cargó.

Para la sintaxis completa de la clave, consulte commands.

Agentes

Un subagente es un asistente separado, con sus propias instrucciones y ventana de contexto, al que Claude puede delegar una tarea. Cada archivo Markdown bajo agents/ define uno:

---
name: security-reviewer
description: Reviews code changes for security issues. Use after edits to authentication or input handling.
model: sonnet
---

You are a security reviewer. Read the changed files and report injection, authentication, and secrets-handling risks.

Este agente se llama my-plugin:security-reviewer, y el usuario puede invocarlo explícitamente con @agent-my-plugin:security-reviewer. La forma del nombre es <plugin>:<name>, donde <name> viene del frontmatter, o del nombre del archivo cuando no hay ninguno.

La clave de manifiesto agents reemplaza el escaneo de agents/.

Organizar agentes en subcarpetas

Puede colocar archivos de agente del plugin en subcarpetas de agents/. Claude Code los carga recursivamente y une el nombre del plugin, cada nombre de subcarpeta y el nombre del archivo con dos puntos para formar el nombre con alcance del agente. Por ejemplo, agents/review/security.md en un plugin llamado my-plugin se carga como my-plugin:review:security. Dos configuraciones cambian ese nombre:

Campos de frontmatter en agentes de plugin

El frontmatter de un agente de plugin sigue estas reglas:

Para ver qué hace cada campo y las reglas de precedencia, consulte Subagentes.

Hooks

Un hook ejecuta algo automáticamente en un punto del ciclo de vida de Claude Code, como después de cada edición de archivo: un comando de shell, una solicitud HTTP, una llamada a herramienta MCP, un indicador a un modelo o un subagente. Guarde los hooks del plugin en hooks/hooks.json en la raíz del plugin, bajo una clave "hooks" de nivel superior, en la misma forma que el objeto hooks en settings.json. Eso le permite copiar un hook de configuración existente sin cambios.

Este hook ejecuta un script incluido después de cada Write o Edit:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "\"${CLAUDE_PLUGIN_ROOT}/scripts/format.sh\""
          }
        ]
      }
    ]
  }
}

Guarde el script en scripts/format.sh y hágalo ejecutable.

Cargue el plugin y pida a Claude que edite un archivo. Un hook PostToolUse que sale con 0 no muestra nada en la transcripción, así que confirme que se ejecutó con registro de depuración o por lo que el script mismo cambia.

Los hooks en hooks/hooks.json y en la clave de manifiesto hooks se cargan ambos. Para cada evento y su carga útil, consulte Eventos de hook.

Cuándo se activan los hooks del plugin

Los hooks de un plugin no esperan a que se use una de las skills o comandos del plugin. Claude Code los registra cuando una sesión carga el plugin, y se activan en sus eventos a partir de entonces. Para limitar cuándo se ejecuta un hook, reduzca su matcher.

Si un hook nunca se activa, consulte hooks que no se activan.

Entorno, entrecomillado y coincidencia de herramientas MCP

El entorno del hook, el entrecomillado de ${CLAUDE_PLUGIN_ROOT} y los matchers para las herramientas MCP propias del plugin funcionan de la siguiente manera:

Servidores MCP

Un servidor MCP proporciona a Claude herramientas de un sistema externo. Declárelo en .mcp.json en la raíz del plugin, en la misma forma que un .mcp.json de proyecto. Este .mcp.json declara un servidor llamado db:

{
  "mcpServers": {
    "db": {
      "command": "node",
      "args": ["${CLAUDE_PLUGIN_ROOT}/server.js"]
    }
  }
}

También puede omitir el contenedor mcpServers y poner db en el nivel superior del archivo.

Cargue el plugin y ejecute /mcp para confirmar que el servidor aparece como plugin:my-plugin:db.

claude plugin validate verifica .mcp.json e informa una entrada de servidor que Claude Code descartaría en el tiempo de carga como un error. Requiere Claude Code v2.1.281 o posterior.

Para ver dónde aparece una entrada incorrecta en el tiempo de carga, consulte Servidores MCP que no se inician.

La clave de manifiesto mcpServers toma un mapa de servidor en línea, una ruta a un archivo JSON, o una matriz de esos. Cuando un servidor de manifiesto tiene el mismo nombre que uno en .mcp.json, el servidor de manifiesto lo reemplaza.

Alcanzar usuarios en claude.ai y Cowork

Un servidor stdio local, como el servidor db bajo Servidores MCP, se ejecuta en Claude Code y en una sesión de Cowork que se ejecuta en su máquina en la aplicación Claude Desktop, pero no en claude.ai. Para alcanzar a los usuarios allí también, haga referencia a un servidor remoto por su URL https://, que claude.ai y Cowork ofrecen al usuario como un conector.

Nombres de servidor, nombres de herramientas y recargas

Los nombres del servidor, la sustitución de variables y el comportamiento de recarga siguen estas reglas:

Incluir un servidor MCPB empaquetado

La clave mcpServers también acepta un servidor empaquetado como un archivo MCPB, cuya extensión es .mcpb o la anterior .dxt. Apunte la clave al archivo, como una ruta dentro del plugin o una URL https://:

{
  "name": "my-plugin",
  "mcpServers": "./servers/db.mcpb"
}

El servidor toma su nombre del name en el manifiesto del paquete.

Para transportes y autenticación, consulte MCP.

Servidores LSP

Un servidor LSP proporciona a Claude diagnósticos y navegación de código para un lenguaje. Si un plugin oficial de inteligencia de código ya cubre su lenguaje, instale ese en su lugar de escribir uno. De lo contrario, declare el servidor en .lsp.json en la raíz del plugin:

{
  "gopls": {
    "command": "gopls",
    "args": ["serve"],
    "extensionToLanguage": {
      ".go": "go"
    }
  }
}

El archivo asigna cada nombre de servidor directamente a su configuración, sin un objeto contenedor alrededor del mapa. command es el nombre del binario, con sus argumentos en args. extensionToLanguage necesita al menos una extensión, cada una comenzando con ..

claude plugin validate no lee este archivo. Cuando cualquier entrada es inválida, todo el archivo se omite en la carga y Invalid LSP server config for ".lsp.json" aparece en la pestaña Errors de /plugin.

Su plugin configura la conexión pero no instala el binario del servidor, y cada extensión de archivo obtiene un servidor:

La clave de manifiesto lspServers toma el mismo mapa en línea, una ruta a un archivo JSON, o una matriz de esos, y sus servidores se suman a los de .lsp.json. Cuando un servidor de manifiesto tiene el mismo nombre que uno en .lsp.json, el servidor de manifiesto lo reemplaza.

Para transport, tiempos de espera, reinicios y los otros campos, consulte lspServers.

Envíe la salida de registro a stderr, no a stdout. Claude Code lee el stdout de un servidor solo como mensajes de protocolo, y acepta encabezados de mensaje de hasta 64 KiB y un cuerpo de mensaje de hasta 32 MiB.

Claude Code desconecta un servidor que excede cualquiera de los límites o escribe salida que no es de protocolo a stdout, y cuenta la desconexión como un bloqueo para restartOnCrash y maxRestarts. Cuando ejecuta con --debug, Claude Code escribe un error que nombra la causa en el registro de depuración.

Ejecutables

Los archivos en bin/ en la raíz del plugin están en el PATH del shell de la herramienta Bash mientras el plugin está habilitado, para que Claude pueda ejecutarlos como comandos simples. Agregue un script ejecutable:

#!/bin/bash
echo "hello from my-plugin"

Hágalo ejecutable con chmod +x bin/hello-plugin y cargue el plugin. Cuando pide a Claude que ejecute hello-plugin, el resultado de la herramienta Bash muestra la salida del script.

Los directorios bin/ del plugin vienen después de las entradas PATH propias del usuario, así que un plugin no puede sombrear git, ls u otro comando del sistema.

claude.ai y Cowork no instalan un plugin que tenga un directorio bin/ de nivel superior, incluido uno que distribuya a través de la configuración de la organización de claude.ai.

Configuración predeterminada

Para establecer valores predeterminados que se apliquen mientras el plugin está habilitado, agregue un settings.json en la raíz del plugin, o coloque el mismo objeto en línea en la clave de manifiesto settings. Dos claves tienen efecto, agent y subagentStatusLine, y todas las demás claves se descartan.

Establezca agent para ejecutar uno de los agentes propios del plugin como el hilo principal:

{
  "agent": "security-reviewer"
}

Cargue el plugin e inicie una sesión. Claude entonces responde en la conversación principal con el indicador del sistema del agente security-reviewer y el modelo.

Para todo lo que controla la clave, consulte la configuración agent.

Cuando la misma clave se establece en más de un lugar, estas reglas deciden qué valor se aplica:

Para la forma subagentStatusLine, consulte líneas de estado de subagente.

Temas y estilos de salida

Un plugin puede incluir temas de color y estilos de salida. Ambos aparecen en los mismos selectores que los del usuario. Para cualquiera de los dos, establecer la clave de manifiesto reemplaza el escaneo de carpeta.

Componente Guardar como Formato Aparece en Clave de manifiesto
Tema themes/<slug>.json El formato de archivo de tema personalizado que los usuarios escriben en ~/.claude/themes/ /theme, bajo el name del archivo experimental.themes
Estilo de salida output-styles/<name>.md El formato de estilo de salida personalizado, con frontmatter name y description /output-style, como <plugin>:<name> outputStyles

Los temas del plugin son de solo lectura, así que cuando un usuario edita uno en /theme, la edición se guarda como una copia en su propio directorio de temas.

Este tema recolora el acento del indicador y el texto de error en el preajuste oscuro:

{
  "name": "Dracula",
  "base": "dark",
  "overrides": {
    "claude": "#bd93f9",
    "error": "#ff5555"
  }
}

Canales

Un canal permite que un sistema externo como una aplicación de chat envíe mensajes a una sesión. En un plugin, un canal es uno de los servidores MCP más una entrada channels que se vincula a él y puede solicitar su propia configuración. Este manifiesto vincula un canal a un servidor telegram y solicita un token de bot:

{
  "name": "my-plugin",
  "mcpServers": {
    "telegram": {
      "command": "node",
      "args": ["${CLAUDE_PLUGIN_ROOT}/server.js"],
      "env": { "BOT_TOKEN": "${user_config.bot_token}" }
    }
  },
  "channels": [
    {
      "server": "telegram",
      "userConfig": {
        "bot_token": {
          "type": "string",
          "title": "Bot token",
          "description": "Telegram bot token",
          "sensitive": true
        }
      }
    }
  ]
}

server debe coincidir con una clave en mcpServers. El userConfig por canal toma la misma forma que la clave userConfig de nivel superior.

Para lo que el servidor debe implementar y cómo los usuarios habilitan un plugin de canal, consulte Empaquetar como un plugin en la referencia de canales. Para la tabla de campos, consulte channels.

Monitores

Un monitor es un comando de shell que se ejecuta en segundo plano durante toda la sesión. Lo que imprime llega a Claude como notificaciones, para que Claude pueda reaccionar a un registro o un cambio de estado sin que se le pida que lo observe. Guarde las entradas en monitors/monitors.json:

[
  {
    "name": "error-log",
    "command": "tail -F ./logs/error.log",
    "description": "Application error log"
  }
]

El comando se ejecuta en un shell, en el directorio de trabajo en el que comenzó la sesión.

El comando de un monitor está limitado en dónde comienza y qué puede referenciar:

La clave de manifiesto experimental.monitors toma la misma matriz en línea o una ruta a un archivo JSON, y se lee en lugar de monitors/monitors.json.

Para el disparador when y los otros campos, consulte monitors.

Pedir al usuario valores de configuración

Declare los valores que su plugin necesita del usuario en la clave de manifiesto userConfig, para que los usuarios no editen settings.json ellos mismos. Cada opción aparece en un diálogo con su title como etiqueta y su description debajo.

Establezca "sensitive": true para un token o contraseña. El diálogo entonces enmascara la entrada, y el valor se almacena en almacenamiento seguro en lugar de settings.json.

Este manifiesto solicita un punto final y un token:

{
  "name": "my-plugin",
  "userConfig": {
    "api_url": {
      "type": "string",
      "title": "API URL",
      "description": "Base URL of your team's API"
    },
    "api_token": {
      "type": "string",
      "title": "API token",
      "description": "Token for your team's API",
      "sensitive": true
    }
  }
}

Cuándo aparece el diálogo de configuración

El diálogo aparece solo en la interfaz interactiva /plugin. Se abre para cualquier opción que aún no esté establecida cuando el usuario hace cualquiera de lo siguiente:

Para abrir el mismo diálogo en cualquier momento, el usuario ejecuta /plugin configure <plugin>@<marketplace>.

El comando de shell claude plugin install nunca solicita valores de userConfig. Para establecer valores desde el shell, pase cada uno como --config KEY=VALUE. Cuando las opciones permanecen sin establecer, el comando imprime una línea userConfig options not yet set que nombra ambas formas de establecerlas. El diálogo userConfig nunca aparece cita la línea.

Para los campos de opción, dónde se almacena cada valor, cómo un componente hace referencia a un valor guardado, y qué campos rechazan ${user_config.*}, consulte Configuración del usuario.

Hacer referencia a rutas de plugin y almacenar datos

No sabe dónde se instalará su plugin, así que haga referencia a sus archivos y datos a través de estas variables en lugar de rutas fijas. Se sustituyen en contenido de skill, comando y agente, en comandos de hook y monitor, y en configuraciones de servidor MCP y LSP. También se exportan a procesos de hook, MCP y LSP:

En la ruta del directorio de datos, <id> es el identificador del plugin con cada carácter que no sea letra, dígito, _ y - reemplazado por -, así que my-plugin@my-marketplace se convierte en my-plugin-my-marketplace.

En Windows, las rutas sustituidas usan barras diagonales para que un shell no lea las barras invertidas como escapes.

Instalar dependencias en el directorio de datos

Para un plugin instalado desde marketplace, Claude Code instala automáticamente dependencias de paquetes Node.js elegibles cuando almacena en caché el plugin, así que es posible que no necesite instalarlas usted mismo. Cuando lo hace, este hook SessionStart instala node_modules en ${CLAUDE_PLUGIN_DATA} en la primera ejecución y nuevamente después de que una actualización cambie package.json:

{
  "hooks": {
    "SessionStart": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "diff -q \"${CLAUDE_PLUGIN_ROOT}/package.json\" \"${CLAUDE_PLUGIN_DATA}/package.json\" >/dev/null 2>&1 || (cd \"${CLAUDE_PLUGIN_DATA}\" && cp \"${CLAUDE_PLUGIN_ROOT}/package.json\" . && npm install) || rm -f \"${CLAUDE_PLUGIN_DATA}/package.json\""
          }
        ]
      }
    ]
  }
}

Después de la primera sesión, ~/.claude/plugins/data/<id>/node_modules existe. Un servidor MCP puede entonces establecer NODE_PATH a ${CLAUDE_PLUGIN_DATA}/node_modules en su env. Para qué campos sustituyen qué variable, consulte Variables de entorno.

Próximos pasos