Todos los recursos

Cuando reescribes las mismas instrucciones en Claude Code por décima vez, ya no estás escribiendo prompts: estás capturando datos. Un comando slash convierte ese prompt repetido en una plantilla versionada, que recibe argumentos y vive dentro de tu repo. Esta guía arma uno desde cero, cubre argumentos, referencias a archivos e inyección de bash, y luego te muestra los errores de alcance y de diseño que vuelven peso muerto un comando que era útil.

Crea un comando slash personalizado en Claude Code (de esos que el equipo sí usa)

En resumen

  • Un comando slash es un archivo Markdown que Claude Code carga como plantilla de prompt. Nada de plugins, nada de código.
  • Los comandos de proyecto viven en .claude/commands/ y viajan con el repo. Los personales viven en ~/.claude/commands/.
  • Usa \$ARGUMENTS para todo lo que viene después del comando, o \$1 \$2 para entradas posicionales.
  • Apunta a archivos con @ruta e inyecta la salida de shell en vivo con una línea que arranca con !, y así el comando arma su propio contexto.
  • El campo description del frontmatter es lo que sale en el menú. allowed-tools limita lo que el comando puede ejecutar. Que cada comando haga una sola cosa.

Deja de reescribir el mismo prompt y escríbelo una sola vez. Como en la décima vez que pegas el mismo bloque de "revisa este archivo en busca de problemas de seguridad, dame línea, severidad y un arreglo", ya dejaste de escribir prompts y solo estás capturando datos. Las instrucciones siempre son las mismas. Lo único que cambia es el archivo. Para eso, justamente, sirve un comando slash. Al terminar esta guía vas a tener un comando de verdad: recibe argumentos, carga archivos y el estado actual de git por su cuenta, queda limitado a las herramientas que realmente necesita y queda guardado en el commit para que todos en el repo corran la misma versión. Y de paso vas a conocer las decisiones de diseño que separan un comando al que la gente vuelve una y otra vez de uno que se queda muerto en el menú.

Un comando slash no es un macro ni un script. Es una plantilla de prompt. Un archivo Markdown que Claude Code lee, rellena con tus argumentos y manda como la primera instrucción del turno. Verlo así importa, porque te aclara qué cabe dentro de uno (instrucciones que se repiten, la forma de una tarea) y qué no (cualquier cosa que dependa de un criterio que no puedas dejar escrito de una vez por todas).

01 · Requisitos y dónde viven los comandos

Nada de esto es complicado, pero arrancar con la idea equivocada te cuesta diez minutos de confusión.

  • Claude Code instalado y autenticado. Corre claude dentro del directorio de un proyecto y confirma que te sale el prompt.
  • Un repo git para el proyecto, para que puedas subir el comando al repo y viaje junto con el código.
  • Permiso de escritura en la raíz del proyecto, porque ahí es donde viven los comandos de proyecto, en .claude/commands/.

Los comandos viven en dos lugares, y elegir uno u otro depende del público, no del gusto:

  • Comandos de proyecto en .claude/commands/ dentro del repo. Quedan subidos al repo, así que cada clon y cada compañero los recibe. Aquí van los estándares del equipo.
  • Comandos personales en ~/.claude/commands/ en tu carpeta de usuario. Estos te acompañan a ti en cada proyecto, pero nadie más los ve. Sirven para tus costumbres personales. No sirven para nada que el equipo deba compartir.

El nombre del archivo pasa a ser el nombre del comando. .claude/commands/security-review.md se invoca como /security-review. Los subdirectorios funcionan como prefijo de namespace en el menú, así que .claude/commands/git/cleanup.md aparece como /cleanup agrupado bajo "git". Así mantienes en orden un conjunto de comandos que no para de crecer.

Nota

Un comando de proyecto y uno personal pueden tener el mismo nombre sin chocar, y el menú te muestra los dos para que distingas cuál es cuál. Ante la duda, quédate con el de proyecto. Un comportamiento que es igual para todo el equipo le gana a uno que solo funciona en tu máquina.

02 · El comando mínimo

Crea .claude/commands/security-review.md:

---
description: Revisa un archivo por problemas de seguridad y propone arreglos concretos
---

Revisa el archivo en $ARGUMENTS por inyección, secretos filtrados y fallos de authz.

Por cada hallazgo, da:
- el archivo y el número de línea
- una severidad (baja / media / alta)
- un arreglo concreto y mínimo

No refactorices código no relacionado. Si no encuentras nada, dilo claro.

Guárdalo y, en Claude Code, escribe /security-review src/auth.ts. Claude Code reemplaza $ARGUMENTS por src/auth.ts y corre el prompt ya completo. Hay dos piezas haciendo el trabajo:

  1. El frontmatter es el bloque YAML de arriba. La description es lo que aparece en el menú de /, así que escríbela como una frase con verbo que un compañero entienda al instante: "Revisa un archivo en busca de problemas de seguridad", no "cosas de seguridad".
  2. El cuerpo es el prompt en sí, con $ARGUMENTS como marcador de lo que el usuario escriba después del nombre del comando. Todo lo demás son instrucciones a secas.

Ese es todo el mecanismo. Sin registrar nada, sin reiniciar. Pones el archivo y el comando ya existe.

03 · Argumentos, todos juntos o uno por uno

$ARGUMENTS captura como un solo string todo lo que viene después del comando. Va perfecto cuando hay una sola entrada o cuando el orden da igual. Cuando necesitas entradas distintas y en cierto orden, mejor usa marcadores posicionales:

---
description: Abre una revisión de PR enfocada en un área de riesgo específica
argument-hint: <numero-pr> <area-de-enfoque>
---

Revisa el PR #$1 con un enfoque específico en $2.

Trae el diff y luego comenta solo sobre problemas relacionados con $2. Ignora
detalles de estilo. Resume los tres riesgos principales y si el PR es seguro de mergear.

Ahora /pr-review 412 concurrencia pone $1 en 412 y $2 en concurrencia. Un par de reglas que te ahorran dolores de cabeza:

  • Usa $ARGUMENTS para el caso simple y deja $1, $2 para cuando de verdad tengas entradas separadas. Mezclar las dos cosas en un mismo comando confunde a quien lo lee, y hasta a ti.
  • Agrega un argument-hint en el frontmatter. Sale en el menú como pista de uso, así la siguiente persona sabe que el comando espera <numero-pr> <area-de-enfoque> y no texto suelto.
  • Escribe el prompt para que, si falta un argumento, igual no falle de forma fea. Si alguien corre /pr-review sin nada, el cuerpo debería seguir leyéndose como una instrucción razonable, aunque genérica, en lugar de quedar apuntando a un $1 vacío.

Consejo

Prueba la sustitución de argumentos con un comando de mentira antes de confiarle un flujo real. Arma un comando de una línea cuyo cuerpo sea solo "Devuélveme tal cual lo que recibiste: $ARGUMENTS" y córrelo con varias entradas. Una vez que veas cómo quedan los espacios y las comillas, vas a escribir el prompt de verdad con toda la confianza.

04 · Deja que el comando arme su propio contexto

Aquí es donde los comandos slash dejan de ser un simple copiar y pegar y de verdad empiezan a valer la pena. Un comando puede apuntar a archivos e inyectar la salida de shell en vivo, así que llega ya sabiendo el estado de tu repo en lugar de pedirte que se lo pegues.

Son dos mecanismos, los dos se usan dentro del cuerpo:

  • Referencias a archivos con @. Escribir @src/auth.ts en el cuerpo le dice a Claude Code que cargue el contenido de ese archivo al contexto. Puedes apuntar siempre a un archivo fijo, o combinarlo con un argumento.
  • Inyección de bash con !. Una línea que arranca con ! corre ese comando de shell antes de mandar el prompt, y su salida queda incrustada dentro del prompt. Así es como un comando puede ver el estado real de tu git.

Este es un comando de commit-message que lee el diff en stage por su cuenta:

---
description: Redacta un mensaje conventional-commit a partir del diff staged
allowed-tools: Bash(git diff:*), Bash(git status:*)
---

Branch actual y estado:

!git status --short --branch

Cambios en stage:

!git diff --cached

Escribe un solo mensaje de Conventional Commits para los cambios staged de arriba.
Usa uno de: feat, fix, docs, refactor, test, chore. Mantén el subject bajo
72 caracteres. Agrega un body corto solo si el cambio no se explica solo.

Cuando corres /commit-msg, Claude Code ejecuta los dos comandos de git, mete su salida en el prompt justo donde estaban las líneas con !, y Claude redacta un mensaje apoyado en el diff real. No pegas absolutamente nada. Fíjate en la línea allowed-tools del frontmatter. Deja en lista blanca exactamente los comandos de shell que este comando tiene permitido correr. Sin una lista de permitidos explícita, un comando que quiera usar bash te pide permiso cada vez. Con ella, solo esos patrones específicos quedan preaprobados.

Atención

La inyección de bash corre comandos reales, con tu shell y tus permisos, antes de que Claude vea un solo token. Mantén allowed-tools tan acotado como el comando lo necesite: Bash(git diff:*), no un Bash(*) que abarque todo. Un comando que puede correr cualquier cosa en la shell es un comando que puede hacer cualquier cosa, incluidas las que no tenías en mente cuando lo escribiste medio dormido.

05 · Ejemplo completo y los errores que matan la adopción

Sigamos un comando de punta a punta y después veamos por qué fallan las versiones obvias pero equivocadas.

Tomemos el comando /commit-msg de arriba. Este es el flujo completo:

  1. Pones tus cambios en stage con git add -p, como de costumbre.
  2. Escribes /commit-msg en Claude Code.
  3. Claude Code corre las líneas !git status y !git diff --cached y captura su salida.
  4. Arma el prompt final: primero el estado, luego el diff y al final tus instrucciones.
  5. Claude te devuelve un mensaje de Conventional Commits que describe de verdad lo que pusiste en stage, porque leyó el diff, no porque lo adivinó.

La ganancia es que el comando trae su propio contexto. Compáralo con la versión en la que corres git diff tú mismo, lo pegas en el chat y después escribes tus instrucciones. Mismo resultado, pero juntando todo a mano, una y otra vez.

Ahora los modos de falla, porque enseñan más que el camino feliz:

  • El comando que quiere hacer de todo. Un comando /ship que revisa código, escribe tests, actualiza el changelog y redacta una nota de release es, en el fondo, un prompt peor disfrazado de comando. Cuesta ponerle nombre, cuesta confiar en él y no puedes reutilizar ninguna de sus partes. Un comando, una tarea. Compón el flujo corriendo varios en secuencia.
  • Una description vaga. Si el menú dice "ayudante" o "haz lo tuyo", nadie sabe cuándo usarlo, ni siquiera tu yo del futuro. La description es toda la interfaz del comando en el menú, así que escríbela como si nombraras un endpoint de una API.
  • Fijar en el código lo que debería ser un argumento. Un comando que siempre revisa src/auth.ts te sirve exactamente una vez. Si lo único que cambia entre usos es una ruta o un tema, eso es un argumento, no una constante.
  • Personal cuando debería ser de proyecto. Poner el comando de revisión estándar del equipo en ~/.claude/commands/ hace que funcione para ti y que, sin que nadie se entere, no exista para los demás. El comportamiento del equipo va en el repo.

Importante

Haz commit de tu directorio .claude/commands/. Un comando que vive solo en tu máquina te da una ventaja que nadie más tiene y, sin que lo notes, se va separando de lo que el resto del equipo sigue haciendo a mano. Todo el beneficio (comportamiento consistente en el equipo, revisable en pull requests como cualquier otro código) sale del control de versiones.

Un buen comando slash se mete en tu memoria muscular. Dejas de pensar en el prompt y empiezas a pensar en la tarea. Arranca con un comando que de verdad reescribas seguido, dale una description clara y el acceso a herramientas más acotado posible, y súbelo al repo. Cuando ese ya se sienta invisible, ese mismo patrón (instrucciones estables, argumentos para lo que cambia y el comando armando su propio contexto) es como vas a ir convirtiendo el resto de tus prompts repetidos en herramientas que todo el equipo comparte.

Puntos clave

  • Un comando slash es una plantilla de prompt en Markdown dentro de .claude/commands/. Nada de plugins, nada de reiniciar, y el nombre del archivo es el nombre del comando.
  • Usa \$ARGUMENTS para una sola entrada y \$1/\$2 para entradas distintas y en cierto orden. Agrega un argument-hint para que el menú documente el uso.
  • Deja que el comando arme su contexto: @ruta carga archivos y una línea ! inyecta la salida de shell en vivo antes de mandar el prompt.
  • Acota bash con allowed-tools a los patrones exactos que el comando necesita, nunca un Bash(*) que abarque todo, porque el comando corre con tus permisos.
  • Un comando, una tarea. Escribe una description con verbo, y sube al repo los comandos de proyecto para que todo el equipo corra la misma versión.

Preguntas frecuentes

¿Cuál es la diferencia entre un comando slash y un subagente?

Un comando slash es una plantilla de prompt que corre dentro de tu conversación actual. Rellena los argumentos y manda el texto como tu siguiente instrucción. Un subagente es un asistente aparte, con su propio contexto, su system prompt y su propio set de herramientas, que resuelve una tarea de forma aislada y te devuelve un resumen. Usa un comando para no tener que reescribir un prompt una y otra vez. Usa un subagente cuando una tarea ensuciaría tu contexto principal y prefieres sacarla a un lado.

¿Tengo que reiniciar Claude Code después de agregar un comando?

No. Pon el archivo Markdown en .claude/commands/ y el comando queda disponible al instante: no hay paso de registro ni de build. Si no lo ves en el menú de /, revisa el nombre del archivo (es el que pasa a ser el nombre del comando) y que esté en el directorio correcto, el del proyecto o el de tu carpeta de usuario.

¿Cuándo uso \$ARGUMENTS contra \$1 y \$2?

Usa \$ARGUMENTS cuando hay una sola entrada o cuando todo el resto de la línea es una sola cosa, como una ruta de archivo o un tema en texto libre. Usa \$1, \$2 cuando tienes entradas distintas y en cierto orden, que cumplen papeles diferentes dentro del prompt: un número de PR y un área de enfoque, por ejemplo. No mezcles los dos estilos en un mismo comando. Quédate con el que vaya con la forma de la tarea.

¿Es seguro usar la inyección de bash (el prefijo !)?

Es seguro si lo acotas. La línea ! corre un comando de shell real con tus permisos antes de mandar el prompt, así que trátalo como cualquier otro código que subes al repo. Limita lo que el comando puede correr con una línea allowed-tools en el frontmatter: lista los patrones exactos, como Bash(git diff:*), en vez de un Bash(*) que abarque todo. El peligro no está en la función en sí. Está en que un comando capaz de correr cualquier cosa termine haciendo algo que no querías.

¿Comando de proyecto o personal? ¿A cuál debería ir por defecto?

Por defecto, elige proyecto (.claude/commands/) para todo lo que al equipo le convenga correr igual: estándares de revisión, convenciones de commit, pasos de release. Deja personal (~/.claude/commands/) solo para costumbres que son únicamente tuyas y que no tienen por qué meterse en el repo de los demás. La regla práctica es simple. Si te gustaría que un compañero lo corriera idéntico, súbelo al repo.

¿Un comando puede llamar a otro, o encadenar pasos?

No trates de armar un mega-comando que lo haga todo. Que cada comando haga una sola tarea y arma el flujo corriendo varios en secuencia dentro de la misma sesión: revisa, luego testea, luego commit-msg. Así cada uno sigue siendo fácil de nombrar, de reutilizar y de confiar en él. Un comando que intenta hacer cinco cosas no es más que una peor versión de un prompt normal.

¿Prefieres que lo hagamos por ti?

Esto mismo lo construimos para negocios como el tuyo. La primera conversación es gratis y sin compromiso.

Escríbenos por WhatsApp

Escríbenos por WhatsApp

Escanéalo con tu teléfono para escribirnos por WhatsApp.

Escanéalo con tu teléfono para escribirnos por WhatsApp.

¿Estás desde el teléfono y no puedes escanear? Escríbenos a info@ilustrari.com

Primera conversación gratis. Te responde el fundador.

Recursos relacionados