Slash Commands avanzados: haz que tus comandos entiendan el contexto

Usa el prefijo ! para ejecutar comandos shell dentro de slash commands e inyectar automáticamente diffs, contenido de archivos y resultados de tests


La mayoría de los slash commands tienen esta pinta:

Revisa la calidad del código de los cambios actuales y da sugerencias concretas.

Funciona, pero tiene un límite de fondo: Claude tiene que deducir por su cuenta "cuáles son los cambios actuales". Si tu command inyecta el contexto por ti, el resultado cambia por completo.

Este artículo trata de cómo convertir un command en una instrucción "con ojos": al dispararse lee archivos, estado de git, información del proyecto, y mete todo eso dentro del prompt para que Claude no tenga que adivinar.


El mecanismo central: !`comando` para inyectar salida del shell

Los slash commands personalizados permiten incrustar comandos de shell dentro del prompt. La sintaxis: envuelve el comando en backticks y añade un signo de exclamación delante: !`comando`. Al disparar el command, primero se ejecuta el comando, su salida reemplaza el marcador, y Claude recibe el prompt ya ensamblado.

Este es el git diff actual:

!`git diff HEAD`

Revisa estos cambios, centrándote en errores de lógica y problemas de seguridad.

Para comandos de varias líneas usa un bloque de código con cerca, abriendo con ```!:

```!
node --version
git status --short
```

Cuando disparas /review, lo que Claude recibe en realidad es:

Este es el git diff actual:

diff --git a/app/models/user.rb b/app/models/user.rb
index 3a2f1c8..9b4e2d1 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -12,6 +12,9 @@ class User < ApplicationRecord
...

Revisa estos cambios, centrándote en errores de lógica y problemas de seguridad.

No hace falta que copies y pegues nada. En el instante en que disparas el command, el diff ya está dentro.


Patrones útiles

Inyectar el contenido del archivo actual

---
allowed-tools: Bash(cat:*)
---

Este es el contenido completo del archivo actual:

!`cat $ARGUMENTS`

Encuentra todos los posibles problemas de rendimiento en este archivo, con número de línea concreto y cómo arreglarlo.

Uso: /perf app/models/order.rb

$ARGUMENTS recibe la ruta del archivo y cat inyecta su contenido. Claude ve el código real, no una descripción vaga tipo "mira el archivo actual".

allowed-tools en el frontmatter preautoriza el comando cat, así que al disparar no aparece el diálogo de permisos. Sin esa línea, cada ejecución te pide pulsar "permitir". Los ejemplos siguientes necesitan la misma declaración.

Inyectar el estado de git

Rama actual y estado de los cambios:

!`git status --short`
!`git log --oneline -10`

Con la información anterior, genera una descripción de PR breve, con el contenido y la motivación de los cambios.

Este command /pr no necesita que le expliques "qué cambié": lo lee él solo.

Inyectar información específica del proyecto

Stack técnico del proyecto:

!`cat .claude/context/stack.md`

Estructura actual de la base de datos (tablas clave):

!`head -100 db/schema.rb`

Con el contexto anterior, escribe un script de migración para $ARGUMENTS que siga las convenciones del proyecto.

Guarda la información de fondo del proyecto en .claude/context/ de antemano y deja que el command la lea bajo demanda cuando se dispare. Así no tienes que repetir la descripción del proyecto cada vez.

Leer resultados de tests dinámicamente

Resultado de la última ejecución de tests:

!`bundle exec rspec --format progress 2>&1 | tail -30`

Arriba están los tests que fallaron. Analiza la causa raíz y propón una solución. No toques los tests.

Al disparar /fix-tests se ejecutan los tests y se recoge el resultado en el momento; Claude ve los mensajes de error reales.


Ejemplo completo: revisión de código consciente del contexto

Combinando todo lo anterior, /review puede quedar bastante fino:

---
description: Revisa los cambios actuales, inyectando automáticamente el diff y el contexto relevante
allowed-tools: Bash(git diff:*), Bash(cat:*)
---

## Cambios de esta sesión

!`git diff HEAD`

## Archivos afectados

!`git diff HEAD --name-only`

## Resumen de las convenciones de código del proyecto

!`cat .claude/context/coding-standards.md 2>/dev/null || echo "(sin archivo de convenciones)"`

---

Revisa los cambios anteriores:

1. Corrección lógica: casos límite sin manejar, errores de lógica
2. Seguridad: inyección SQL, validación de permisos, filtrado de información sensible
3. Adherencia a las convenciones: si cumple el estándar del proyecto
4. Legibilidad: nombres, comentarios, estructura

Para cada problema indica archivo, línea y sugerencia concreta. Si no hay problemas, dilo; no rellenes por rellenar.

Este command no exige ninguna preparación: al dispararlo, diff, lista de archivos y convenciones se inyectan solos.


Manejar fallos de comandos

Los comandos de shell pueden fallar (archivo inexistente, comando fuera del PATH, etc.). Usa || para dar un valor por defecto y evitar que el command se rompa:

!`git diff HEAD 2>/dev/null || echo "(sin cambios en git o fuera de repositorio)"`
!`cat .env.example 2>/dev/null || echo "(no hay archivo .env.example)"`
!`which rspec > /dev/null 2>&1 && bundle exec rspec --dry-run 2>&1 | head -20 || echo "(RSpec no detectado)"`

Cuando el comando falla, Claude recibe un texto explicativo en lugar de un vacío, y puede ajustar su respuesta en consecuencia.


Rendimiento: no inyectes de más

Todo lo que sale de los comandos ! entra en el context window. Trampas habituales:

No hagas cat de un archivo enorme

# Peligroso: puede inyectar decenas de miles de líneas
!`cat db/schema.rb`

# Mejor: coge solo lo que necesitas
!`grep -A 5 "create_table \"orders\"" db/schema.rb`

Limita líneas en los logs

!`tail -50 log/development.log`

Trunca la salida de los tests

!`bundle exec rspec 2>&1 | tail -40`

Cuanto más preciso sea el contexto, mejor responde Claude. Meter todo el código base no lo vuelve más listo; solo lo pierde entre el ruido.


Reparto con CLAUDE.md

La duda habitual: ¿la información de fondo del proyecto va en CLAUDE.md o se inyecta dinámicamente con !?

Criterio:

Tipo de información Dónde va
Contexto del proyecto que siempre hace falta (stack, estructura de directorios, convenciones) CLAUDE.md
Estado que cambia con el tiempo (diff actual, resultado de tests, contenido de un archivo) Inyección dinámica con !
Contexto que solo necesita una tarea concreta (notas de diseño de un módulo) !cat bajo demanda

CLAUDE.md es conocimiento de fondo persistente; ! es una instantánea inmediata para la tarea. Son complementarios, no los dupliques.


Un directorio .claude/commands/ completo

.claude/
├── commands/
│   ├── review.md        # Review: inyecta diff + convenciones
│   ├── test.md          # Escribir tests: inyecta el archivo objetivo
│   ├── fix-tests.md     # Arreglar tests: inyecta los fallos
│   ├── pr.md            # Descripción de PR: inyecta git log + status
│   ├── explain.md       # Explicar código: inyecta el contenido del archivo
│   └── migrate.md       # Migraciones: inyecta fragmento del schema
├── context/
│   ├── stack.md         # Descripción del stack técnico
│   └── coding-standards.md  # Convenciones de código
└── settings.json

El directorio context/ guarda archivos de fondo estáticos que los distintos commands leen cuando los necesitan. Esta estructura puedes meterla en git tal cual y compartirla con el equipo.


Comparación de resultado

Command estático:

Revisa los cambios actuales del código.

Claude tiene que preguntar "¿dónde están los cambios?" o buscarlos por su cuenta; el resultado es inconsistente.

Command consciente del contexto:

Aquí tienes el diff (con contenido real) y las convenciones relevantes (con contenido real). Revísalo.

Claude empieza a analizar directamente. Responde con precisión, sin paja ni rondas de confirmación.

La diferencia no está en las capacidades de Claude, sino en cuánta información real le das.