Contenido

  1. Introducción — Las 3 Plataformas y sus Filosofías
  2. OpenCode — Sistema de Plugins
  3. Codex CLI — Sistema de Plugins
  4. Claude Code — Sistema de Plugins
  5. Comparativa Cross-Platform
  6. Tabla de Equivalencias
  7. Estrategia Cross-Platform
  8. Conclusión y Lecciones Aprendidas

1 Introducción — Las 3 Plataformas y sus Filosofías

Tres plataformas compiten hoy por ser el entorno definitivo para programación agentica asistida por IA. Cada una tiene una filosofía distinta, un ecosistema de plugins diferente, y —lo más importante— un modelo mental particular sobre qué significa "extender" la plataforma.

OpenCode

Minimalista elegante. Filosofía Unix: herramientas pequeñas que hacen una cosa bien. Plugin system tipo middleware con hooks asíncronos.

🏗️

Codex CLI

Corporativo completo. Codex CLI (OpenAI). Plugins tipo agente MCP con ciclo de vida y sandboxing.

🏰

Claude Code

Castillo con todas las torres. El ecosistema más maduro: MCP nativo, hooks CLI, modo "edict" remoto, y el SDK más documentado.

Analicemos las capacidades reales de cada plataforma desde sus fundamentos arquitectónicos. No se trata de declarar un ganador absoluto, sino de entender dónde se pueden construir extensiones, qué tipo de extensiones permite cada una, y cómo portar un plugin entre las tres con el mínimo esfuerzo.

📌 Premisa central: No hay una plataforma "mejor" en términos absolutos. Cada una optimiza para casos de uso distintos. El objetivo es mapear equivalencias para que puedas portar plugins entre ellas con el mínimo esfuerzo.

Filosofías de Extensibilidad

Cada plataforma responde una pregunta distinta sobre la extensibilidad:


2 OpenCode — Sistema de Plugins

OpenCode implementa un sistema de plugins basado en middleware asíncrono. Cada plugin es una función que recibe un contexto (PluginInput) y devuelve un objeto con hooks. La plataforma ofrece 17 hooks que cubren prácticamente todos los puntos de extensión del pipeline de conversación.

Los 17 Hooks

Cada hook es un punto de extensión en el pipeline de la conversación. Los hooks reciben un contexto y pueden devolver modificaciones parciales o completas del comportamiento.

Hook ¿Solo observa? ¿Modifica? ¿Qué modifica?
eventNoEventos del ciclo de vida (start, stop, error, tool_call)
chat.beforeParcialLectura del mensaje entrante (no modifica)
chat.messageNoSystem prompt, messages[], model, params LLM
chat.afterParcialPost-procesamiento de respuesta (lectura)
tool.execute.beforeNoBloquear tool call, validar argumentos, modificar args
tool.execute.afterNoPost-procesar resultado, detectar errores/éxito
tool.execute.errorNoManejar errores, retry, fallback
tool.registerNoModificar definición de tools, añadir/quitar tools
tool.addToolNoRegistrar custom tools nativas (JavaScript/TypeScript)
provider.beforeNoModificar config del provider (modelo, apiKey, baseUrl)
provider.afterParcialObservar respuesta del provider
auth.registerNoRegistrar auth providers (OAuth, API key, OIDC)
command.registerNoRegistrar slash commands
configNoModificar configuración global de OpenCode
compact.beforeNoCustomizar lógica de compactación de contexto
compact.afterParcialObservar resultado de compactación
env.registerNoInyectar/eliminar variables de entorno
14 de 17 hooks modifican comportamiento activamente. Solo event, chat.before y chat.after son puramente observacionales (y aún así pueden ser útiles para logging/monitoreo).

Arquitectura del Plugin System

En OpenCode, un plugin es simplemente una función que recibe PluginInput y devuelve hooks:

type Plugin = (
  input: PluginInput,
  options?: PluginOptions
) => Promise<Hooks>

PluginInput completo

El contexto que OpenCode inyecta a cada plugin contiene:

interface PluginInput {
  client: Client              // Cliente LLM (OpenAI, Anthropic, etc.)
  project: Project           // Proyecto actual
  directory: string          // Directorio del proyecto
  worktree: string           // Worktree de git (si aplica)
  experimental_workspace: Workspace  // Workspace experimental
  serverUrl: string          // URL del servidor MCP/local
  $: typeof Bun.$            // Template literal para shell
}
🔌 PluginOptions: Objeto opcional que permite definir metadatos (name, version, description) y permisos con un sistema whitelist/blacklist granular para cada hook.

Carga y Descubrimiento de Plugins

OpenCode descubre plugins mediante tres mecanismos:

  1. Auto-descubrimiento local — Archivos .ts/.js en .opencode/plugins/ se cargan automáticamente al iniciar, sin necesidad de declararlos. El nombre canónico del directorio es plugins (plural), aunque plugin (singular) también se acepta por retrocompatibilidad. También escanea ~/.config/opencode/plugins/ a nivel global. El patrón es {plugin,plugins}/*.{ts,js} (solo primer nivel).
  2. Paquetes npm — Vía array "plugins" en opencode.json con nombres de paquetes npm.
  3. Rutas explícitas — Vía array "plugins" en opencode.json con URLs file:// o rutas absolutas.

Soporta hot reload nativo: los cambios en plugins se reflejan sin reiniciar la sesión. Esto es único entre las tres plataformas.

Caso de Estudio: opencode-model-fallback

Este plugin en producción usa 3 hooks para implementar failover automático entre modelos LLM. Veamos cómo funciona:

HookPropósitoQué hace
eventDetección de erroresEscucha eventos rate_limit, quota_exceeded, 5xx
chat.messageCambio de modelo en runtimeInyecta variant para cambiar modelo en la request
tool.execute.afterDetección de éxitoSi el tool call succeed con el fallback, registra recuperación
import { Plugin, PluginInput } from "opencode/plugin";

interface Config {
  fallbackModels: Record<string, string[]>;
  cooldownMs: number;
  retryOriginalAfterMs: number;
  maxFallbackDepth: number;
}

const state = new Map<string, {
  currentModel: string;
  depth: number;
  lastFallbackAt: number;
}>();

export const plugin: Plugin = async (input: PluginInput, options?: Config) => ({
  async event({ type, payload, sessionId }) {
    if (["rate_limit", "quota_exceeded", "5xx", "timeout", "overloaded"]
      .includes(type)) {
      const s = state.get(sessionId) ?? {
        currentModel: payload.model,
        depth: 0, lastFallbackAt: Date.now()
      };
      s.depth++; s.lastFallbackAt = Date.now();
      state.set(sessionId, s);
    }
  },

  async chat.message({ messages, sessionId, variant }) {
    const s = state.get(sessionId);
    if (!s || s.depth === 0) return { messages };
    const agentName = variant ?? "default";
    const fallbacks = options?.fallbackModels?.[agentName];
    const fallbackIdx = Math.min(s.depth - 1, (fallbacks?.length ?? 1) - 1);
    if (fallbacks?.[fallbackIdx] && s.depth <= (options?.maxFallbackDepth ?? 3)) {
      return { messages, variant: fallbacks[fallbackIdx] };
    }
    return { messages };
  },

  async tool.execute.after({ sessionId, result }) {
    const s = state.get(sessionId);
    if (s && s.depth > 0 && !result.isError) {
      setTimeout(() => { s.depth = 0; s.currentModel = ""; },
        options?.retryOriginalAfterMs ?? 900000);
    }
    return { result };
  }
});

El patrón —detectar evento → modificar mensaje → verificar éxito— es reproducible en las 3 plataformas con adaptaciones mínimas en la capa de integración, aunque el cambio de modelo en runtime es exclusivo de OpenCode.

🏭 Producción real: Este plugin está publicado como opencode-model-fallback y se configura desde opencode.json con mapeo de agentes a modelos de fallback. Soporta wildcards ("*") y profundidad máxima configurable.

3 Codex CLI — Sistema de Plugins

Codex CLI, la plataforma de OpenAI, implementa un sistema de plugins con un enfoque enterprise: ciclo de vida explícito, manifests con metadatos, y un SDK multi-lenguaje que permite escribir plugins en Python, TypeScript, Go y Java.

Ciclo de Vida del Plugin

Cada plugin en Codex CLI pasa por tres fases:

FaseMétodoPropósito
Inicializacióninit()Cargar configuración, validar dependencias, conectar servicios externos
Ejecuciónstart()Activar hooks, registrar MCP tools, iniciar background workers
Terminaciónstop()Liberar recursos, cerrar conexiones, persistir estado

A diferencia de OpenCode (donde el plugin es una función pura), en Codex CLI el plugin es una clase que extiende CodexPlugin y puede mantener estado interno con un ciclo de vida gestionado por la plataforma.

Manifest: plugin.json

Cada plugin de Codex CLI requiere un manifest explícito:

{
  "name": "model-fallback",
  "version": "1.0.0",
  "description": "Automatic model failover",
  "hooks": ["onError", "postExec"],
  "env": {
    "FALLBACK_COOLDOWN_MS": "300000"
  },
  "permissions": ["network", "fs.read"]
}

Puntos de Extensión

Los plugins de Codex CLI pueden integrarse mediante:

SDK Multi-Lenguaje

Codex CLI es la única plataforma que ofrece un SDK oficial para múltiples lenguajes:

LenguajeSDKCasos de uso
TypeScript@openai/codex-sdkPlugins nativos, integración con el runtime
Pythonopenai-codex-sdkCiencia de datos, ML, scripting
Gogithub.com/openai/codex-sdk-goMicroservicios, herramientas de red
Javacom.openai:codex-sdkIntegración enterprise, JVM ecosystem

Marketplace Emergente

OpenAI está construyendo un registry de plugins para Codex CLI. Los plugins se pueden descubrir y compartir via el sistema de manifests, aunque el marketplace aún está en fase emergente. La carga puede ser desde un registry o desde rutas locales definidas en codex.json.

💡 Limitación clave: Codex CLI no permite modificar el modelo LLM ni sus parámetros en runtime. La configuración del modelo es fija por sesión. Tampoco soporta múltiples proveedores — solo OpenAI. Para escenarios que requieren cambiar de modelo sobre la marcha, se necesita una capa proxy externa.

4 Claude Code — Sistema de Plugins

Claude Code, también de Anthropic, tiene el ecosistema de plugins más maduro de las tres plataformas. Con aproximadamente 30 hooks CLI, un marketplace funcional, y el protocolo MCP como columna vertebral, representa el estado del arte en extensibilidad agentica desde la perspectiva de producto.

Arquitectura de Hooks

Claude Code expone hooks CLI que se declaran en claude.json y se ejecutan en puntos específicos del pipeline:

CategoríaHooksPropósito
Pre-ejecuciónpre_message, pre_toolModificar mensaje o tool antes de enviar al LLM
Post-ejecuciónpost_tool, post_messageProcesar respuesta, detectar errores
ComandoscommandRegistrar comandos slash personalizados
AprobaciónapprovalInterceptar y aprobar/rechazar operaciones
Backgroundmonitor, watchTareas periódicas y watch mode
LSPlsp.*Integración con Language Server Protocol

Manifest: claude.json

Los plugins de Claude Code se declaran con un archivo de configuración similar a Codex pero con un ecosistema más estandarizado:

{
  "name": "model-fallback",
  "version": "1.0.0",
  "hooks": {
    "pre_message": "./hooks/pre-message.js",
    "post_tool": "./hooks/post-tool.js"
  },
  "env": { "FALLBACK_COOLDOWN_MS": "300000" },
  "mcp_servers": ["./mcp/server.js"]
}

Capacidades Distintivas

Detección de Plugins

Claude Code descubre plugins mediante escaneo de node_modules/ (paquetes @anthropic-ai/*) y configuración explícita en claude.json. No soporta hot reload — los cambios requieren reiniciar el agente.

📖 Documentación: Claude Code tiene la documentación más completa y organizada de las tres plataformas, con guías de inicio rápido, API reference, ejemplos, y una comunidad activa en GitHub.

5 Comparativa Cross-Platform

Las diferencias no están en "quién tiene más features", sino en dónde cada plataforma pone los límites de extensibilidad. Veamos la tabla más completa hasta la fecha:

Dimensión OpenCode Codex CLI Claude Code
Hooks API 17 hooks
asíncronos, tipados
Plugin lifecycle
init/start/stop + MCP
CLI hooks + MCP
~30 hooks, edict remoto
Capacidad de bloqueo
en tool.execute.before
Parcial
vía MCP tools
Parcial
vía hook approval
Modificar modelo runtime
vía chat.message + variant
No
config fija por sesión
No
solo vía config global
Modificar params LLM
temperature, max_tokens, etc.
No
fijo por provider
No
fijo por perfil
Custom tools nativas
tool.addTool (JS/TS)

SDK MCP nativo (4 lenguajes)

SDK MCP + STDIO
Registrar providers
provider.before
No
solo OpenAI
No
solo Anthropic
Auth OAuth/API
auth.register
Limitado
solo API key

OAuth nativo
Modificar config global
config hook
No No
Modificar system prompt
chat.message
Vía MCP
resource template

CLI hook + MCP
Transformar historial
chat.message
No No
Customizar compactación
compact.before
No No
Plugin manifest Implícito
package.json + naming
Explícito
plugin.json
Explícito
claude.json
Marketplace No
comunitario npm
Emergente
registry OpenAI

Claude Marketplace
LSP bundling No
no necesita

SDK multi-lenguaje

LSP nativo
Monitors background No
solo hooks síncronos

background workers

watch mode
Open Source
MIT License
Parcial
código disponible
No
código cerrado
Model-agnóstico
OpenAI, Anthropic, Google, openrouter, local
No
solo OpenAI
No
solo Anthropic

Fortalezas de OpenCode

Debilidades de OpenCode

💡 La paradoja: OpenCode tiene el plugin system más potente de los tres, pero es el que menos plugins tiene en su ecosistema. Codex tiene un plugin system más limitado pero ya tiene decenas de plugins en su registry. La potencia técnica no siempre gana; la documentación y el marketplace importan.

6 Tabla de Equivalencias

Este es el mapa que necesitas para portar un plugin entre las 3 plataformas. Cada fila es una capacidad que quieres implementar y cómo se logra en cada plataforma:

Capacidad OpenCode Codex CLI Claude Code
Bloquear tool call tool.execute.before → throw Error MCP tool validation Hook approval → reject
Validar argumentos tool.execute.before JSON Schema en tool def JSON Schema + hook
Post-procesar tool tool.execute.after MCP middleware CLI hook post-exec
Cambiar modelo chat.message + variant No soportado No soportado
Ajustar temperature chat.message → modify params No soportado No soportado
System prompt dinámico chat.message → prepend system MCP resource template pre_message hook
Auth provider auth.register API key env vars OAuth nativo
Custom tool nativa tool.addTool (JS/TS) MCP SDK (Python, TS, Go, Java) MCP SDK + STDIO
Comando slash command.register MCP tool con trigger CLI hook command
Inyectar env vars env.register plugin.json env block claude.json env block
Modificar definición de tool tool.register No soportado No soportado
Plugins desde npm/directorio .opencode/plugins/ + npm + opencode.json Git repo + codex.json npm package + claude.json
Carga automática .opencode/plugins/
(auto-descubrimiento)
Registry + dependencias Scan node_modules/
@anthropic-ai/*
Recarga sin reiniciar Hot reload nativo Requiere restart Requiere restart
Modificar config en runtime config hook No No
🔑 Regla de oro: Si tu plugin necesita modificar el comportamiento del LLM en runtime (cambiar modelo, ajustar temperatura, transformar mensajes), OpenCode es la única opción. Si tu plugin necesita integración con herramientas externas vía protocolo estándar, cualquier plataforma sirve gracias a MCP.

7 Estrategia Cross-Platform

La estrategia para construir plugins que funcionen en las tres plataformas no es "elegir una y adaptar", sino Core-First: aislar la lógica portable en un núcleo independiente y construir adapters específicos para cada plataforma.

Core Layer (100% portable entre plataformas)

Este código se escribe una vez y funciona en todas partes:

Platform Adapter Layer (lo que cambia por plataforma)

PlataformaFormato de pluginHook de entradaCómo se registra
OpenCode Función asíncrona
(input, opts) => Hooks
event, chat.message, tool.execute.* opencode.json → plugins[]
Codex CLI Plugin class
class P extends CodexPlugin
onError, postExec .codex-plugin/plugin.json
Claude Code Hook function
(context) => void
pre_message, post_tool claude.json → hooks[]

La Estrategia Core-First

  1. Escribe el Core Layer como un paquete npm independiente (TypeScript puro, sin dependencias de plataforma).
  2. Exporta interfaces que cada plataforma debe implementar: EventHandler, MessageMutator, ToolInterceptor.
  3. Crea un adapter por plataforma que mapee hooks nativos → interfaces del Core.
  4. El Core no sabe qué plataforma lo ejecuta. Los adapters son la única capa que conoce la plataforma target.

Este patrón permite que ~80% del código sea portable y solo ~20% sea específico de plataforma. En la práctica, para el plugin model-fallback, el Core Layer tiene 120 líneas y los adapters ~30 líneas cada uno.

Lo que realmente cambia por plataforma

No es la lógica de negocio. Es dónde y cómo te conectas al pipeline:

DimensiónOpenCodeCodexClaude
EntrypointFunción exportadaPlugin classHook function array
ContextoPluginInput completoContext tipado parcialContext tipado parcial
ModificaciónReturn object mergeMuta contextReturn partial
Error handlingThrow en hookPlugin.onErrorHook error callback
Carga de pluginsAuto-descubrimiento + npm + configRegistry + localScan + config
Hot reloadNativoNoNo
🎯 Recomendación: Si estás comenzando un plugin nuevo, escríbelo primero para OpenCode (entorno más permisivo y debuggeable), luego porta a Codex y Claude. El camino inverso es más difícil porque OpenCode tiene capacidades que las otras no soportan.

8 Conclusión y Lecciones Aprendidas

No hay un ganador absoluto. Hay ganadores por categoría:

OpenCode

Hook más potente
17 hooks, 14 modifican comportamiento. La plataforma más extensible. Model-agnóstico, open source, hot reload.

Gana en: profundidad de extensibilidad, runtime modification, model-agnostic

🏰

Claude Code

Packaging más maduro
Marketplace funcional, SDK documentado, ~30 hooks CLI. La experiencia de desarrollo más pulida.

Gana en: marketplace, documentación, DX, edict remoto

🏗️

Codex CLI

Enterprise más completo
SDK multi-lenguaje (Python, TS, Go, Java), background workers, LSP bundling. La plataforma para equipos.

Gana en: multi-lenguaje, background tasks, enterprise features

Tabla de Decisión

Usa esta guía para elegir plataforma según tu caso de uso:

Si necesitas...EligePor qué
Modificar modelo/params en runtimeOpenCodeÚnica plataforma con chat.message + variant
Soporte multi-lenguaje en toolsCodex CLISDK para Python, TS, Go, Java
Marketplace y distribuciónClaude CodeClaude Marketplace es el más maduro
Plugin 100% portableCore-FirstCore Layer + adapters específicos
Open Source / auditoríaOpenCodeMIT License, código abierto
Multi-provider LLMOpenCodeOpenAI, Anthropic, Google, OpenRouter, Ollama
Enterprise / equipos grandesCodex CLIBackground workers, LSP, watch mode

La lección más importante de esta clase magistral es metodológica: cuando analices arquitecturas de software, no te detengas en la documentación superficial. El código fuente es la única fuente de verdad. La documentación miente por omisión; el código fuente no.

El sistema de plugins de OpenCode es significativamente más potente de lo que su documentación superficial sugiere. Codex CLI tiene un SDK multi-lenguaje que ninguna otra plataforma iguala. Claude Code tiene el marketplace y la experiencia de desarrollo más madura. Cada una gana en una dimensión distinta, y la estrategia correcta no es elegir una, sino diseñar para portabilidad desde el día 1.

El patrón Core-First permite que ~80% del código de un plugin viaje entre plataformas sin cambios. Los adapters específicos (ese ~20% restante) son el precio justo por acceder a las capacidades únicas de cada ecosistema.


📚 Fuentes y Referencias

Todas las afirmaciones en esta clase están respaldadas por documentación oficial y código fuente verificable.

OpenCode

Codex CLI (OpenAI)

Claude Code (Anthropic)

MCP (Model Context Protocol)

SDKs y Paquetes

Última verificación: Junio 2026. Las especificaciones y documentación pueden cambiar; consulte las fuentes oficiales para información actualizada.