Usa referencias @file, allowed-tools, subagentes y herramientas MCP para convertir los slash commands de atajos en una biblioteca de flujos de trabajo del equipo.
Los dos artículos anteriores cubrieron qué es un slash command (un archivo Markdown) y cómo usar el prefijo ! para inyectar la salida del shell en el contexto. Este va más lejos: cómo hacer que un solo command orqueste las capacidades más potentes de Claude Code —referencias a archivos, subagentes, herramientas MCP— manteniendo los permisos bajo control.
A este nivel, un command deja de ser un "atajo de prompt" y se convierte en un pequeño flujo de trabajo reutilizable.
@file: una inyección estática más limpia que !cat!cat file.md mete el contenido de un archivo en el contexto, pero pasa por el shell, y eso tiene costes: lanza un subproceso cada vez, las rutas con espacios o caracteres especiales requieren escape, y Claude Code trata la salida como texto plano, no como "un archivo".
La referencia @ es nativa:
---
description: Revisar los cambios contra las normas del proyecto
---
Material de referencia:
@.claude/context/coding-standards.md
@.claude/context/security-checklist.md
Revisa los cambios del diff de abajo y señala todas las violaciones de estas normas.
!`git diff HEAD`
@ruta le dice a Claude Code "adjunta este archivo a la conversación". La diferencia:
| Escenario | Usar !cat |
Usar @ |
|---|---|---|
La ruta viene de un argumento ($ARGUMENTS) |
✅ Obligatorio | ❌ @ no expande variables |
| Normas, plantillas, convenciones fijas | ⚠️ Funciona pero es pesado | ✅ Nativo, sin shell |
| Contenido dinámico (diff, logs, resultados de tests) | ✅ Obligatorio | ❌ Imposible |
Regla: @ para archivos estáticos, ! para salida dinámica, !cat $ARGUMENTS para rutas parametrizadas.
allowed-tools: fronteras de permisos para commandsPor defecto, un command puede usar todas las herramientas disponibles en la sesión. No siempre es lo que quieres: /review es una tarea de solo lectura y no te conviene que "de paso" edite una línea de código.
Añade allowed-tools al frontmatter y solo las herramientas listadas estarán disponibles mientras se ejecute el command:
---
description: Revisión de código de solo lectura
allowed-tools: Read, Grep, Glob, Bash(git diff:*), Bash(git log:*)
---
Revisa la diferencia entre esta rama y master. Solo lectura, sin ediciones.
!`git diff master...HEAD`
Puntos clave:
Bash(git diff:*) es autorización de grano fino: solo se permiten comandos bash que empiezan con git diff; git push quedaría bloqueadoRead / Grep / Glob otorga explícitamente herramientas de solo lecturaEdit / Write no están listados, así que el modelo no puede modificar código aunque quisieraTambién funciona al revés, con un command de alto privilegio como /deploy:
---
description: Desplegar la rama actual
allowed-tools: Bash(kamal deploy:*), Bash(git push:*), Read
---
Dejar fijado por contrato "qué puede hacer este command" es mucho más fiable que depender de aprobaciones manuales de bash en cada ejecución.
Algunas tareas revientan tu contexto principal: recorrer decenas de archivos para encontrar todas las llamadas a una función, calcular estadísticas de todo el codebase, analizar un log enorme. Hacerlo en línea deja miles de líneas de salida en el contexto, y cada turno posterior se vuelve más lento y torpe.
Lo correcto es delegar ese trabajo a un subagente. Corre en su propio contexto y solo trae la conclusión de vuelta. En el command basta con decirlo explícitamente:
---
description: Investigación profunda de todos los usos de un símbolo
allowed-tools: Task
---
Usa un subagente Explore para investigar en profundidad todos los usos de: $ARGUMENTS
El subagente debe cubrir:
- Todos los puntos de llamada (incluidos los archivos de test)
- Los escenarios de negocio cubiertos
- Si existen implementaciones alternativas equivalentes
Cuando el subagente regrese, dame un resumen de menos de 300 palabras. No pegues fragmentos de código en bruto.
Dispara /trace SomeClass#some_method y Claude Code arranca un subagente Explore que recorre el codebase en paralelo. La conversación principal recibe solo la conclusión destilada. Ni salida de grep, ni fragmentos de archivos. El contexto queda limpio.
Un paso más:
---
description: Investigar tres enfoques candidatos en paralelo
allowed-tools: Task
---
Arranca 3 subagentes en paralelo, cada uno investigando una ruta de implementación:
1. ActiveJob + Sidekiq existentes
2. Solid Queue
3. Una cola ligera hecha en casa
Cada agente informa: esfuerzo, riesgo y cuán invasivo es el cambio sobre el código actual. Cuando los tres regresen, yo comparo.
Tres agentes corriendo en paralelo, la conversación principal espera una sola vez. Este es uno de los mayores puntos de apalancamiento que ofrece un command: convertir "tareas de investigación que cuestan muchos tokens" en un disparador de una sola pulsación.
Si la sesión tiene servidores MCP conectados (Linear, GitHub, Sentry, un proxy de base de datos interno, etc.), el command puede indicar al modelo que los use:
---
description: Convertir un Linear issue en un plan de implementación
allowed-tools: mcp__linear__*, Read, Grep
---
Trae la descripción completa y los comentarios del Linear issue $ARGUMENTS.
Combinándolo con el estado actual del codebase (usa Grep/Read para localizar los archivos relevantes), produce un todo de implementación:
- Qué archivos hay que cambiar
- Si cada paso debe ser su propio commit o agruparse
- Cualquier ambigüedad que requiera hablar antes con PM
No empieces a escribir código. Solo el plan.
mcp__linear__* autoriza todas las herramientas MCP de Linear: el modelo puede obtener detalles del issue, comentarios, estado. Todo el command se convierte en la entrada de un flujo "de ticket a plan de implementación".
Ojo: los nombres de herramientas MCP en allowed-tools necesitan el prefijo completo (mcp__<servidor>__<herramienta>), o la autorización no se aplica.
Un malentendido común: meter /test dentro del archivo de /review para "disparar" el command de test. No funciona. Los slash commands se expanden exactamente una vez, en la entrada del usuario. Un /xxx dentro del cuerpo de un command es solo texto: el modelo lo lee, pero Claude Code no lo ejecuta.
Si quieres componer commands, las opciones correctas son:
Opción A: extrae la lógica compartida a archivos de contexto y referénciala desde cada command con @ o !cat
@.claude/context/review-checklist.md
@.claude/context/security-checklist.md
Opción B: escribe "hazlo como lo hace /review" y repite las instrucciones clave
No es elegante pero funciona. Mientras el prompt sea claro, el modelo seguirá la misma ruta.
Opción C: haz que un command use la herramienta Task para arrancar un subagente, y reutiliza los mismos archivos de contexto dentro del prompt del subagente
Toda la orquestación real de flujos vive aquí. El command padre despacha y resume; el subagente ejecuta el paso real.
El antipatrón a evitar: escribir un solo command de cientos de líneas intentando hacerlo todo de una vez. El coste de mantenimiento se dispara y una sola ejecución se come tu presupuesto de tokens.
Con @, !, subagentes y herramientas MCP en juego, los mecanismos para inyectar "capacidad externa" en un command están todos sobre la mesa. Cómo elegir:
| Necesidad | Elección |
|---|---|
| Normas, plantillas, documentos de contexto fijos | Referencia @file |
| Estado en vivo (diff, logs, tests, consultas DB) | Inyección !shell |
| Contenido de archivo parametrizado | !cat $ARGUMENTS |
| Investigación pesada en contexto, búsqueda cross-file | Subagente vía Task |
| Sistemas externos (tracker, monitoreo, datos prod) | Herramientas MCP + allowed-tools |
| Flujos multi-paso en serie o paralelo | Command padre que despacha subagentes |
Declara las fronteras de permisos explícitamente con allowed-tools, sobre todo en commands que todo el equipo comparte. Fijar qué puede hacer un command es mejor que confiar en aprobación manual en cada ejecución.
Juntándolo todo: un command que convierte un Linear ticket en un plan de implementación:
---
description: Generar un plan de implementación desde un Linear ticket
allowed-tools: mcp__linear__*, Task, Read, Grep, Glob, Bash(git log:*)
---
## Contexto
@.claude/context/architecture.md
@.claude/context/coding-standards.md
## Estado actual del repo
!`git log --oneline -10`
## Tarea
Trae el Linear ticket $ARGUMENTS: descripción, comentarios y tickets relacionados.
Después arranca dos subagentes en paralelo:
1. Primer agente: rastrea el codebase en busca de implementaciones existentes relevantes y módulos reutilizables
2. Segundo agente: evalúa el riesgo: qué rutas de código de alto tráfico toca este cambio, dónde hay huecos en la cobertura de tests
Cuando ambos regresen, devuelve:
- Pasos de implementación (ordenados por dependencia)
- Lista de riesgos
- Granularidad de commits sugerida
No empieces a escribir código.
Ejecuta /plan ENG-4213 y un solo command recorre todo el flujo: obtener ticket → investigación paralela del codebase → evaluación de riesgo → plan sintetizado. Lo único que hace el usuario es leer la salida y decidir si empezar.
Con esto se cierra el arco de los primeros tres artículos de la serie: definir prompts reutilizables (intro) → inyectar contexto dinámico (context) → orquestar herramientas y subagentes (este). A este nivel, .claude/commands/ ya no es un directorio de atajos. Es una pequeña biblioteca de flujos de trabajo que tu equipo comparte.