Saltar a contenido

Index

Coding Agentes: Commands en Gemini

Serie de artículos sobre funcionalidades para inyectar contexto en los coding agents:
  1. Funcionalidades de "inyección de contexto"
  2. Commands en Cursor
  3. Commands en Gemini
  4. Commands en Claude (Codex y OpenCode)
  5. Cómo funcionan las rules en distintos Coding Agentes
  6. Cómo funcionan las Agent Skills

En esta artículo nos centramos en cómo funcionan los commands en Gemini. Las pruebas han sido hechas sobre la versión 0.33.1.

Gemini no tiene un nombre genérico para estas funcionalidades y en su documentación están dispersas entre "Features", "Usage" y "Configuration". Contempla:

Además de otras funcionalidades cómo modificar el System Prompt, Subagents, Remote Subagents y Plan Mode. Y no tiene un sistema de reglas.

Commands

La documentación oficial es bastante clara.

  • Van en .gemini/commands del proyecto o de ~.
    • Admite namespaces (subdirectorios). .gemini/commands/git/commit.toml se convierte en /git:commit.
  • Por algún motivo inexplicable, usa ficheros TOML
  • Los campos del TOML son description el texto de ayuda que pone para el comando y prompt donde metes las instrucciones en sí.
  • Admite cierto grado de interpolación.
    • {{args}} El placeholder es substituido por el texto que acompaña al comando en el chat.
    • !{{...}}. Ejecuta el comando y substituye el placeholder por la salida. Se puede combinar con args: !{grep -r {{args}} .}
    • @{path/to/file_or_dir}. El placeholder es substituido por el contenido del fichero o los ficheros del directorio. Esta substitución es la primera así que no se puede combinar con {{args}} y pasar el path cómo parámetro.
  • No son composables sólo funciona el / al principio del prompt.

Una de las cosas buenas de que gemini-cli sea software libre es que podemos ver cómo funciona y no hacer observaciones indirectas cómo en Cursor.

El propio gemini tras estudiar su código responde más o menos esto a si es lo mismo usar @ que un command

Gemini CLI uses clear separators and headers to help the model distinguish between your prompt, injected files, and shell command outputs, rather than complex XML tags. For @file references, it uses REFERENCE_CONTENT_START and REFERENCE_CONTENT_END markers, with individual file contents prefixed by --- filename ---. Custom slash commands defined in .toml files expand @{path} with similar --- filename --- headers and use --- Start of content for directory: path --- for directory injections

Shell command output !{command} is appended with exit codes or signal markers if they fail, and if a command doesn't use {{args}}, the raw invocation is appended to the end of the prompt to provide context. Overall, the system relies on these human-readable delimiters to maintain context without over-engineering the prompt structure.

Vamos que no hay magia. Y en las pruebas que he hecho los resultados era similares.

Conclusiones

  • gemini-cli al contrario que Cursor, no hace magia con los comandos, simplemente es un texto añadido al prompt
  • Las opciones de interpolación de los comandos pueden abrir usos creativos. Pero no tengo claro cual puede ser la diferencia entre interpolar un !{git diff} y decirle que use git diff y con la salida escriba el mensaje de commit. Allá de menos requests. Quizás menos consumo de tokens
  • Usar formato TOML para algo cómo esto es tocar las narices. Tiene pinta de over engineering.

Coding Agentes: Commands en Cursor

Serie de artículos sobre funcionalidades para inyectar contexto en los coding agents:
  1. Funcionalidades de "inyección de contexto"
  2. Commands en Cursor
  3. Commands en Gemini
  4. Commands en Claude (Codex y OpenCode)
  5. Cómo funcionan las rules en distintos Coding Agentes
  6. Cómo funcionan las Agent Skills

En esté artículo nos centramos cómo funcionan los commands en Cursor. Las pruebas han sido hechas sobre la versión 2.5.

Saber que hace Cursor under the hood es muy difícil. He probado con HTTP Toolkit pero es difícil de saber que información se envía realmente. Así que no va a ser un proceso científico sino basado en un par de pruebas y en la documentación.

Los commands se introdujeron en septiembre de 2025 y recomiendan substituirlos por skills desde enero de 2026.

Prácticamente han eliminado toda la documentación referida a los commands:

Los commands son:

  • Ficheros markdown que pueden contener un frontmatter de name y description. Que no parece valer para nada.
  • Van en el .cursor/commands del proyecto o de ~. No busca en subdirectorios.
  • Se invocan a demanda del usuario en el chat con /nombre-del-comando
  • Y una cosa chula es que son composables: /check-compiler-errors and /commit, then create a /pr.

Cual es la diferencia con las reglas

Las reglas se usan:

  • Siempre
  • Bajo criterio del agente
  • Cuando lo fuerza el usuario.
  • Combinación de patrones sobre los nombres de archivos, criterio del agente, ...

Los comandos funcionan estrictamente bajo demanda del usuario.

Además en Cursor parece haber cierta lógica interna asociado al uso de un comando.

Las reglas deberían usarse para definir estándares, guidelines, ... que el LLM debe seguir. En definitiva "reglas". Sería un follow this rules when making a refactor

Los comandos deberían usarse para pedir al LLM que lleve a cabo una acción y definir los pasos para ejecutarla. Sería un make a refactor

Por supuesto hay overlap pero al menos la intención debería ser clara.

Cual es la diferencia con las skills

El metadata de las skill se carga siempre y el agente decide cuando usar una skill o puede ser forzado por el usuario.

Las skills pueden ser muy complejas y encapsular scripts, ...

Las skills en teoría son un estándar, mientras que los comandos no.

Si hay alguna diferencia a nivel resultado de la ejecución /commit vs skill/commit/SKILL.md queda para artículos futuros.

Hay alguna diferencia con referenciar un documento

Una de las cosas que más preocupan es cómo mantener agent stuff compatible entre herramientas. Así que, ¿hay alguna diferencia entre referenciar un documento en el chat con @ y usar un comando?.

Para comprobarlo he creado un fichero refine-english.md

# refine-english

## Task

Refine the English prose in the provided file.

- Clarity: Simplify wording to be accessible for non-native speakers. Avoid flowery language.
- Correction: Fix all grammar, spelling, and punctuation errors.
- Constraint: Maintain the original structure and core intent. Focus strictly on clarity and consistency.

## Output Instructions

- Agent must edit the file directly.
- In the agent chat response:
    - Do not summarize minor edits. Only mention changes if they significantly alter the meaning.
    - Refinements & Critiques: Point out logical inconsistencies, suggest deeper structural improvements, or critique the overall flow.

Cuando lo uso cómo comando /refine-english @mydoc.md:

  • Es muy directo (se ve en la cadena de pensamiento). Sabe que tiene que ejecutar unas instrucciones sobre un fichero.
  • Sigue bien las instrucciones.
    • Algún documento tenía mezclaba inglés y español. Dejo el texto en castellano intacto y el chat lo indicó directamente "The document is mostly Spanish, consider ..." o veladas "Updated the English parts of ". Hay que estar fino para darse cuenta de "English parts".
    • Había un cacho pequeño de código con un bug. Lo mencionó en la conversación pero no lo corrigió.

Cuando lo uso cómo referencia @refine-english.md for @mydoc.md

  • Se pasa un tiempo al inicio intentando interpretar que es lo que se está pidiendo.
  • Varias veces que lo probé tuvo problemas aplicando parches. ¿Quizá sea porqué estaba en modo "Auto" y no escogió el modelo adecuado para la tarea?
  • Directamente tradujo los textos a inglés en todas las ocasiones, y en alguna corrigió por su cuenta los errores en el código.
  • Usa un 1% de contexto más (acorde al indicador del chat de cursor)

Cuando lo uso cómo: please do the tasks followed by @refine-english.md in document @mydoc.md

  • El resultado se parece más al uso del comando y el % de contexto usado es similar.
  • Cómo en la referencia decide por su cuenta traducir los textos en español
  • Sin problemas aplicando los parches.

Las pruebas anteriores era con el modelo en Auto. Al pasarlo a Sonnet 4.6

  • Las tres formas de usarlo traducen el texto a inglés.
  • El contexto es similar pero un 4% superior a usarlo en modo Auto.
  • Sin problemas aplicando los parches.
  • Es difícil de determinar pero el modo comando parece seguir mejor las instrucciones, sobre todo en el formato de salida.
  • En ninguno de los casos mencionó el bug en el código

Conclusiones

En Cursor usar un comando (parece que) frente a referenciar un documento:

  • Activa cierta lógica interna que consume menos tokens y sigue mejor las instrucciones.
  • En modo Auto selecciona modelos distintos que con la referencia.
  • No he notado mucha diferencia entre usar @mydoc.md y 'mydoc.md'.
  • Influye más el modelo que usarlo cómo comando o cómo @

Este es uno de los mejores comentaros que he encontrado sobre cómo funcionan estas herramientas:

Alexandros alexandrosandre, en el foro de Cursor

To my understanding you aren't missing anything. What helps myself get through this caos is the following simplified rationale "It is all a lie. Everything is just another prompt." Therefore your usage might not be standard or documented but can work just as fine.

Not trying to be disrespectful at all with the "lie" here. Product is trying to name and build use cases and follow standards the best they can. And it’s tough.

It just helps me understand that all we are doing is telling LLMs what to do in a prompt or where to find the longer instructions (aka prompt) to avoid filling up the context. The rest on top is a essentially looping/harnessing/if-this-then-that nothing else.

Teniendo en cuenta cómo funcionan las skills, los comandos son más bien innecesarios.

Coding Agentes: Funcionalidades de "inyección de contexto"

Serie de artículos sobre funcionalidades para inyectar contexto en los coding agents:
  1. Funcionalidades de "inyección de contexto"
  2. Commands en Cursor
  3. Commands en Gemini
  4. Commands en Claude (Codex y OpenCode)
  5. Cómo funcionan las rules en distintos Coding Agentes
  6. Cómo funcionan las Agent Skills

Los coding agents ofrecen varias funcionalidades para lo que podemos llamar inyectar contexto explicita o implicitamente:

  • prompt: Ya sea user prompt, system prompt, ...
  • referencias: En el prompt también podemos pedir a la herramienta que incluya el contenido de un fichero con @ o con instrucciones.
    • Los modelos y las herramientas son complejos. No se comportan todas igual, ni el mismo modelo hace siempre lo mismo. Tampoco es lo mismo referencia una imagen binaria que se suele hacer en peticiones distintas que un md.
    • La forma en que la herramienta marca o incluye este contexto adicional también puede variar.
    • El concepto de memory banks encaja aquí y en AGENTS.md
  • AGENTS.md: Siempre introduce en el contexto el fichero en la raíz del repo. Algunas herramientas admiten ficheros en subdirectorios y los adjuntan cuando se accede a un fichero en ese directorio. Puede actuar cómo un índice que adjunte otros documentos:
    • Con @. Debería leerlo e incluirlo siempre.
    • Condicionalmente mediante instrucciones read 'testing.md' when writing tests
  • commands: Escribimos en el chat /fix-bug in my_file.py, y envía al modelo fix-bug.md que está en una ruta predeterminada junto al resto del contexto.
  • rules: No todas las herramientas las tienen. Suelen ser ficheros md con un frontmatter que indica cuando se debe usar la regla. Es la herramienta y el modelo quien decide que reglas leer, pero el usuario puede forzarlo.
  • hooks: Las incluyo porqué son un buen substituto a ciertas instrucciones (estén donde estén). En lugar de `execute format.sh and lint.sh after making changes", un hook puede correrlos. De hecho las instrucciones pueden ser ignoradas y el hook no.
  • MCP
  • Skills. Un directorio, en una ruta predefinida de la herramienta, que tiene dentro un fichero SKILL.md y otros assets. Tienen metadatos cortos de nombre y descripción que se inyectan siempre en el contexto. El LLM decide cuando una skill aplica en base a los metadatos o el usuario puede forzar su uso.
    • Hay un par de cosas que no me gustan de los skill. O que si se retocara la spec podrían ser un total substituto a los comandos. Los comandos se cargan y ejecutan exclusivamente bajo demanda del usuario. Las skills no.
    • La spec dice que los metadatos se cargan siempre.
    • El LLM decide cuando cuando leer y aplicar la skill en base a la vaga descripción
    • No se pueden tener "infinitas" skills. Para que el LLM no se lie decidiendo, y para no consumir contexto. A pongamos 50-100 tokens por skill, 20-40 skills es un 1% del contexto habitual de 200k.
  • Extensiones o Plugins. Depende de la herramienta, pero la mayoría incluye alguna forma de empaquetar combinaciones de lo anterior y otras extensiones de comportamiento.

En próximos artículos iremos viendo con más detalle algunas de estas funcionalidades, cómo se comportan en distintas herramientas y cómo se relacionan entre sí.

Lint y Format para Markdown (rumdl)

Después del post anterior gracias a Antón descubro una nueva herramienta

rumdl

rumdl es un formatter y linter de Markdown escrito en Rust siguiendo las ideas de ruff.

El primer commit es de Febrero de 2025, así que es un proyecto muy reciente con unas 800 estrellas en este momento. Parecen pocas pero para una herramienta que sigue siendo de nicho no está mal. Markdownlint tiene 2k y mdformat 600. Además ha sido adoptado por proyectos como lucene, ULauncher o pyo3.

No usaría este proyecto si fuera una dependencia core porqué para mi tiene varios red flags:

  • El proyecto tiene apenas un año y muchas features. Tiene pinta de haber mucho LLM y eso necesita mucha destreza para que el mantenimiento no se complique.
  • Tiene 25 contributors, pero el 98% de los commits son de la misma persona.
  • El README (que es gigante) está desincronizado con la documentación. Y la web no está enlazada desde el repositorio.

La herramienta promete mucho y, cumple más requisitos que las herramientas analizados en el anterior post:

  • Escrito en rust, es un binario instalable por todos los métodos habituales: uv, npm, curl, ...
  • Paridad de reglas con Markdownlint (con algunas extra) y opción para importar la configuración
  • Formatter y Linter en la misma herramienta, en un estilo muy ruff, parámetros parecidos en la CLI, el formato de configuración, ... lo que se agradece.
  • Soporta por defecto varios formatos de Markdown
  • Plugins para los editores habituales (LSP en el propio binario) e integración con pre-commit y sistemas varios de CI

Pero, a poco que la he probado hay muchos detalles que no encajan bien con mi forma de trabajo:

  • Es muy agresiva en los auto-fix
  • La configuración de las reglas se vuelve complicada. Por ejemplo hay varios bugs en torno a la regla blanks-around-headings y después de varias pruebas no he conseguido que simplemente me elimine todas las líneas en blanco antes el H1 que prettier hace sin problemas.

Conclusiones

rumld es una herramienta con potencial. Merece la pena probarla y ver si encaja, pero en mi caso, esperaré un par de meses antes de volver a probarla.

Herramientas de Lint y Format para Markdown

Note

No te pierdas la continuación de este artículo hablando de la herramienta rumdl

Llevo bastante tiempo usando markdownlint-cli2 y prettier para linting y formatting de Markdown, pero no tenía un análisis de las herramientas disponibles, para ver si había mejores opciones.

Requisitos Deseables

  • Integración con el IDE. Una buena extensión para VSCode y derivados
  • Integración con pre-commit (oficial en el repo, no sólo ejecución local)
  • Una sola herramienta mejor que varias herramientas. En todo caso el linter y el formatter deben ser compatibles.
  • Bien mantenida, popular, ...
  • Rápida
  • Rust > Python > Javascript
  • Prefiero herramientas en lenguajes que generan binarios como Rust porqué son más fáciles de instalar y mantener. Luego en Python porqué conozco mejor el ecosistema
  • Formato:
  • Mucho Markdown es para LLMs o producido por LLMs. Así que prefiero un estilo que concuerde.
  • Que se lleve bien con MkDocs, que tiene su propio sabor (python-markdown, y python-markdown-extensions)

Aunque preparando el artículo me entero de que MkDocs está deprecated y Zensical del mismo equipo usará en el futuro (1) CommonMark

  1. 🙏 !Gracias!

Herramientas

mdformat

mdformat es un formatter escrito en Python.

  • Usa markdown-it-py cómo parser.
  • 643 estrellas
  • Soporta CommonMark, GFM, MysT
  • Tiene plugins para soportar casos particulares como Admonitions, formatear código dentro de fenced blocks, ...
  • Opinionated. Pocas opciones de configuración
  • Soporta MkDocs a través de plugin:
  • Aunque hay que probar bien.
  • Plugin no oficial para vscode.
  • Tiene soporte para pre-comit

No me acaba de convencer.

prettier

Prettier es el estándar para formatear en el ecosistema JavaScript.

  • Usa remark-parser como parser
  • 50k estrellas
  • Soporte para CommonMark, GFM y MDXv1
  • Muy buena integración con el IDE
  • Es opinionated. La única opción específica markdown es prose-wrap
  • No hay soporte oficial para pre-commit, ni para prek

Una opción que nunca es mala, aunque puede no ser la mejor.

markdownlint

Bajo este nombre encontramos varias herramientas de lint:

La que nos interesa es markdownlint-cli2.

  • Markdown/CommonMark
  • pre-commit, github action, extensión para vscode.
  • Distintos formatos de salida (xml, json, consola, con colores, ...)
  • La configuración es algo confusa, pero los ficheros .markdownlint-cli2.* permiten configurar tanto la CLI, cómo la extensión para code, cómo la librería
  • El linter usa por debajo el parse markdown-it.

Un artículo sobre la herramienta.

A pesar de las confusiones de nombres, y la documentación dispersa no es una mala opción.

remark

Remark no es una herramienta si no un ecosistema en torno a Markdown que a su vez forma forma parte de unifiedjs.

Por defecto trabaja con ConmmonMark pero tiene plugins para otras versiones.

Es muy configurable, tanto, que entender bien cómo funciona, escoger los plugins y configurar las opciones adecuadas se vuelve complicado.

Sin soporte oficial para pre-commit.

La extensión de remark-lint para vscode que aparece en el README no se actualiza desde 2018. Hay otra extensión que parece oficial que en el momento de escribir esto lleva más de año y medio (Abril/2024) sin actualizarse.

  • remark-parse es la librería que convierte markdown a AST. Es usada también por prettier.
  • remark-stringify. Es la librería que se encarga de convertir el AST a Markdown. Cuando formateamos Markdown remark-parse lo convierte a AST, y remark-stringify lo convierte de nuevo a Markdown. Las reglas que queremos para el formatter son las que admita esta librería más plugins.
  • remark-lint. Es un monorepo que contiene la librería básica de linting y un montón de reglas que están por separadas o en conjuntos llamados "presets". Pero no es una herramienta, el uso de la librería es a través de remark-cli. Cuando instalamos un preset el paquete base remark-lint va cómo dependencia. Los presets más habituales:
  • remark-preset-lint-consistent — rules that enforce consistency
  • remark-preset-lint-markdown-style-guide — rules that enforce the markdown style guide
  • remark-preset-lint-recommended — rules that prevent mistakes or stuff that fails across vendors.
  • remark-cli, es la herramienta de línea de comandos para llevar a cabo operaciones.
  • plugins para casi todo lo que podamos imaginar. Otras versiones de markdown cómo remark-gfm, manipulaciones cómo remark-toc, linting cómo remark-lint, ...
Un ejemplo de instalación y uso
# Instalar la línea de comandos genérica
npm install --save-dev remark-cli

# Instalar plugins cómo remark-toc o un conjunto de reglas
npm install --save-dev remark-preset-lint-markdown-style-guide remark-toc

# Format de un fichero
remark --output readme.md

# Format de un fichero añadiendo el TOC
remark --output --use remark-toc readme.md

# Lint de todos los ficheros acorde a remark-preset-lint-markdown-style-guide
remark --use remark-preset-lint-markdown-style-guide .

# Format de todos los ficheros markdown en el directorio actual
remark . --output

# Lint de todos los ficheros markdown en el directorio actual
remark .
Un ejemplo de configuración
// .remarkrc.yaml
plugins:
  # Check that markdown is consistent.
  - remark-preset-lint-consistent
  # Few recommended rules.
  - remark-preset-lint-recommended
  # Generate a table of contents in `## Contents`
  - - remark-toc
    - heading: contents
settings:
  bullet: "*"
  emphasis: "_"
  strong: "*"

Herramientas Descartadas

Biome

Biome es la alternativa a prettier y eslint escrita en rust, pero todavía no implementa todas las reglas ni todos los lenguajes que soporta prettier. No soporta Markdown por ahora.

PyMarkdown

PyMarkdown es un linter escrito en Python que cumple pocos de los requisitos.

  • Usan su propio parser.
  • 109 estrellas
  • Soporta CommonMark y GFM
  • Tiene soporte para pre-commit
  • No parece tener extensión para vscode, ni ningún otro IDE
  • Tienen muchas opciones y reglas y es muy configurable
dprint

dprint no es un proyecto al que le hubiera prestado mucha atención si no fuera porqué lo usan Deno y Helix.

Es un "framework" para formatting escrito en Rust que soporta muchos lenguajes a través de plugins, entre ellos Markdown. Por ejemplo tienen un plugin para ruff para formatear Python.

Para markdown usa un parser centrado en CommonMark con soporte parcial para GFM. Las reglas de formato son poco configurables. Parece tener integración con pre-commit (no oficial) y vscode, pero no muy mantenida:

Bugs a los que prestar atención:

Otras referencias

Conclusiones

Prettier y Markdownlint son las mejores opciones en este momento. Habrá que estar atentos a la evolución de otras herramientas cómo dprint, biome u Oxc, y también a lo que salga de Zensical.

Si manipular el Markdown mediante línea de comandos también es de interés remark es una opción a estudiar.