standup-mr
Notas de standup a partir do estado de merge requests do GitLab ou GitHub, com as linhas de erro do log de job de um pipeline com falha.
Documentação
standup-mr
Notas de standup baseadas no estado dos merge requests, não nos logs de commit.
A maioria das ferramentas de standup lê seu git log local. Isso responde "o que eu digitei",
que não é o que alguém pergunta em um standup. Esta lê GitLab ou GitHub:
o que está pronto para merge, o que está bloqueado, o que está esperando por você — e quando um
pipeline está vermelho, ela abre o log do job e diz por quê.
O que a torna diferente
| ferramentas de log de commit | standup-mr | |
|---|---|---|
| Fonte | git log local | API do GitLab ou GitHub |
| Estado do merge request | ✗ | pronto / bloqueado / rascunho / obsoleto |
| Fila de revisão | ✗ | apenas pendentes, aprovações filtradas |
| Pipeline com falha | ✗ | linhas de erro do trace do job ou do log do job do Actions |
| Self-hosted (GitLab CE/EE, GitHub Enterprise) | varia | primeira classe |
Uso
npx standup-mr fetch # JSON, provider auto-detected
npx standup-mr fetch --provider github # GitHub
npx standup-mr fetch --provider gitlab # GitLab
npx standup-mr fetch --markdown # structured digest
npx standup-mr fetch --lang tr # Turkish date labels
npx standup-mr fetch --markdown | npx standup-mr post --google-chat "$URL"
Identidade
| GitHub | GitLab | |
|---|---|---|
| Flags | --host / --token | --host / --token |
| Env | GITHUB_HOST / GITHUB_TOKEN | GITLAB_HOST / GITLAB_TOKEN |
| Sessão CLI | gh config de auth | glab config de auth |
O GitHub usa github.com por padrão quando nenhum host é informado. O GitLab não tem padrão —
self-hosted é a norma lá, então um host deve vir de uma flag, variável de ambiente, ou
da própria config do glab.
O provedor em si é escolhido nesta ordem:
--provider github/--provider gitlab, se passados- um
--hostreconhecível (github.com,gitlab.com, ou um hostname contendogithub/gitlab) STANDUP_PROVIDER, ou qualquer um dos pares de envGITHUB_*/GITLAB_*que estiver definido- qualquer um de
gh/glabque estiver logado
Se nenhum desses resolver — ou ambos resolverem, de forma ambígua — o comando falha com um erro claro em vez de adivinhar.
Então, se você já usa gh ou glab, não há nada para configurar.
Publicar no chat
npx standup-mr fetch --markdown | npx standup-mr post --slack "$SLACK_WEBHOOK_URL"
As três superfícies
CLI — o núcleo. Emite JSON; zero dependências de runtime.
Servidor MCP (mcp/) — uma ferramenta, get_standup_data, para Claude Desktop,
Cursor, ou qualquer cliente MCP. Veja mcp/README.md.
Plugin Claude Code — o playbook de escrita de notas, enviado como a skill standup.
De dentro do Claude Code:
/plugin marketplace add Jubstaaa/standup-mr
/plugin install standup@standup-mr
Depois digite /standup. As atualizações vêm com /plugin marketplace update standup-mr.
Usando no Cursor, Codex, ou outro assistente
Se você não está usando Claude Code, configure o servidor MCP para dados ao vivo e cole as regras de escrita de notas separadamente.
Cursor — adicione em ~/.cursor/mcp.json (global) ou .cursor/mcp.json
(específico do projeto):
{
"mcpServers": {
"standup": {
"command": "npx",
"args": ["-y", "standup-mr", "mcp"],
"env": {
"GITHUB_TOKEN": "ghp_..."
}
}
}
}
Codex — adicione em ~/.codex/config.toml:
[mcp_servers.standup]
command = "npx"
args = ["-y", "standup-mr", "mcp"]
[mcp_servers.standup.env]
GITHUB_TOKEN = "ghp_..."
A chave de configuração exata e o caminho do arquivo dependem da versão para ambos os clientes — se um trecho acima não funcionar, verifique os docs de MCP do Cursor ou a documentação de configuração do Codex para o formato atual, em vez de confiar cegamente neste arquivo.
O servidor expõe três ferramentas:
| Ferramenta | O que faz |
|---|---|
get_standup_data | Lê o provedor e retorna o relatório como JSON. Opcionais: provider, host, lang. |
get_note_instructions | Retorna as regras de escrita de notas, para o assistente escrever a nota como a skill faria. |
post_standup_note | Publica uma nota finalizada em um webhook do Slack, Discord ou Google Chat. |
post_standup_note lê a URL do webhook de STANDUP_WEBHOOK_URL e nunca
a recebe como argumento — qualquer pessoa com essa URL pode publicar no canal, então
ela pertence aos tokens, não a um transcript. O formato do payload é inferido
do host da URL; kind só é necessário quando um proxy a esconde.
Três formatos são implementados: slack e google-chat ambos publicam {"text"},
discord publica {"content"}.
Slack e Google Chat não renderizam Markdown padrão, então a nota é reescrita
na saída: **bold** vira *bold* e um cabeçalho ## vira uma linha em negrito.
Código inline, blocos cercados e seus conteúdos são deixados intactos. Discord
fala Markdown nativamente e é enviado sem alterações. Qualquer outra coisa que aceite um corpo no formato Slack —
Mattermost, Rocket.Chat, um endpoint n8n ou Zapier — funciona hoje passando
kind: "slack", ou --slack URL na CLI.
Fora do MCP, as mesmas regras estão disponíveis no stdout:
npx standup-mr instructions >> AGENTS.md
--markdown é um resumo, não uma nota escrita
--markdown organiza o material bruto em seções legíveis. Ele não
agrupa eventos em temas nem diagnostica bloqueios — esse é o trabalho do modelo, e
vive no prompt do cliente MCP ou na skill do Claude Code.
- Sem IA: um resumo estruturado.
- Com IA: uma nota que você pode ler em voz alta.
Como é o resumo
Saída anonimizada de uma execução real de segunda-feira — note que sexta e sábado cada um tem sua própria seção, e que um merge request que o GitLab ainda não avaliou não é chamado de pronto:
# Monday, 31 August — dev
_Structured digest — not a written note._
## Previous working day: Friday, 28 August
- `acme/ui` pushed to — fix(keyboard): scale keys to viewport (4 commits)
- `acme/ui` accepted — chore(deps): bump @acme/ui to 0.5.18
- `acme/api` opened — feat: package subscription sales
## Previous working day: Saturday, 29 August
- `acme/ui` pushed to — fix(keyboard): close the autofill bar (1 commit)
## Ready to merge (2)
- `acme/api` !196 fix: normalise the +90 trunk prefix
- `acme/web` !194 refactor: loading state — **no pipeline ran**
## Blocked (1)
- `acme/terminal` !49 fix: relative date chips — **1 unresolved comment(s)**
## Reviews (2 pending)
- `acme/mobile` !501 chore: upgrade to RN 0.87 — Teammate
## Blockers
- `acme/mobile` !6 — job `quality`
- `npm ERR! code E404`
- `npm ERR! 404 Not Found - GET https://registry.example.com/@acme%2fui`
A última seção é o ponto da ferramenta. Toda outra ferramenta de standup pode te dizer que o pipeline está vermelho; esta abre o log do job com falha e mostra o 404 — e um 404 em vez de um 403 geralmente significa que o escopo do token está errado, não que o pacote está faltando.
Limitações conhecidas
- O feed de eventos do GitHub é raso. Ele é limitado a cerca de 300 eventos nos últimos 90 dias, então uma conta muito ativa ou uma lacuna antiga pode silenciosamente perder os eventos mais antigos. O GitLab não tem um limite documentado comparável.
- A atividade do GitHub só é visível para um token da mesma conta, e eventos de repositórios privados não aparecem para tokens de outras pessoas, mesmo com escopos suficientemente amplos.
- No GitHub, CI que reporta apenas pela API legada de commit-statuses
— ainda como alguns fornecedores integram — aparece como
pipelineMissing. O estado do check é lido apenas de check-runs. - Um bloqueador cujo diagnóstico não pôde ser buscado ainda é reportado, como
job: "unknown"com uma linha de errodiagnosis unavailable: …. O merge request está bloqueado de qualquer forma; apenas a explicação está faltando. Erros de servidor são tentados duas vezes primeiro, e um token rejeitado ainda falha a execução.
Atualizando da 0.1.x
A 0.2.0 muda a saída JSON, a API da biblioteca e as opções do MCP. Se você
canaliza standup fetch para qualquer coisa, ou importa o pacote, leia
CHANGELOG.md antes de atualizar. A versão curta:
previousepreviousEventssão substituídos porpreviousDays[], uma entrada por dia ativo, então um fim de semana não engole mais a sexta-feira.jq .previousagora retornanullsem erro.MergeRequest,RevieweBlockercarregam um campoproviderobrigatório, eProvider.getReviewsrecebe umIdentityem vez de um id numérico.- O
CollectOptions.providerdo MCP agora é um nome de provedor; injete uma instância deProvideratravés deproviderImpl.
Usuários do plugin Claude Code devem executar /plugin marketplace update standup-mr —
a skill standup mudou junto com o formato do relatório.
Requisitos
Node 20 ou mais novo. O núcleo da CLI (fetch, post, instructions) não puxa
dependências de runtime. O servidor MCP (comando mcp) traz uma:
@modelcontextprotocol/sdk.
Licença
MIT