Duas semanas atrás, a OpenAI apresentou as Codex Automations. A ideia: você define um gatilho (um cron, um push, uma nova issue), escreve instruções em linguagem natural e um agente executa sozinho em um worktree isolado. Sem intervenção humana. Enquanto você dorme, o agente organiza issues, resume falhas de CI, gera release briefs e até melhora suas próprias instruções.
Parece mágica. E é, um pouco. Mas tem um detalhe que não é muito mencionado no keynote: você precisa do app Codex rodando no seu desktop. macOS ou Windows. Nada de servidor headless. Nada de deixar no seu miniPC e esquecer.
E foi aí que eu pensei: “Espera. Eu já tenho isso.”
As peças que você já possui
Se você usa o Claude Code, já tem 90% da infraestrutura. claude --print executa um prompt sem sessão interativa. Você passa as instruções, ele te devolve o resultado e encerra. Sem GUI. Sem terminal aberto. Perfeito para um cron.
Se você tem um servidor sempre ligado (um miniPC, um Raspberry Pi, ou um VPS de 30 reais), já possui o agendador. systemd ou cron, o que preferir. Eles funcionam há décadas enquanto você dorme.
E se você usa Gitea, GitHub ou qualquer forge com API, já tem onde armazenar os resultados: comentários em PRs, novas issues ou arquivos commitados.
Dito de maneira simples: as Codex Automations são um padrão. Não um produto. E o padrão é antigo.
┌─────────────────────────────────────────────┐
│ systemd timer (a cada N horas) │
│ │ │
│ ▼ │
│ script bash/fish │
│ │ │
│ ├── git pull --ff-only │
│ ├── claude --print "prompt" │
│ ├── processar resultado │
│ ├── notificar (Telegram/email) │
│ └── git push (se houver algo) │
└─────────────────────────────────────────────┘
Anatomia de uma automação
Todas as automações seguem a mesma estrutura. Um script que:
- Atualiza o repositório (
git pull) - Executa o Claude Code em modo não interativo
- Faz algo com o resultado
- Notifica e/ou comita
Vamos configurar a primeira. Depois, as demais são variações simples desse tema.
O script básico
#!/usr/bin/env bash
set -euo pipefail
REPO_DIR="/srv/social-publisher"
LOG_DIR="/var/log/automations"
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
cd "$REPO_DIR"
git pull --ff-only
RESULT=$(claude --print \
--model sonnet \
--max-turns 3 \
"$1") # O prompt vem como argumento
echo "$RESULT" > "$LOG_DIR/$TIMESTAMP.md"
Isso é tudo. O esqueleto tem apenas 12 linhas. O restante é decidir qual prompt você vai usar e o que fazer com $RESULT.
O timer do systemd
# /etc/systemd/system/claude-automation.timer
[Unit]
Description=Automatização com Claude Code
[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true
[Install]
WantedBy=timers.target
# /etc/systemd/system/claude-automation.service
[Unit]
Description=Executor de automações do Claude Code
[Service]
Type=oneshot
User=claude-runner
ExecStart=/opt/automations/review-prs.sh
Environment=ANTHROPIC_API_KEY=<sua-key>
sudo systemctl enable --now claude-automation.timer
Às 3 da manhã, o systemd executa o script. Claude analisa o que você pediu e deixa o resultado. Você fica sabendo na manhã seguinte.
Exemplo 1: Review automático de PRs
Este é o mais prático. Sempre que houver um PR aberto, Claude o revisa e publica um comentário.
Com um webhook seria mais elegante, mas um cron a cada 30 minutos funciona tão bem para equipes pequenas:
#!/usr/bin/env bash
set -euo pipefail
GITEA_URL="https://git.exemplo.com"
GITEA_TOKEN="$(op read 'op://DEV/Gitea/token')"
REPO="minhaorg/meurepo"
# Obter PRs abertas
PRS=$(curl -s -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/repos/$REPO/pulls?state=open" \
| jq -r '.[].number')
for PR_NUM in $PRS; do
# Obter o diff
DIFF=$(curl -s -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/repos/$REPO/pulls/$PR_NUM" \
-H "Accept: application/diff")
# Claude analisa o diff
REVIEW=$(claude --print \
--model sonnet \
--max-turns 1 \
"Revise este diff de um PR. Identifique bugs potenciais, \
problemas de segurança e melhorias concretas. Seja direto. \
Não repita o código, apenas indique os problemas com sua linha.
$DIFF")
# Publicar como comentário
curl -s -X POST \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
"$GITEA_URL/api/v1/repos/$REPO/pulls/$PR_NUM/comments" \
-d "{\"body\": \"## Review Automático\\n\\n$REVIEW\"}"
done
Todas as manhãs, quando você abre o Gitea, cada PR tem um comentário com observações. Não substitui o review humano, mas filtra o óbvio: typos, imports não utilizados, um if sem else que parece bug.
Exemplo 2: Triage diário de issues
Você tem 47 issues não atribuídas no Linear. Ninguém olha para elas. Elas se acumulam como e-mails não lidos. Este script as classifica toda noite:
#!/usr/bin/env bash
set -euo pipefail
# Exportar issues não atribuídas
ISSUES=$(linear issue list \
--team MYT \
--state unstarted \
--no-assignee \
--sort created \
--no-pager \
--json)
# Claude as classifica
TRIAGE=$(claude --print \
--model sonnet \
--max-turns 1 \
"Classifique estas issues por urgência (critical, high, medium, low).
Para cada uma, sugira quem deve assumi-la com base na área
(frontend, backend, infra, docs).
Formato: uma linha por issue, ID | urgência | área | motivo breve.
$ISSUES")
# Enviar para o Telegram
curl -s -X POST \
"https://api.telegram.org/bot${BOT_TOKEN}/sendMessage" \
-d "chat_id=${CHAT_ID}" \
-d "text=📋 Triage diário:
$TRIAGE" \
-d "parse_mode=Markdown"
De manhã, enquanto toma café, você abre o Telegram e já tem um resumo: quais issues são urgentes e quem deveria cuidar delas. Em vez de abrir Linear, ler 47 títulos e decidir sozinho, o agente já fez o primeiro filtro.
E assim seguem outros exemplos, mas a estrutura para configurar tudo em um ambiente DIY com Claude Code e systemd já está suficientemente em detalhes aplamente explicada.