Skip to content

Manual de referencia de plugins: Empaquetar y distribuir tu configuración

📚 Navegación de la serie: El artículo anterior 37 Checkpoints (puntos de control) te enseñó cómo revertir estados en la conversación y recuperar versiones previas del código. En este artículo abordaremos el desarrollo de extensiones: el artículo 24 te enseñó a "usar plugins de otros"; este te enseñará a "crear tus propios plugins". Veremos cómo estructurar la carpeta del plugin, qué opciones tiene el archivo plugin.json, qué componentes puedes empaquetar, cómo definir dependencias y cómo publicar tu mercado (marketplace) para tu equipo. Esta es la guía de referencia de desarrollo de plugins.

Al ejecutar claude plugin details en un plugin, verás datos interesantes sobre su consumo: este plugin ocupa unos 180 tokens por sesión de forma fija; y sus dos skills integrados consumen unos 2400 y 1800 tokens adicionales cuando se ejecutan.

Un plugin sencillo consume tokens por el hecho de estar registrado. Es importante entender que un plugin no es una caja negra: se compone de componentes específicos, y el consumo y comportamiento de cada uno de ellos se puede analizar y configurar. Comprender esta estructura te permitirá crear tus propios desarrollos de forma limpia.

En el artículo 24 aprendimos a utilizar plugins: añadir mercados, instalar, recargar con /reload-plugins y gestionar la seguridad. En este artículo nos centraremos en el desarrollo interno y distribución de extensiones. Si el artículo 24 te enseñó a conducir el coche, este te enseñará a desmontar el motor y construir uno nuevo.

Este artículo tiene un formato de manual de referencia, por lo que su densidad de datos es alta. No necesitas memorizarlo de golpe; utilízalo para crear tu primer plugin, y regresa a las tablas para consultar las opciones y campos cuando lo necesites.

Al terminar de leer este artículo, obtendrás:

  • La estructura de directorios estándar de un plugin, detallando la regla de colocar únicamente el archivo plugin.json en la carpeta .claude-plugin/.
  • El esquema del archivo de manifiesto plugin.json: campos obligatorios, metadatos, rutas de componentes, configuraciones y dependencias.
  • Las siete categorías de componentes que se pueden empaquetar (skill, command, agent, hook, MCP, LSP, monitor), sus rutas y restricciones.
  • Las variables de entorno de rutas (${CLAUDE_PLUGIN_ROOT}, ${CLAUDE_PLUGIN_DATA}, ${CLAUDE_PROJECT_DIR}) y por qué son obligatorias para evitar fallos de rutas.
  • Un ejercicio práctico completo: crear un plugin desde cero, probarlo en local, crear un mercado local e instalarlo.
  • Cómo gestionar las versiones y las dependencias de los plugins al distribuirlos para evitar problemas de caché o dependencias rotas.

01 Estructura del plugin: Carpeta y distribución de componentes

Presentamos la versión más simple de un plugin en el artículo 24 (el manifiesto plugin.json y carpetas de componentes). Para diseñar tus propios plugins, debes conocer la estructura completa de archivos para evitar desordenar el repositorio.

La regla de partida: un plugin es una carpeta raíz que contiene un archivo de manifiesto para definir su identidad, y los directorios de componentes organizados a nivel raíz.

Analogía: Una caja de piezas de construcción. Dispones de un manual de instrucciones (el manifiesto plugin.json) que indica el nombre del set y las piezas incluidas, y de compartimentos organizados para las piezas (ruedas en una sección, ventanas en otra). El plugin sigue esta distribución: plugin.json es el manual de instrucciones y carpetas como skills/, agents/ o hooks/ son los compartimentos de piezas. El manual tiene su compartimento propio, y las piezas se sitúan fuera.

La estructura estándar de directorios de un plugin se organiza así:

text
my-plugin/
├── .claude-plugin/           # Directorio de metadatos
│   └── plugin.json           # Manifiesto (manual) — Único archivo en esta ruta
├── skills/                   # Skills del plugin, organizados como <nombre>/SKILL.md
│   └── code-reviewer/
│       └── SKILL.md
├── commands/                 # Formato antiguo de Skills en Markdown (plano)
│   └── status.md
├── agents/                   # Definición de subagentes (subagents)
│   └── security-reviewer.md
├── hooks/                    # Configuración de ganchos (Hooks)
│   └── hooks.json
├── .mcp.json                 # Definición de servidores MCP
├── .lsp.json                 # Configuración de servidores LSP
├── bin/                      # Ejecutables que se inyectan en el PATH de la sesión
├── scripts/                  # Scripts auxiliares para Hooks o herramientas
└── settings.json             # Ajustes por defecto del plugin

Hay una regla de diseño estricta destacada en el manual oficial que debes cumplir:

La carpeta .claude-plugin/ solo debe contener el archivo plugin.json. El resto de carpetas de componentes (commands/, agents/, skills/, output-styles/, themes/, monitors/, hooks/) deben colocarse directamente en la raíz del plugin, y nunca dentro de .claude-plugin/.

Es decir, el directorio .claude-plugin/ es de uso exclusivo para plugin.json. Carpetas como skills/ o agents/ deben colgar directamente de la raíz del plugin. Es un error común de desarrollo empaquetar carpetas de componentes dentro de .claude-plugin/, lo que provoca que Claude Code cargue el plugin pero sea incapaz de detectar los Skills. Visualiza la caja de piezas: el manual va en su compartimento exclusivo y las piezas se distribuyen fuera.

Un detalle del comportamiento del sistema: el archivo CLAUDE.md de la raíz del plugin no se cargará en el contexto de la conversación. Si quieres alimentar a Claude con instrucciones en el plugin, debes estructurarlas en Skills, subagentes o Hooks; el CLAUDE.md de la carpeta del plugin se ignorará al iniciar la conversación, a diferencia del CLAUDE.md del repositorio de desarrollo (artículo 18).

💡 Resumen en una frase: Un plugin se compone de un manifiesto en .claude-plugin/plugin.json y de los directorios de componentes en la raíz; la regla de oro exige que .claude-plugin/ solo contenga a plugin.json, con el resto de carpetas situadas en la raíz del plugin.


02 plugin.json: Estructura del manifiesto de configuración

Con la estructura clara, analicemos el manifiesto de configuración: plugin.json. Declarará la identidad, autor y dependencias de la extensión.

Un detalle práctico: el manifiesto plugin.json es opcional. La documentación oficial detalla que si omites el archivo, Claude Code buscará componentes en las carpetas por defecto (como skills/ o agents/) e inferirá el nombre del plugin del nombre de la carpeta de instalación. No obstante, para distribuir o definir metadatos necesitarás el manifiesto. Veamos cómo estructurarlo.

Analogía: La etiqueta de envío de un paquete. Al enviar mercancía, pegas una etiqueta que detalla el contenido: nombre del remitente, dirección, peso, versión y descripción de los artículos. El transportista (Claude Code) lee esta información para procesar y clasificar el paquete. plugin.json es esa etiqueta: nombre, versión, descripción y componentes se declaran en este archivo.

Campos obligatorios

Si decides incluir el archivo de manifiesto, solo hay un campo requerido:

CampoTipoComportamiento
namestringIdentificador único en formato kebab-case (letras minúsculas y guiones), sin espacios.

¿Por qué es crucial el campo name? Define el espacio de nombres (namespace) de los componentes del plugin. Si creas un plugin llamado plugin-dev con un subagente llamado agent-creator, se registrará en el sistema como plugin-dev:agent-creator. Sus Skills se invocarán en la terminal como /plugin-dev:nombre-del-skill. El espacio de nombres es la barrera que evita conflictos de nombres entre plugins, permitiéndote instalar herramientas de diversos autores sin que interfieran entre sí.

Metadatos descriptivos (documentación)

Campos opcionales para documentar e informar al usuario en la instalación:

CampoPropósito
displayNameNombre amigable para mostrar en la interfaz (admite mayúsculas y espacios); si se omite, se usa name.
versionVersión del plugin usando semver (versionado semántico). Es vital para gestionar las actualizaciones de caché de los clientes (ver sección 08).
descriptionResumen de las capacidades del plugin, visible al instalar o listar extensiones.
authorDatos del creador de la extensión (name, email, url).
homepage / repository / licenseEnlaces de documentación, código fuente y tipo de licencia.
keywordsEtiquetas de búsqueda para clasificar el plugin.

Rutas personalizadas (definición de componentes)

Por defecto, Claude Code busca los componentes en las carpetas estándar de la raíz. Solo necesitas configurar estos campos si usas rutas alternativas:

CampoPropósito
skillsCarpetas adicionales de Skills (se añaden a la carpeta por defecto skills/).
commands / agents / outputStylesRutas personalizadas (de tipo string o array) que reemplazan a las carpetas por defecto.
hooks / mcpServers / lspServersRutas a los archivos JSON de configuración o declaración directa en el manifiesto.
dependenciesLista de plugins de los que depende esta extensión (ver sección 08).

Aquí radica un detalle de comportamiento importante: algunos campos añaden rutas a la búsqueda, mientras que otros las sobrescriben.

  • Reemplazar por defecto: commands, agents, outputStyles. Si configuras el campo "agents": ["./mis-agentes/"] en el manifiesto, se ignorará la carpeta estándar agents/ de la raíz. Si quieres mantener la búsqueda en ambos sitios, deberás listarlos de forma explícita: "agents": ["./agents/", "./mis-agentes/"].
  • Añadir a la búsqueda: skills. La carpeta estándar skills/ siempre se analizará en segundo plano; las rutas indicadas en este campo se sumarán a la búsqueda.

Tenlo en cuenta al diseñar tu estructura para evitar que tus subagentes o comandos personalizados dejen de cargarse al añadir una ruta alternativa.

Un ejemplo de manifiesto plugin.json estructurado con metadatos:

json
{
  "name": "deployment-tools",
  "displayName": "Deployment Tools",
  "version": "1.2.0",
  "description": "Herramientas para la automatización de despliegues en el repositorio",
  "author": { "name": "Equipo de DevOps", "email": "devops@company.com" },
  "license": "MIT",
  "keywords": ["deployment", "ci-cd", "kubernetes"]
}

💡 Resumen en una frase: El archivo plugin.json actúa como manifiesto; el campo obligatorio name define el prefijo de tus comandos, y debes diferenciar los campos de rutas que sobrescriben la carpeta por defecto de aquellos que se limitan a añadir rutas de búsqueda.


03 Categorías de componentes: Las siete piezas del plugin

Esta es la sección de referencia para conocer qué herramientas puedes empaquetar dentro de un plugin. Estructura cada componente en su compartimento correspondiente:

ComponenteCarpeta raízFunción en la extensiónActivación o disparo
Skillsskills/<nombre>/SKILL.mdInstrucciones con plantillas y scripts de apoyo (ver artículo 26).Invocación manual /plugin:skill o propuesta automática de la IA.
Commandscommands/*.mdFormato antiguo de Skills de un solo archivo.Invocación manual /plugin:comando.
Agentsagents/*.mdSubagentes personalizados con instrucciones y herramientas (ver artículo 23).Se listan en /agents y se invocan por nombre.
Hookshooks/hooks.jsonComandos automáticos vinculados a eventos (ver artículo 33).Disparo en segundo plano ante eventos de sesión.
MCP servers.mcp.jsonConexión con servicios, bases de datos o APIs locales/remotas (ver artículo 22).Carga automática en la sesión; expone sus herramientas a Claude.
LSP servers.lsp.jsonConfiguración de servidores de lenguaje para el análisis de código.Análisis semántico automático (ir a definición, buscar referencias).
Monitorsmonitors/monitors.jsonMonitorización de logs en segundo plano para notificar a la IA (experimental).Ejecución automática al activar la sesión.

Analicemos algunas restricciones de diseño de estos componentes especificadas en la documentación:

Los subagentes del plugin tienen límites de permisos por seguridad. La documentación oficial detalla: por motivos de seguridad, los subagentes declarados en plugins no admiten las directivas hooks, mcpServers y permissionMode en su frontmatter. Es decir, un subagente empaquetado en un plugin no puede registrar Hooks en tu máquina, levantar servidores MCP o modificar las reglas de autorización; esto evita que un plugin modifique el comportamiento del sistema sin tu supervisión. Los campos admitidos por el frontmatter del subagente son name, description, model, effort, maxTurns, tools, disallowedTools, skills, memory, background e isolation (donde el único valor admitido para isolation es "worktree").

Los Hooks cubren múltiples eventos de ciclo de vida. Los ganchos integrados en el plugin responden a los mismos eventos que los Hooks locales (artículo 33): desde SessionStart (inicio), PreToolUse (antes de herramienta, permite bloqueo) y PostToolUse (después de herramienta) hasta Stop (fin de turno de chat) y SessionEnd (cierre de sesión). El manual oficial documenta decenas de eventos para su control.

La lógica de ejecución de los Hooks admite varias tecnologías. Además del tipo command (ejecución de scripts Bash), el manifiesto de Hooks permite configurar tipos de tipo http (envío de JSON a un endpoint web), mcp_tool (invocación de una herramienta de un servidor MCP), prompt (evaluar una directriz con el LLM) o agent (validar la tarea con un subagente independiente).

Los Monitors son una característica en fase experimental. Permiten que el plugin monitorice un archivo de log o estado del sistema en segundo plano y envíe notificaciones a Claude ante cambios. Requiere la versión interactiva de Claude Code v2.1.105 o superior; su diseño puede sufrir cambios.

Otras carpetas auxiliares de interés: la carpeta bin/ permite empaquetar ejecutables nativos que se añadirán al PATH de la terminal de Claude durante la sesión, permitiendo invocarlos directamente; el archivo settings.json define ajustes iniciales del plugin (actualmente limitado a definir el agent principal o la visualización de la barra de estado subagentStatusLine).

💡 Resumen en una frase: Un plugin admite siete categorías de componentes (skill, command, agent, hook, MCP, LSP, monitor); recuerda que los subagentes de plugins tienen restringidos los permisos de Hooks y MCP por seguridad, y que la carpeta bin/ permite añadir binarios al PATH de la sesión.


04 Rutas dinámicas: Uso obligatorio de variables de entorno

Esta sección aborda el fallo más común al desarrollar plugins: definir rutas fijas. La solución consiste en el uso de variables dinámicas de entorno.

Planteemos el escenario: tu plugin incluye un Hook que ejecuta el script scripts/format.sh, o un servidor MCP que ejecuta node server.js. Si defines la ruta absoluta de tu máquina (/Users/desarrollador/my-plugin/scripts/format.sh), el script fallará en la máquina de tus compañeros y dejará de funcionar en tu terminal en cuanto el plugin se actualice y cambie su directorio de caché.

Para solucionarlo, Claude Code expone tres variables de rutas que el sistema traduce dinámicamente al cargar el plugin:

Variable de rutaResolución en calienteCaso de uso recomendado
${CLAUDE_PLUGIN_ROOT}Ruta absoluta al directorio de instalación de la versión activa del plugin.Invocar scripts, binarios o archivos de configuración empaquetados en el plugin.
${CLAUDE_PLUGIN_DATA}Ruta absoluta al directorio persistente de datos del plugin (se mantiene tras actualizar).Guardar archivos de configuración locales, carpetas node_modules o bases de datos de la extensión.
${CLAUDE_PROJECT_DIR}Ruta absoluta a la raíz del repositorio de desarrollo activo.Hacer referencia a scripts de testing o linters del proyecto del usuario.

Analogía: Una etiqueta con la indicación "carpeta del manual" frente a una ruta fija. Si en un archivador pones una nota que dice "los planos están en el cajón 3, archivador azul", en cuanto traslades los documentos a otra oficina la nota dejará de ser útil. Si en su lugar escribes "los planos están en la carpeta adyacente a esta nota", la indicación funcionará sin importar dónde muevas el archivador. ${CLAUDE_PLUGIN_ROOT} es esa indicación relativa: apunta siempre a la carpeta raíz de la versión del plugin que se está ejecutando.

Veamos cómo declarar la ruta de un script en el archivo de configuración de Hooks:

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

Nota: Rodea la variable con comillas dobles para evitar fallos si la ruta del sistema contiene espacios.

Una advertencia importante de seguridad y caché descrita en la documentación:

...

Al actualizar el plugin, la ruta de ${CLAUDE_PLUGIN_ROOT} cambiará. La carpeta de la versión anterior se conserva en disco durante unos siete días para permitir la finalización de procesos activos, pero debe considerarse temporal; no escribas archivos de estado o configuración en ella.

Es decir, el directorio de ROOT es de solo lectura y temporal; no escribas datos en él. Si tu plugin necesita descargar paquetes o guardar configuraciones que persistan entre actualizaciones, escríbelas en ${CLAUDE_PLUGIN_DATA}. Un error de desarrollo habitual consiste en instalar las dependencias de node en ROOT, lo que provoca que al actualizar la versión del plugin se borren las dependencias instaladas. Usa ROOT para scripts empaquetados y DATA para el almacenamiento local.

Otra regla del sistema de archivos: los plugins instalados no pueden hacer referencia a archivos fuera de su directorio. Si intentas acceder mediante rutas relativas hacia atrás (../libreria-compartida), la llamada fallará, ya que al instalar el plugin su carpeta se copia de forma aislada a la caché de la aplicación (~/.claude/plugins/cache) omitiendo los archivos adyacentes de desarrollo.

💡 Resumen en una frase: Utiliza siempre ${CLAUDE_PLUGIN_ROOT} para referenciar recursos del plugin y ${CLAUDE_PLUGIN_DATA} para archivos locales que deban persistir; no definas rutas fijas ni intentes acceder a directorios situados fuera de la carpeta del plugin.


05 Ejercicio práctico: Crear y probar un plugin en local

Pasemos a la práctica. Diseñaremos un plugin sencillo llamado my-greeter que contenga un Skill de saludo personalizado, probando su funcionamiento en local sin necesidad de publicar mercados.

Paso 1: Crear la estructura del plugin con la consola

Claude Code dispone del comando plugin init para generar la estructura inicial:

bash
claude plugin init my-greeter --with skills

El parámetro --with skills creará la subcarpeta de Skills. Esta orden generará el manifiesto plugin.json en .claude-plugin/ y la plantilla de Skills en la ruta de caché local del usuario ~/.claude/skills/my-greeter/.

Resultado esperado: la consola informará de que el plugin se ha creado en la ruta de configuración ~/.claude/skills/my-greeter/.

Nota de desarrollo: los plugins situados en la carpeta ~/.claude/skills/ que contienen un manifiesto plugin.json son detectados de forma automática por Claude Code como plugins del tipo nombre-del-directorio@skills-dir al iniciar el chat, sin necesidad de registrarlos en mercados ni realizar instalaciones locales. Es la vía óptima para el desarrollo de tus herramientas personales.

Paso 2: Inspeccionar la estructura generada

Consulta la carpeta del plugin para verificar su distribución:

bash
ls -R ~/.claude/skills/my-greeter

Resultado esperado: la carpeta .claude-plugin/ contendrá el archivo plugin.json, y la carpeta skills/ se situará a nivel de raíz del plugin, confirmando la regla de distribución de la sección 01.

Paso 3: Escribir el Skill de saludo

Edita o crea el archivo de Skill en la ruta ~/.claude/skills/my-greeter/skills/hello/SKILL.md con las siguientes directrices:

markdown
---
description: Envía un saludo personalizado al usuario con tono entusiasta
---

# Hello Skill

Por favor, saluda al usuario llamado "$ARGUMENTS" con entusiasmo. Pregúntale en qué puedes ayudarle hoy en el desarrollo de su código. Mantén un tono motivador y añade algún emoji amistoso.

Utilizamos $ARGUMENTS para inyectar el parámetro que pasemos al invocar el comando slash.

Resultado esperado: has guardado el archivo SKILL.md en la ruta especificada.

Paso 4: Iniciar la sesión de Claude cargando el plugin local

Utiliza el flag --plugin-dir para forzar la carga del plugin de desarrollo local:

bash
claude --plugin-dir ~/.claude/skills/my-greeter

Resultado esperado: la sesión de Claude Code se iniciará con normalidad. Si escribes /help, verás en la lista de comandos slash el registro de tu Skill bajo el prefijo del plugin.

Paso 5: Invocar el comando del plugin

Escribe el comando en la terminal pasando tu nombre como argumento (recuerda que el comando adopta el espacio de nombres del plugin):

text
/my-greeter:hello Walter

Resultado esperado: Claude responderá al prompt saludándote por tu nombre ("Walter") con el tono entusiasta y emojis solicitados en el Skill, confirmando que el empaquetado del plugin y el Skill funcionan en tu máquina.

Paso 6: Modificar el Skill en caliente y aplicar el hot reload

Modifica el texto de SKILL.md (por ejemplo, cambia el tono de saludo a uno formal o en otro idioma) y, sin cerrar la sesión de Claude, ejecuta:

text
/reload-plugins

Resultado esperado: al ejecutar /my-greeter:hello Walter de nuevo, la respuesta reflejará los cambios del archivo.

Nota de desarrollo: las modificaciones en los archivos SKILL.md de un plugin se leen en caliente ante cada llamada; sin embargo, cambios en Hooks (hooks.json), configuraciones de MCP (.mcp.json) o subagentes (agents/) requieren invocar /reload-plugins o reiniciar la sesión para que Claude Code vuelva a indexar el manifiesto.

Al completar estos pasos habrás creado, editado, cargado en caliente y probado tu primer plugin en local. Es el flujo de desarrollo recomendado.

💡 Resumen en una frase: Pon en marcha el flujo de desarrollo: crea la estructura con plugin init → escribe el Skill con la variable $ARGUMENTS → inicia con --plugin-dir para probar en local → recarga cambios con /reload-plugins; este ciclo te permitirá iterar el código de tu extensión de forma ágil.


06 Publicar tu extensión: Configurar un mercado de plugins

Una vez que el plugin funciona en tu máquina, el siguiente paso consiste en compartirlo con tu equipo de desarrollo mediante un mercado (marketplace).

Conviene diferenciar dos conceptos similares descritos en el manual oficial:

ConceptoPropósitoDeclaración
Marketplace source (origen del mercado)Dirección de consulta para obtener el catálogo de plugins disponibles (marketplace.json).Se añade con /plugin marketplace add en la consola.
Plugin source (origen del plugin)Ubicación de descarga del código del plugin propiamente dicho.Se declara en el campo source de cada plugin dentro de marketplace.json.

Analogía: La tienda online frente a los almacenes de distribución. El marketplace source es la URL de la tienda online; contiene la lista de artículos y sus descripciones. El plugin source es la dirección física del almacén desde donde se envía el producto al comprarlo. La lista puede estar en una web, y el producto descargarse de GitHub o de un registro de paquetes.

Para constituir un mercado, crea el archivo de catálogo .claude-plugin/marketplace.json en la raíz de tu carpeta de mercado. Su estructura básica es:

json
{
  "name": "my-plugins",
  "owner": { "name": "Organización de Desarrollo" },
  "plugins": [
    {
      "name": "my-greeter",
      "source": "./plugins/my-greeter",
      "description": "Skill para dar saludos personalizados en local"
    }
  ]
}

El parámetro source define de dónde descargar el plugin. Admite los siguientes formatos:

Formato de sourceSintaxisCaso de uso
Ruta relativa"source": "./plugins/my-greeter"El plugin se encuentra en el mismo repositorio del mercado (formato habitual).
Repositorio GitHub"source": "github", "repo": "autor/nombre-repo"El plugin se gestiona en un repositorio de GitHub independiente.
Monorepo (git-subdir){ "source": "git", "url": "https://...", "path": "subcarpeta/plugin" }El plugin se sitúa en una carpeta interna de un repositorio git extenso.
Registro npm{ "source": "npm", "package": "@organizacion/plugin" }El plugin se distribuye como paquete npm público o privado.

Probar la instalación del mercado en local

Si organizas tu mercado local en una carpeta my-marketplace/ conteniendo el catálogo .claude-plugin/marketplace.json y el plugin en plugins/my-greeter/, puedes simular la instalación escribiendo:

text
/plugin marketplace add ./my-marketplace
/plugin install my-greeter@my-plugins

Resultado esperado: la primera orden registra tu mercado en la caché de Claude; la segunda descarga e instala el plugin. El comando /my-greeter:hello estará disponible de la misma forma que si lo descargaras de un repositorio oficial.

Antes de compartir el mercado, realiza una validación formal del archivo usando la CLI:

bash
claude plugin validate ./my-marketplace

Resultado esperado: la herramienta comprobará que la estructura del archivo marketplace.json cumple las especificaciones, que no hay nombres duplicados y que las rutas son válidas. Para validar los metadatos y la sintaxis de un plugin concreto, ejecuta la orden apuntando a su carpeta (claude plugin validate ./my-marketplace/plugins/my-greeter).

Para distribuir el catálogo en el equipo, sube la carpeta del mercado a un repositorio de git. Tus compañeros podrán añadirlo ejecutando /plugin marketplace add autor/repositorio-git en su terminal.

💡 Resumen en una frase: Distribuye tus extensiones configurando un archivo .claude-plugin/marketplace.json que declare el catálogo y la procedencia de los plugins (source), valida la sintaxis con claude plugin validate y súbelo a un repositorio compartido.


07 Estrategias de distribución: Cuándo usar cada opción

Al diseñar y probar plugins, es común dudar sobre qué vía de distribución utilizar en cada momento del ciclo de vida del código:

Opción de distribuciónÁmbitoComando de cargaVentaja principal
Skills como plugin localPersonal globalCarpeta ~/.claude/skills/<nombre>/Carga automática persistente entre sesiones, ideal para tus utilidades del día a día.
Directorio de desarrolloTemporal de pruebasclaude --plugin-dir ./ruta-pluginAislamiento completo; ideal para probar cambios locales sin ensuciar la instalación.
Mercado compartidoEquipo / ProducciónRegistro en marketplace.jsonGestión de versiones, actualizaciones automáticas y distribución al equipo.

Recomendaciones de uso:

El flag --plugin-dir es específico de la sesión de consola activa. En cuanto cierres la terminal de Claude Code, el plugin dejará de cargarse. Esto es útil para desarrollo, ya que te asegura que no quedarán residuos de pruebas en tu configuración de usuario. Además, el plugin cargado con --plugin-dir sobrescribirá a uno del mismo nombre instalado mediante mercado, lo que te permite probar parches en local sobre herramientas oficiales sin desinstalarlas.

Los plugins locales en ~/.claude/skills/ requieren atención en las rutas. Si bien son muy cómodos para tus herramientas cotidianas al no requerir confirmaciones de mercados, la documentación advierte: si colocas un plugin de tipo carpeta en el .claude/skills/ del repositorio de trabajo (proyecto), solo se cargará si inicias Claude Code desde esa misma carpeta raíz. Si inicias la consola desde un subdirectorio del proyecto, no se detectará. Asegúrate de iniciar la sesión en la raíz o recurre a la recarga de plugins con /reload-plugins.

Evita dar de alta mercados en fases tempranas de diseño. Crear el catálogo marketplace.json y gestionar las instalaciones añade complejidad innecesaria en la fase de prototipado de prompts. Realiza el diseño y las pruebas iniciales usando la carpeta local ~/.claude/skills/ o el flag --plugin-dir; y pasa al formato de mercado únicamente cuando la herramienta sea estable y desees compartirla.

💡 Resumen en una frase: Utiliza ~/.claude/skills/ para tus herramientas de diario, --plugin-dir para depurar cambios locales en caliente, y reserva los mercados para la distribución de versiones estables al equipo de desarrollo.


08 Gestión de versiones y dependencias: Evitar fallos de caché

Para finalizar la guía de referencia, abordemos las dos incidencias más comunes en la distribución de plugins: el control de caché por versión y la gestión de dependencias.

Control de versiones: El peligro de fijar la versión en desarrollo

Claude Code gestiona la caché de los plugins instalados desde mercados según un orden de prioridad de versión:

  1. El campo version en el manifiesto plugin.json del plugin.
  2. El campo version del plugin registrado en marketplace.json.
  3. Si no se especifican, se utiliza el hash SHA de git del commit de descarga.

Aquí radica una restricción crucial del sistema:

...

Si especificas la versión del plugin en plugin.json (por ejemplo, "version": "1.0.0"), esta quedará fija. Si realizas cambios en el código y los subes al repositorio sin modificar esta cadena, la actualización no se aplicará a los usuarios, ya que Claude Code detectará el mismo número de versión y mantendrá la copia local en caché.

Es decir: si declaras "version": "1.0.0", debes incrementar el número de versión ante cada cambio de código. De lo contrario, los comandos /plugin update de tus compañeros informarán de que el plugin ya está actualizado, ignorando los cambios del repositorio.

Estrategias recomendadas según el ciclo de la extensión:

Tipo de desarrolloDeclaración de version en manifiestoComportamiento de actualización
Desarrollo activo / InternoNo incluir el campo versionEl sistema evalúa el hash SHA del commit de git; cada cambio subido se detecta como nueva versión de forma automática.
Estable / Distribución externaDeclarar version (por ejemplo, 1.1.0)El desarrollador incrementa el valor semántico ante cada release; las actualizaciones se aplican de forma controlada.

Nota: no dupliques el campo version en plugin.json y marketplace.json. La versión del manifiesto interno del plugin sobrescribirá de forma silenciosa a la del mercado, lo que puede provocar que los cambios en marketplace.json no surtan efecto.

Nuestra recomendación: omite el campo version en tus plugins de desarrollo interno. Al usar el hash de git como identificador, cada git push que realices será detectado de forma automática por las terminales de tus compañeros en la siguiente actualización.

Gestión de dependencias en plugins

Si tu plugin requiere de las funciones de otra extensión para operar, decláralo en el array dependencies de tu manifiesto:

json
{
  "name": "my-plugin",
  "dependencies": [
    "helper-lib",
    { "name": "secrets-vault", "version": "~2.1.0" }
  ]
}

Al configurar este campo, Claude Code instalará y activará automáticamente las extensiones listadas al instalar tu plugin. Puedes acotar las versiones de las dependencias usando reglas semver (como ~2.1.0) para evitar que actualizaciones de terceros rompan tu lógica. Al desinstalar la extensión, ejecutar claude plugin uninstall --prune limpiará del sistema las dependencias automáticas que ya no sean requeridas por ningún plugin activo. Las extensiones instaladas de forma manual por el usuario nunca se eliminarán con el comando prune.

Analogía: La lista de herramientas requeridas en un mueble. Si en el manual de instrucciones indicas "se requiere el kit de llaves allen modelo X para el montaje", el usuario sabrá qué herramientas adquirir. Al declarar dependencies, Claude Code lee esta lista de accesorios y los descarga de forma automática en la caché de la sesión, asegurando que el plugin dispone de todo lo necesario para operar.

💡 Resumen en una frase: Al distribuir, evita definir version en la fase de desarrollo activo para permitir que git gestione las actualizaciones mediante hashes SHA, e introduce las dependencias necesarias en el campo dependencies para automatizar su instalación en los clientes.


09 Resumen

En este artículo hemos detallado las especificaciones técnicas para el desarrollo y publicación de plugins en Claude Code.

Repasemos los conceptos explicados:

Componente de desarrolloEspecificación / SintaxisDetalle de control
Estructura de carpetas.claude-plugin/plugin.jsonÚnico archivo admitido en este directorio; el resto de carpetas cuelgan de la raíz.
Manifiesto de configuraciónParámetro nameÚnico campo obligatorio; define el espacio de nombres de la extensión.
Componentes integradosSkills, subagentes, Hooks, MCP, LSPLos subagentes no admiten Hooks ni MCP en plugins por seguridad.
Gestión de rutasVariable ${CLAUDE_PLUGIN_ROOT}Evita rutas absolutas locales; ${CLAUDE_PLUGIN_DATA} almacena datos persistentes.
Flujo de pruebasComando plugin init y flag --plugin-dirPermite estructurar e iniciar el plugin de desarrollo en local.
Publicación de mercadoArchivo marketplace.jsonAgrupa los plugins indicando su procedencia en el parámetro source.
Control de versionesCaché por SHA de git o version semverEvita fijar version en desarrollo activo para permitir actualizaciones por hash.
DependenciasArray dependenciesAutomatiza la instalación de extensiones secundarias requeridas.

Ahora deberías ser capaz de: estructurar una carpeta de plugin bajo los estándares oficiales, configurar el manifiesto plugin.json con metadatos y rutas, empaquetar Skills y subagentes gestionando sus límites de permisos, utilizar variables de ruta dinámicas para asegurar la portabilidad, iniciar la depuración en local con --plugin-dir, configurar un mercado de plugins local y gestionar las dependencias y versiones de tus lanzamientos. Escribir y distribuir plugins te permite consolidar tus flujos de trabajo e integraciones en herramientas compartibles y reutilizables.

Estructura tu primera extensión y comparte tus Skills y Hooks con el equipo de desarrollo.


En el próximo artículo, 39 "Primeros pasos en la práctica", iniciaremos el bloque de desarrollo práctico. Tras haber analizado las configuraciones, MCP, subagentes, checkpoints y plugins, disponemos de una sólida base teórica. En la siguiente sección implementaremos una tarea real paso a paso, desde el análisis del prompt inicial hasta la validación y entrega, aplicando las herramientas estudiadas de forma coordinada. Piensa en esto: ¿cómo se coordinan los Skills, checkpoints y la edición de archivos al resolver una tarea real en la consola? Lo veremos en el próximo artículo.


Lecturas recomendadas