Mata el standup
Lee los issues de Linear y los commits de GitHub del día anterior. Formatea una actualización diaria. Publícala en Slack.
Paso 1: Verificación de configuración
Confirma que las variables de entorno requeridas están configuradas:
echo "LINEAR_API_KEY: ${LINEAR_API_KEY:+set}"
echo "SLACK_WEBHOOK_URL: ${SLACK_WEBHOOK_URL:+set}"
echo "GITHUB_REPO: ${GITHUB_REPO:-no configurado}"
echo "GITHUB_USERNAME: ${GITHUB_USERNAME:-no configurado}"
Si LINEAR_API_KEY falta: Detente. Indica al usuario: "LINEAR_API_KEY es obligatorio. Obténlo en Linear → Configuración → API → Claves API personales. Añádelo a tu archivo .env."
Si SLACK_WEBHOOK_URL falta: Detente. Indica al usuario: "SLACK_WEBHOOK_URL es obligatorio. Crea un Incoming Webhook en api.slack.com/apps → Tu App → Incoming Webhooks. Añádelo a tu archivo .env."
Si GITHUB_REPO falta: Continúa. Los commits de GitHub se omitirán. Notifica esto al usuario.
Paso 2: Obtener actividad de Linear
Calcula la fecha de ayer en formato ISO 8601 (ej. 2026-04-09T00:00:00.000Z).
Obtener el ID del usuario actual:
curl -s -X POST https://api.linear.app/graphql \
-H "Authorization: Bearer $LINEAR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "query { viewer { id name email } }"}'
Extrae el campo id de la respuesta. Almacénalo como LINEAR_USER_ID.
Obtener issues asignados a mí, actualizados desde ayer:
curl -s -X POST https://api.linear.app/graphql \
-H "Authorization: Bearer $LINEAR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "query($since: DateTime!, $userId: ID!) { issues(first: 50, filter: { assignee: { id: { eq: $userId } } updatedAt: { gte: $since } }) { edges { node { identifier title state { name } url completedAt updatedAt createdAt } } } }",
"variables": {"since": "YESTERDAY_ISO", "userId": "LINEAR_USER_ID"}
}'
Categorizar issues:
completedAtno es nulo → Hechostate.namees "In Progress", "Started" o "In Review" → Haciendostate.namees "Cancelled" → omitirstate.namees "Todo" o "Backlog" → omitir (no trabajado)
Si ningún issue: anota "No se encontró actividad en Linear ayer."
Paso 3: Obtener commits de GitHub
Omite este paso silenciosamente si GITHUB_REPO no está configurado.
Si GITHUB_REPO está configurado:
gh api "repos/$GITHUB_REPO/commits?author=${GITHUB_USERNAME:-$(gh api user --jq .login)}&since=YESTERDAY_ISO&per_page=30" \
--jq '[.[] | {message: .commit.message, url: .html_url}]'
Procesar commits:
- Extrae la primera línea de cada mensaje de commit (todo antes del primer salto de línea)
- Omite commits de fusión (merge): descarta cualquier mensaje que comience con "Merge"
- Desduplica por texto del mensaje
Si GITHUB_REPO está configurado pero devuelve cero commits: anota "No se encontraron commits ayer."
Paso 4: Formatear standup
Lee el contenido completo de references/standup-format.md antes de escribir.
Produce el standup con esta estructura exacta:
**Hecho**
- [ENG-123] Título del issue completado
- fix: mensaje del commit aquí
**Haciendo**
- [ENG-124] Título del issue en progreso
**Bloqueos**
Sin bloqueos.
Reglas de standup-format.md:
- Sin pronombres en primera persona ("yo", "nosotros")
- Tiempo pasado para elementos Hecho, presente continuo para elementos Haciendo
- Cada elemento de Linear usa el formato
[IDENTIFICADOR] Título - Cada commit de GitHub usa la primera línea del mensaje del commit
- Si no hay elementos Hecho: escribe "Nada completado." bajo Hecho
- Si no hay elementos Haciendo: escribe "Nada en progreso." bajo Haciendo
- Si no hay bloqueos: escribe "Sin bloqueos."
- Menos de 200 palabras en total
Paso 5: Publicar en Slack o mostrar
Presenta el standup formateado al usuario.
Pregunta: "¿Publicar esto en Slack o solo mostrar?"
Al confirmar publicar:
curl -s -X POST "$SLACK_WEBHOOK_URL" \
-H "Content-Type: application/json" \
-d '{
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Standup — FECHA_AQUÍ*\n\n*Hecho*\nELEMENTOS\n\n*Haciendo*\nELEMENTOS\n\n*Bloqueos*\nELEMENTOS"
}
}
]
}'
Pasa el cuerpo mediante un archivo temporal o una cadena heredada para evitar problemas de escape con caracteres especiales en mensajes de commit o títulos de issues:
cat > /tmp/standup-payload.json << 'ENDJSON'
{
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "CONTENIDO_DEL_STANDUP_AQUÍ"
}
}
]
}
ENDJSON
curl -s -X POST "$SLACK_WEBHOOK_URL" -H "Content-Type: application/json" -d @/tmp/standup-payload.json
Después de publicar: "Standup publicado."
En caso de "solo mostrar": Imprime el standup en un bloque de código para copiar y pegar.