Capitulo 14: Comandos Custom
Capitulo 14: Comandos Custom
< Volver al Indice del Tutorial
Que son los Comandos Custom
Los comandos custom son slash commands propios que ejecutan un prompt predefinido. En lugar de escribir instrucciones largas cada vez que necesitas una tarea recurrente, defines un comando una vez y lo invocas con /nombre desde la TUI.
Son el equivalente a aliases de bash pero para prompts del agente AI. Si detectas que escribes el mismo tipo de prompt con frecuencia, como “revisa el último commit”, “genera tests para los cambios” o “verifica que el build compile”, esas son señales claras de que necesitas un comando custom.
La ventaja principal sobre escribir el prompt manualmente es la consistencia. Un comando custom garantiza que siempre se envía exactamente el mismo prompt, con las mismas instrucciones y el mismo nivel de detalle. No hay riesgo de olvidar un paso o de ser menos específico por pereza al escribir.
Configuracion
Los comandos se definen en opencode.json bajo la clave "command":
{
"command": {
"review": {
"template": "Revisa los cambios del ultimo commit. Busca problemas de seguridad, performance y calidad. Genera un reporte con hallazgos.",
"description": "Revisar codigo del ultimo commit"
}
}
}
Cada comando tiene tres partes:
- nombre (la clave del objeto): identificador que escribes en la TUI precedido por
/ - template: el prompt que se envía al agente cuando invocas el comando. Puede incluir variables dinámicas como
$FILEo$SELECTION. - description: texto que aparece en el autocompletado y ayuda a recordar qué hace cada comando.
Opcionalmente, puedes especificar un agente que ejecute el comando:
{
"command": {
"test": {
"template": "Ejecuta la suite de pruebas usando Jest con coverage. Reporta errores.",
"description": "Ejecutar pruebas",
"agent": "build"
}
}
}
El campo agent indica qué agente debe procesar el comando. En este ejemplo, el comando /test se ejecutará con el agente build, que tiene acceso a herramientas de ejecución de comandos del sistema. Si omites el campo agent, se usa el agente por defecto de la sesión.
Uso desde la TUI
Dentro de la interfaz TUI de OpenCode, simplemente escribe el nombre del comando:
> /review
OpenCode reemplaza /review con el template configurado y lo envía al agente correspondiente. Es equivalente a escribir el prompt completo manualmente, pero más rápido y consistente.
Los comandos aparecen en el autocompletado cuando escribes /, junto con los comandos nativos de OpenCode. La descripción que definiste aparece al lado del nombre para ayudarte a identificar cada comando.
sequenceDiagram
participant U as Usuario
participant T as TUI
participant A as Agente
U->>T: /review
T->>T: Busca template del comando "review"
T->>A: "Revisa los cambios del ultimo commit..."
A->>A: Ejecuta el prompt como si lo hubieras escrito
A->>U: Resultado del review
Variables en Templates
Los templates pueden incluir variables dinámicas que OpenCode reemplaza con contexto del proyecto al momento de ejecutar el comando. Las variables disponibles son:
- $FILE: ruta del archivo actualmente seleccionado o en foco
- $SELECTION: texto seleccionado en el editor, si aplica
Esto permite crear comandos que operan sobre archivos o selecciones específicas sin hardcodear rutas:
{
"command": {
"review-file": {
"template": "Revisa el codigo en busca de: seguridad, performance, mantenibilidad. Archivo: $FILE",
"description": "Revisar codigo de un archivo especifico",
"agent": "plan"
},
"explain": {
"template": "Explica en detalle que hace el siguiente codigo y sugiere mejoras: $SELECTION",
"description": "Explicar codigo seleccionado"
}
}
}
Cuando ejecutas /review-file, OpenCode sustituye $FILE con la ruta del archivo actual. Cuando ejecutas /explain, sustituye $SELECTION con el texto que tengas seleccionado. Si la variable no tiene valor en ese momento, se envía vacía.
Asignacion de Agentes
El campo agent es una de las características más poderosas de los comandos custom. Permite dirigir cada comando a un agente específico, aprovechando las capacidades y restricciones de cada uno.
Recuerda del capítulo de agentes que cada agente tiene su propio modelo, herramientas y system prompt. Al asignar un agente a un comando, garantizas que la tarea se ejecuta con la configuración adecuada:
{
"command": {
"test": {
"template": "Ejecuta la suite de pruebas y reporta errores.",
"description": "Ejecutar pruebas",
"agent": "build"
},
"review": {
"template": "Revisa el codigo en busca de problemas de seguridad y calidad.",
"description": "Revisar codigo",
"agent": "plan"
},
"docs": {
"template": "Genera documentacion JSDoc para las funciones publicas sin documentar.",
"description": "Documentar codigo",
"agent": "code"
}
}
}
En este ejemplo:
/testusa el agentebuildporque necesita ejecutar comandos del sistema/reviewusa el agenteplanporque solo necesita analizar código sin modificar nada/docsusa el agentecodeporque necesita editar archivos
Si no especificas un agente, el comando se ejecuta con el agente activo en la sesión actual. Esto es útil para comandos genéricos que funcionan con cualquier agente.
Casos de Uso Practicos
/review: Code Review Automatico
{
"command": {
"review": {
"template": "Ejecuta git diff HEAD~1 y revisa los cambios. Para cada archivo modificado analiza: 1) Problemas de seguridad 2) Problemas de performance 3) Codigo duplicado 4) Nombres poco descriptivos. Genera un reporte ordenado por severidad.",
"description": "Review del ultimo commit",
"agent": "plan"
}
}
}
Este comando es especialmente útil antes de hacer push. Crea el hábito de ejecutar /review después de cada commit significativo. El agente plan es ideal porque analiza sin modificar código.
/test: Generar Tests
{
"command": {
"test": {
"template": "Revisa los archivos modificados con git status. Para cada archivo fuente modificado, genera tests unitarios siguiendo las convenciones existentes del proyecto. Asegurate de cubrir edge cases y caminos de error.",
"description": "Generar tests para cambios recientes",
"agent": "build"
}
}
}
Usa el agente build porque necesita ejecutar git y potencialmente correr los tests después de generarlos para verificar que pasan.
/deploy: Verificar antes de Deploy
{
"command": {
"deploy": {
"template": "Ejecuta las siguientes verificaciones antes del deploy: 1) Corre los tests 2) Verifica que no hay console.log 3) Revisa que no hay secretos hardcodeados 4) Verifica que el build compila sin errores. Reporta el resultado de cada paso.",
"description": "Verificaciones pre-deploy",
"agent": "build"
}
}
}
Un checklist automatizado que ejecutas antes de cada deploy. Elimina el factor humano de olvidar verificar algo crítico.
/fix: Analizar y Corregir Errores
{
"command": {
"fix": {
"template": "Ejecuta el build del proyecto y analiza cualquier error o warning. Para cada problema: 1) Explica la causa 2) Propone una solucion 3) Implementa el fix si es seguro hacerlo. No hagas cambios que puedan romper funcionalidad existente.",
"description": "Analizar errores del build",
"agent": "build"
}
}
}
/docs: Generar Documentacion
{
"command": {
"docs": {
"template": "Busca funciones publicas sin documentacion JSDoc en el directorio src/. Para cada una, agrega documentacion con @param, @returns y @example. No modifiques funciones que ya estan documentadas.",
"description": "Documentar funciones sin documentar",
"agent": "code"
}
}
}
/security: Auditoría de Seguridad
{
"command": {
"security": {
"template": "Analiza el proyecto en busca de vulnerabilidades: 1) Secretos hardcodeados en el codigo 2) Dependencias con CVEs conocidos 3) Inputs sin sanitizar 4) SQL injection o XSS potencial 5) Permisos excesivos. Genera un reporte CRITICAL/HIGH/MEDIUM/LOW.",
"description": "Auditoria de seguridad del proyecto",
"agent": "plan"
}
}
}
Comandos vs Skills
Aunque ambos ayudan a automatizar, tienen propósitos fundamentalmente diferentes:
| Aspecto | Comandos | Skills |
|---|---|---|
| Activación | Explícita con /nombre | Automática por el agente |
| Contenido | Un prompt directo (template) | Instrucciones detalladas en Markdown |
| Alcance | Una acción específica | Convenciones reutilizables |
| Contexto | Se envía como mensaje al agente | Se carga on-demand en el contexto |
| Formato | JSON en opencode.json | Archivo SKILL.md con frontmatter |
| Variables | Soporta $FILE, $SELECTION | No tiene variables dinámicas |
| Agente | Puede especificar agente | El agente activo decide cuándo cargarlo |
En la práctica, un comando puede complementarse con un skill. Por ejemplo, /test puede ser el trigger rápido y un skill testing puede contener las convenciones detalladas que el agente cargará al ejecutar la tarea de generación de tests.
flowchart TD
A["/test"] -->|Envía template| B[Agente build]
B -->|Necesita convenciones| C["skill: testing"]
C -->|Inyecta instrucciones| B
B -->|Genera| D[Tests siguiendo convenciones]
Ejemplo Completo
Configuración de comandos útiles para un proyecto web con Astro:
{
"command": {
"check": {
"template": "Ejecuta estos comandos en orden: 1) bun astro check - verifica TypeScript y Astro 2) bun build - verifica que compila 3) Revisa si hay archivos con mas de 200 lineas en src/. Reporta un resumen de cada verificacion.",
"description": "Verificar salud del proyecto",
"agent": "build"
},
"new-page": {
"template": "Necesito crear una nueva pagina para el tutorial. Preguntame: 1) Nombre del archivo 2) Titulo del capitulo 3) Descripcion breve. Luego crea el archivo con el frontmatter correcto siguiendo el formato de los archivos existentes en la misma coleccion.",
"description": "Crear nueva pagina del tutorial",
"agent": "code"
},
"optimize": {
"template": "Analiza los componentes en src/components/. Para cada uno revisa: 1) Imports no usados 2) Props sin tipar 3) Logica que podria extraerse 4) Oportunidades de lazy loading. Lista las mejoras ordenadas por impacto.",
"description": "Optimizar componentes",
"agent": "plan"
},
"changelog": {
"template": "Lee los ultimos 10 commits con git log y genera un changelog agrupado por: Features, Fixes, Refactors. Usa formato Markdown con links al commit.",
"description": "Generar changelog desde commits",
"agent": "plan"
}
}
}
Observa cómo cada comando usa el agente más apropiado para su tarea. Los comandos de análisis usan plan (solo lectura), los que modifican archivos usan code, y los que ejecutan comandos del sistema usan build.
Configuracion Global vs Proyecto
Los comandos en opencode.json son específicos del proyecto y se comparten con el equipo al commitear el archivo. Pero también puedes definir comandos globales en tu configuración personal:
~/.config/opencode/config.json
Los comandos globales están disponibles en todos tus proyectos. Si un comando con el mismo nombre existe tanto en la configuración global como en la del proyecto, el del proyecto tiene prioridad.
Esto es útil para comandos personales que usas en todos tus proyectos, como tu estilo de review o tus verificaciones estándar. Los comandos específicos del framework o las herramientas del proyecto deben ir en opencode.json del repositorio.
Buenas Practicas
- Prompts claros y acotados: un comando debe hacer una cosa bien. Si un template crece demasiado, probablemente necesites un skill en lugar de un comando.
- Incluye instrucciones de seguridad: agrega guardrails como “no modifiques archivos de configuración” o “no hagas cambios destructivos” para evitar que el agente tome acciones no deseadas.
- Usa nombres cortos:
/reviewes mejor que/hacer-code-review-completo. Los nombres cortos son más rápidos de escribir y más fáciles de recordar. - Documenta con description: aparece en el autocompletado y ayuda a recordar qué hace cada comando, especialmente cuando tienes muchos definidos.
- No dupliques lógica de skills: si el prompt necesita instrucciones detalladas de más de 3-4 líneas, mejor crea un skill y deja que el comando sea el trigger simple.
- Commitea la configuración:
opencode.jsondebe estar en el repositorio para que el equipo comparta los mismos comandos. - Asigna agentes apropiados: usa
planpara análisis,buildpara ejecución de comandos,codepara modificación de archivos. Un agente equivocado puede no tener las herramientas necesarias. - Usa variables cuando aplique: si el comando opera sobre un archivo específico, usa
$FILEen lugar de pedir al usuario que escriba la ruta. - Itera sobre los templates: si un comando no genera los resultados esperados, ajusta el template. A veces una instrucción más específica marca la diferencia entre un resultado mediocre y uno excelente.
Siguiente: Capitulo 15: Plugins —>