Todos los recursos

Cortar un release de memoria tres días después significa que el changelog nunca cuadra con lo que salió y el salto de versión es una moneda al aire. Este es un skill de Claude Code empaquetado que lee tus commits, propone el salto de semver, escribe un changelog a partir de los títulos reales de los commits, crea el tag y deja listo el release en GitHub. Te muestra la propuesta y espera un sí antes de escribir nada, así un major equivocado nunca sale por accidente.

Release Cutter: un skill de Claude Code que lee git en vez de adivinar

En resumen

  • Un skill de release convierte todo el checklist de publicación (bump, changelog, tag, notas) en una sola invocación que lee de git, no de tu memoria.
  • Se dispara cuando main está en verde y dices 'corta un release'. No en cada commit ni a mitad de una feature.
  • El salto de semver sale de los prefijos de conventional commits: feat es minor, fix es patch, un footer de breaking change es major.
  • La regla que lo vuelve seguro: frena y pregunta en vez de adivinar. Un major equivocado sale caro de revertir una vez que hiciste push.
  • No reemplaza tu criterio. Te quita el tecleo y las desviaciones. La versión la sigues aprobando tú.

Corta un release de memoria tres días después y siempre fallan dos cosas: el changelog nunca termina de cuadrar con lo que salió, y el salto de versión es una moneda al aire. El trabajo en sí es un checklist que a nadie le gusta: elegir la próxima versión, escribir el changelog, subir la versión en el manifest, crear el tag, hacer push, redactar las notas. Esta guía recorre cómo armar todo ese checklist como un solo skill de Claude Code. Qué hace, en qué momento exacto debe dispararse, cómo funciona por dentro, una invocación real con el output que esperarías, los parámetros de configuración y los detalles que separan un skill útil de uno peligroso. Al final vas a tener un release-cutter en el que confías lo suficiente como para correrlo sobre main, con las barreras que evitan que algún día publique un major equivocado.

Para quien no lo conozca, un skill no es más que un conjunto empaquetado de instrucciones que Claude Code carga cuando hace falta. Un archivo Markdown pequeño con un nombre, una descripción que controla cuándo se dispara y un cuerpo que le dice al agente qué hacer. El release-cutter es un candidato casi perfecto porque la tarea es lo bastante determinista como para automatizarla, pero lo bastante engorrosa como para que los humanos la hagan mal. El truco está en escribirlo de modo que lea la verdad desde git en vez de inventarse un cuento.

01 · Qué hace

El release-cutter junta toda la secuencia de publicación en una sola invocación. Cuando lo corres hace cinco cosas en orden, y las hace con evidencia, no de memoria:

  1. Encuentra el último tag de release y lee cada commit desde ahí.
  2. Agrupa esos commits por prefijo de conventional commits y propone la próxima versión semántica.
  3. Escribe una entrada de changelog (Añadido / Corregido / Cambiado) generada a partir de los títulos reales de los commits.
  4. Sube la versión en el manifest (package.json, Cargo.toml, pyproject.toml, lo que use el repo).
  5. Hace commit del bump, crea un tag anotado y deja listo el release en GitHub con la CLI gh.

La ganancia no es la velocidad, aunque sí termina siendo más rápido. La ganancia es que el changelog por fin cuadra con la realidad, porque sale de los commits y no de un recuerdo borroso de cómo fue la semana. El salto de versión deja de ser una corazonada. Y los pasos aburridos (editar el manifest, crear el tag, dejar el draft) dejan de ser el lugar donde un humano cansado teclea mal v.1.2.0 o se le olvida hacer push del tag.

Nota

Un skill de release no es un pipeline de CI. CI corre solo, disparado por un evento. Este skill corre cuando se lo pides, te muestra su propuesta y espera un sí. Ese checkpoint humano es el punto, no una feature que falta.

02 · Cuándo debe dispararse

La disciplina del trigger es lo que separa un skill que conservas de uno que borras en una semana. Un release-cutter debe dispararse en una sola situación: main está en verde y decidiste publicar. No debe dispararse en cada commit, ni a mitad de una feature, y muchísimo menos en un branch con trabajo sin fusionar.

La línea de descripción en el frontmatter del skill es contra lo que Claude Code compara para decidir si lo carga, así que escríbela específica, no ansiosa:

---
name: release-cutter
description: >
  Cut a release from main: read commits since the last tag, propose a
  semver bump, write the changelog, bump the manifest, tag, and draft
  the GitHub release. Use when the user says "cut a release", "ship it",
  or "tag a version" AND the working tree is clean on the default branch.
---

Fíjate en la cláusula "AND". Una descripción vaga ("gestiona versiones y releases") hace que el skill se cargue en los momentos equivocados y va minando la confianza. Una específica amarra la activación a una intención explícita del usuario más una precondición que el agente sí puede verificar. Antes de hacer cualquier cosa destructiva, el skill mismo debe verificar la precondición: working tree limpio, en el branch por defecto y el local sincronizado con el remoto.

Atención

Nunca dejes que el skill corte un release con el working tree sucio o desde un feature branch. Que corra primero git status --porcelain y git rev-parse --abbrev-ref HEAD, y que aborte con un mensaje claro si cualquiera de los dos chequeos falla. Un release armado sobre cambios sin subir al repo no se puede reproducir.

03 · Cómo funciona por dentro

Aquí no hay magia. El skill es una secuencia de comandos de shell que el agente corre y sobre los que razona. Recorrer el flujo deja claras las decisiones de diseño.

Leer el historial

Arranca por encontrar la línea base. El último tag es el piso; todo lo que vino después es el release:

# Línea base: el tag más reciente alcanzable desde HEAD
LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")

# Asuntos de los commits desde ese tag (o todos si aún no hay ninguno)
if [ -z "$LAST_TAG" ]; then
  git log --pretty=format:"%s" --no-merges
else
  git log "$LAST_TAG"..HEAD --pretty=format:"%s" --no-merges
fi

El flag --no-merges importa: los commits de merge meten ruido sin describir ningún cambio. El agente lee esos títulos y los ordena por prefijo.

Inferir el salto

Esta es la única parte que necesita un modelo y no un script, y aun así la regla es simple. Siguiendo semver y conventional commits:

  • Un commit con footer BREAKING CHANGE, o un prefijo con ! (como feat!), implica un salto major.
  • Cualquier feat implica al menos un salto minor.
  • Si no, cualquier fix implica un salto patch.
  • Gana el nivel más alto que aparezca. Un solo breaking change en medio de un mar de fixes sigue siendo un major.

El agente no aplica la regla a ciegas: enseña su razonamiento. Lista qué commits motivaron la decisión para que puedas revisar el porqué antes de que el tag exista.

Dejarlo escrito y publicar

Una vez acordada la versión, corren los pasos mecánicos: editar el manifest, anteponer una sección con fecha al changelog, hacer commit con un mensaje convencional, crear un tag anotado y dejar listo (sin publicar) el release:

git commit -am "chore(release): v$NEXT_VERSION"
git tag -a "v$NEXT_VERSION" -m "Release v$NEXT_VERSION"
gh release create "v$NEXT_VERSION" --draft --notes-file CHANGELOG_ENTRY.md

Dejarlo en draft y no publicarlo es a propósito: te da una última lectura humana de las notas ya renderizadas antes de que el mundo las vea. Pasar un draft a público es un clic; despublicar un release malo es un lío.

04 · Una invocación concreta

Así se ve correrlo en la práctica, en un repo con un puñado de commits desde el último tag.

Tú escribes:

> cut a release

El skill chequea las precondiciones, lee el log y vuelve con una propuesta en vez de un hecho consumado:

Último tag: v1.4.2  •  branch: main (limpio, sincronizado)
12 commits desde el último release.

Salto propuesto: 1.4.2 → 1.5.0  (MINOR)
Razón: 3 commits feat, 0 breaking changes, 5 fixes.

Vista previa del CHANGELOG
──────────────────────────
## v1.5.0 — 2026-05-23

### Añadido
- feat: scopes de token por proyecto en el gestor de secretos
- feat: flag de dry-run para el runner de migraciones
- feat: salida JSON estructurada del comando de auditoría

### Corregido
- fix: race cuando dos agentes refrescan el mismo lease
- fix: las fechas del changelog salían en el timezone equivocado
  (+3 más)

¿Aplico este salto, escribo el changelog, etiqueto v1.5.0 y preparo el
release en GitHub? [y / elige otra versión / aborta]

Respondes y, ejecuta las escrituras e imprime la URL del draft del release. Ese checkpoint, primero la propuesta y después la acción, es justo lo que hace seguro apuntarlo a main. En un proyecto como Infuse, el gestor de secretos, esa pausa no es negociable: quiero leer exactamente qué cambios de la API se van a anunciar antes de que un tag congele la versión para siempre.

Consejo

Que el skill imprima la URL del draft de gh al final y se detenga ahí. Revisar la página del release ya renderizada en el navegador te salva de ese Markdown que se veía bien en la terminal pero se rompe cuando GitHub lo renderiza.

05 · Configuración y detalles que muerden

Casi todos los repos piden algo de ajuste. Mantén la configuración en el cuerpo del skill para que quede versionada junto al repo, no enterrada en la cabeza de alguien.

Los parámetros que vale la pena exponer:

  • Ruta del manifest y clave de versión. La "version" de package.json, o la versión bajo [project] en pyproject.toml. Decláralo de forma explícita; no hagas que el agente adivine en un monorepo.
  • Archivo y formato del changelog. Estilo Keep a Changelog, o tus propios encabezados. Fija el orden de las secciones para que el output sea estable.
  • Nombre del branch por defecto. main en la mayoría, pero dilo; algunos repos todavía usan master o un branch release.
  • Manejo de prereleases. Si se permite 1.5.0-rc.1 y cómo se incrementa el sufijo.

Y los detalles que muerden en producción:

El salto vale lo que valgan tus mensajes de commit. Si la mitad del historial es "wip" y "arregla cosas", el skill no puede inferir la intención, y no debe hacer como que sí. Lo correcto es frenar y preguntar, no adivinar un patch en silencio. Un major equivocado al que ya subiste es de verdad molesto de revertir, porque los tags se quedan pegados y río abajo alguien ya pudo haberse fijado a él.

Segundo: los tags no son reversibles en espíritu aunque de hecho se puedan borrar. Una vez que un tag es público y alguien ya lo trajo con fetch, re-apuntarlo rompe el contrato implícito. Trata el paso del tag como el punto de no retorno y pon el checkpoint humano justo antes.

Tercero: no dejes que el skill haga push del tag y publique el release en el mismo aliento en que hace el commit. Separa el "draft" del "publish" para que siempre tengas una ventana para abortar sin más que un commit local por deshacer.

Un skill así es el ejemplo más limpio del principio que hay detrás de todo buen skill de Claude Code: automatiza la rutina determinista, saca a la superficie la única decisión de verdad, y niégate a adivinar cuando los inputs son basura. El release-cutter no te vuelve mejor release manager. Solo evita que las partes aburridas sean donde pasan los errores, y te hace la única pregunta que de verdad necesita un humano. Constrúyelo una vez, ajústale bien el trigger, y nunca más vuelves a teclear un changelog de memoria.

Puntos clave

  • Arma todo el checklist de publicación como un solo skill que lee de git (bump, changelog, tag, draft) para que el changelog cuadre con lo que de verdad salió.
  • Acota bien el trigger: tree limpio, branch por defecto e intención explícita de 'cortar un release'. Con una descripción vaga es como un skill pierde tu confianza.
  • Infiere el salto desde los prefijos de conventional commits, pero siempre muestra qué commits lo motivaron y frena a preguntar cuando el historial está demasiado ruidoso para leerlo.
  • Déjalo en borrador, nunca auto-publiques, y trata el paso del tag como el punto de no retorno humano. Despublicar un release malo es mucho peor que aprobar un borrador.
  • El skill te quita la rutina y las desviaciones, no el criterio. La versión la sigues aprobando tú; solo evita que las partes aburridas sean donde viven los errores.

Preguntas frecuentes

¿Por qué un skill de Claude Code y no un pipeline de CI como semantic-release?

Usa los dos, para trabajos distintos. semantic-release encaja cuando los releases están totalmente automatizados al integrar a main y tu disciplina de commits es impecable. Un skill encaja cuando quieres supervisión humana, leyendo el salto y el changelog propuestos y aprobándolos antes de que se cree ningún tag. Si tus mensajes de commit son inconsistentes, el checkpoint humano que te da un skill es justo lo que evita que se publique un major equivocado sin que nadie lo revise.

¿Qué pasa si mi historial no usa conventional commits?

El skill pierde la capacidad de inferir el salto automáticamente, y lo correcto es que lo diga y te pregunte. Dile de forma explícita que frene y te pida una versión en vez de caer por defecto en un patch. Igual puedes sacar un buen borrador de changelog a partir de los títulos crudos. Solo que no te va a proponer la versión. Adoptar conventional commits de aquí en adelante deja bastante más limpio cada release a futuro.

¿Puede publicar el release automáticamente en vez de dejarlo en borrador?

Puede, pero para un skill que invocas a mano, no lo hagas. Dejarlo en borrador mantiene una ventana en la que lo único confirmado es un cambio local que puedes deshacer sin consecuencias públicas. Pasar un draft a publicado es un clic, una vez que le echaste el ojo a las notas renderizadas. La asimetría importa: publicar un release malo y luego despublicarlo es mucho más enredado que aprobar un borrador limpio.

¿Cómo maneja monorepos con varios paquetes?

Por defecto asume una sola versión para todo el repo. Para un monorepo, acota el skill a un paquete a la vez: pásale de forma explícita el directorio del paquete y la ruta de su manifest, y que lea solo los commits que tocaron esa ruta con git log -- <ruta>. Querer subir todos los paquetes en una sola invocación es justo donde la lógica se vuelve frágil; un paquete por corrida mantiene la propuesta auditable.

¿Es seguro apuntarlo al branch main?

Sí, con dos barreras. Primero, el skill debe verificar que el working tree esté limpio y que estés en el branch por defecto antes de hacer nada, y abortar si no. Segundo, el checkpoint de propuesta y aprobación significa que no se escribe nada hasta que digas que sí. Con eso puesto, apuntarlo a main es el uso previsto. La versión peligrosa es la que actúa antes de mostrarte qué va a hacer.

¿Y si no estoy de acuerdo con la versión propuesta?

La cambias. La invocación siempre debe ofrecer 'elige otra versión' como respuesta, y el skill toma tu número, regenera el encabezado del changelog con ese valor y sigue. La inferencia es un valor por defecto, no un veredicto. A veces sabes que un fix en realidad cambia el comportamiento para los usuarios y amerita un minor, y el humano es el lugar indicado para tomar esa decisión.

¿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