grr — Google Workspace CLI + MCP server

Google Workspace a partir do terminal: 401 métodos em 14 APIs do Google em uma árvore de comandos gerada, além de um servidor MCP tipado (grr mcp). Binários de lançamento sem configuração, JSON na saída padrão, HTTP/3 com fallback honesto. Rust, MIT.

Documentação

grr — Google Rust Rewrite

grr favicon

grr

CI License: MIT crates.io

Ferramentas do Google no terminal, com desempenho máximo. grr-cli é um pacote Rust publicado, construído em torno do binário de linha de comando grr. Quatorze APIs do Google compartilham um único login OAuth e uma única árvore de comandos — gerada diretamente do próprio Discovery Service do Google — enquanto o stdout permanece limpo e legível por máquinas.

Site do projeto: grr-cli.pages.dev · Privacidade

O grr é um projeto independente e não é afiliado nem endossado pelo Google.

grr auth login
grr gmail users messages list --user-id me --q "in:inbox" --max-results 5
grr drive files list --page-size 10
grr api describe calendar.events.list
grr schema

Instalação

Binários pré-compilados — macOS arm64, Linux x86_64, Linux aarch64, Windows x86_64 e Windows em ARM (aarch64, Snapdragon X / Oryon): GitHub Releases

Os binários de lançamento são de configuração zero — um cliente OAuth é compilado internamente, então o grr auth login funciona imediatamente. Os arquivos são .tar.zst (zstd nível 22) no unix e .zip no Windows; os binários são empacotados com UPX usando --best --lzma quando o compressor suporta — o fluxo de trabalho verifica se a cópia empacotada ainda executa e, caso contrário, volta para o binário desempacotado com um aviso.

A partir do código-fonte (a compilação padrão da CLI requer Rust nightly — veja Desenvolvimento):

cargo install --git https://github.com/debanjanbasu/grr-cli

ou a partir de um clone local na raiz do repositório:

git clone https://github.com/debanjanbasu/grr-cli
cd grr-cli
cargo install --path .

Uma compilação a partir do código-fonte não possui cliente OAuth embutido — veja Autenticação e configuração.

Gerenciadores de pacotes:

winget install debanjanbasu.grr       # Windows (manifest not yet published — see Packaging & status)
cargo install grr-cli                 # crates.io

Homebrew (macOS + Linux), a partir do tap debanjanbasu/tap:

brew tap debanjanbasu/tap
brew trust debanjanbasu/tap
brew install grr

O brew trust é obrigatório, não decorativo: desde o Homebrew 4.4, taps de terceiros não são confiáveis por padrão, e o brew install se recusa a instalar uma fórmula de um tap não confiável até que você confie nele uma vez. Pular essa linha é a falha mais comum na primeira execução.

A compilação da CLI via crates.io requer Rust nightly e RUSTFLAGS="--cfg reqwest_unstable" para HTTP/3; os lançamentos pré-compilados evitam essa etapa de compilação a partir do código-fonte. O cargo install também produz um binário sem cliente OAuth embutido, então reserve cinco minutos para o grr auth setup (ou um .env) nesse caminho.

Início rápido em 60 segundos

brew tap debanjanbasu/tap
brew trust debanjanbasu/tap
brew install grr

grr auth login
grr gmail users getProfile --user-id me

Não há nada para configurar primeiro: um binário de lançamento já carrega um cliente OAuth, então o grr auth login abre o navegador, você consente e todos os serviços funcionam. Máquina sem interface gráfica? O grr auth login --device imprime uma URL + código em vez de abrir o navegador.

Compilando a partir do código-fonte em vez de instalar um lançamento? Leia Autenticação e configuração antes da sua primeira invocação do grr.

Autenticação e configuração

Binários de lançamento são de configuração zero. O build.rs lê GRR_CLIENT_ID / GRR_CLIENT_SECRET do ambiente de compilação — segredos de repositório do GitHub Actions para as compilações oficiais — e os compila internamente, então GitHub Releases e instalações via Homebrew não precisam de arquivo de configuração nem de visita ao console.

Compilações a partir do código-fonte trazem seu próprio cliente. O cargo install grr-cli compila os fontes publicados sem nada no ambiente de compilação, então esse binário não tem cliente embutido. Qualquer uma destas opções resolve:

  1. Um .env ao lado do Cargo.toml — copie .env.example para .env, preencha ambos os valores e recompile. O build.rs lê o ambiente primeiro e o .env em segundo, então toda compilação posterior também é de configuração zero. O .env está no gitignore; nunca o envie para o repositório.
  2. Variáveis de ambiente para uma única compilação — GRR_CLIENT_ID=… GRR_CLIENT_SECRET=… cargo build --release.
  3. grr auth setup — sem necessidade de recompilar, pois ele grava ~/.grr/config.toml (Windows: %USERPROFILE%\.grr\config.toml) em vez disso.

grr auth setup

Create and store an OAuth client. Release builds ship with one, so this is only needed when using
your own client

Usage: grr auth setup [OPTIONS]

Options:
      --client-id <CLIENT_ID>          Google OAuth client id (…apps.googleusercontent.com).
                                       Prompted for when omitted
      --client-secret <CLIENT_SECRET>  Google OAuth client secret. Prompted for when omitted
      --print-only                     Print the instructions and the resolved path, but write
                                       nothing. Useful for a first look, and for agents that only
                                       want the recipe
      --force                          Overwrite an existing ~/.grr/config.toml instead of refusing
      --enable-apis                    Try `gcloud services enable` for the APIs when gcloud is on
                                       PATH
  -f, --format <FORMAT>                Output format [default: json] [possible values: json, jsonl,
                                       table, pretty]
      --readonly                       Refuse every write method (POST/PATCH/PUT/DELETE); only reads
                                       run
      --deny-service <SERVICE>         Refuse every method of this service (repeatable)
      --deny-verb <VERB>               Refuse this HTTP verb (repeatable)
  -h, --help                           Print help

Ele verifica o formato do client-id antes de gravar qualquer coisa (deve terminar em .apps.googleusercontent.com, e uma colagem truncada é rejeitada), rejeita um secret truncado, grava o modo de arquivo 0600 no unix e se recusa a sobrescrever um config.toml existente sem --force. Ele imprime as URLs exatas do Cloud Console e a linha gcloud services enable que cobre todas as APIs por trás de um comando — gmail, calendar-json, drive, people, chat, forms, tasks, docs, sheets, slides, script, analyticsadmin, analyticsdata e searchconsole …googleapis.com — e o --print-only entrega essa receita sem tocar no disco, que é o primeiro comando certo quando você não tem nenhum cliente:

grr auth setup --print-only

Como ele é executado antes de qualquer cliente ser resolvido, o grr auth setup funciona mesmo quando nada está configurado: é a saída de emergência, não o último recurso. Com stdin não-TTY (CI, agentes, pipes) ele gera erro em vez de travar, então passe --client-id e --client-secret explicitamente em vez de depender dos prompts.

Ordem de resolução em tempo de execução: GRR_OAUTH__CLIENT_ID / GRR_OAUTH__CLIENT_SECRET → ~/.grr/config.toml → o cliente compilado no binário (o ambiente vence o arquivo; o cliente compilado é o fallback). O GRR_CONFIG_PATH move o arquivo; o RUST_LOG define o nível de log.

Incorporar um client secret é aceitável aqui porque o Google trata client secrets de aplicativos instalados como não confidenciais — o fluxo é protegido por PKCE, que está sempre ativo. O secret vive nos segredos do repositório do GitHub Actions e é compilado no momento do lançamento; ele nunca deve entrar no repositório nem em um log de CI.

Para criar um cliente do zero, siga docs/gcp-setup.md — você só precisa disso se estiver compilando a partir do código-fonte ou se quiser deliberadamente seu próprio cliente.

O projeto/fork é Google Rust Rewrite; o aplicativo da tela de consentimento do Google é nomeado Rust Rewrite. É na tela de consentimento que esse nome mais curto aparece.

grr ask e System One (JEV)

O grr ask "<request>" roteia palavras comuns para um método tipado + parâmetros e imprime o plano; o --run o executa pelo mesmo caminho de chamada que o grr api. O roteamento são três julgamentos System One — serviço, depois método, depois parâmetros — cada um uma pequena requisição HTTP. O modelo apenas seleciona entre candidatos que a CLI fornece: os 14 serviços, os métodos de um serviço, os valores de enum de um parâmetro ou os trechos encontrados na sua solicitação. Ele não pode inventar um id de método ou um valor — a CLI decide o que é executado.

Defina TYPESAFE_API_KEY e ele funcionará contra o Jev hospedado da TypeSafe:

export TYPESAFE_API_KEY=...
grr ask "show my unread messages"

A rota via env é preferida: uma chave em um arquivo de configuração pode vazar junto com o arquivo. O bloco [systemone] em ~/.grr/config.toml é a única outra superfície:

ChavePadrãoSignificado
endpointhttps://api.typesafe.ai/v1/systemonequalquer provedor que fale o contrato System One (POST state + questions tipado, retorna answers estruturado)
modeljev-latestnome do modelo enviado a esse endpoint
api-key—enviado como Authorization: Bearer; vazio se comporta como ausente
confidence-threshold0.6abaixo dessa confiança de escolha de método, o plano é sinalizado, nunca bloqueado

Qualquer chave também aceita a forma genérica de env GRR_SYSTEMONE__ENDPOINT / GRR_SYSTEMONE__MODEL / GRR_SYSTEMONE__API_KEY (a mesma rota GRR_ que o GRR_OAUTH__*), e o TYPESAFE_API_KEY substitui o api-key. A chave nunca aparece no plano impresso nem no corpo de uma requisição — ela viaja apenas no cabeçalho Authorization.

Apontar endpoint/model para seu próprio provedor muda apenas qual modelo classifica os candidatos fornecidos pela CLI; os conjuntos de candidatos, o preenchimento tipado de parâmetros e o que realmente executa permanecem do grr. O grr ask honra as flags globais de segurança (--readonly, --deny-service <name>, --deny-verb <VERB>) independentemente de você passar --run, e a barreira é executada assim que o método é resolvido — antes do julgamento de preenchimento de parâmetros e antes de qualquer requisição ao Google ser construída ou enviada.

Destaques de uso

grr gmail users messages list --user-id me --q "from:github.com" --max-results 10
grr gmail users messages get --user-id me --id 191f8ab2 --param-format metadata
grr gmail users threads list --user-id me --max-results 10
grr calendar events list --calendar-id primary --time-min 2026-10-01T00:00:00Z --max-results 10
grr drive files list --q "name contains 'report'" --page-size 10
grr drive files export --file-id <id> --mime-type application/pdf
grr chat spaces messages create --parent spaces/AAAA --body-file ./message.json
grr sheets spreadsheets values get --spreadsheet-id 1AbC… --range Sheet1!A1:B10
grr tasks tasklists list
grr transport
grr schema

Todo comando aceita -f/--format json|jsonl|table|pretty (padrão json). Para gmail users messages get, o parâmetro MIME do Gmail chamado format chega como --param-format full|metadata|minimal|raw (veja a regra de colisão abaixo), enquanto -f/--format ainda seleciona o formato de saída impresso. Os logs vão para o stderr, então o stdout é sempre analisável:

grr gmail users messages list --user-id me --q "in:inbox" --max-results 1 | jq -r '.[0].id'

O grr --version imprime o semver na primeira linha (scripts dependem disso), depois o mascote caranguejo: em arte pixel completa de 24 bits em terminais que anunciam COLORTERM/cor direta, e como ASCII simples em qualquer outro lugar — um pipe, TERM=dumb ou NO_COLOR. Defina CLICOLOR_FORCE=1 para forçar o logo colorido através de um pipe (grr --version | less -R); o NO_COLOR ainda vence sobre ele.

Referência de comandos

A árvore de comandos é gerada a partir do índice Discovery commitado pelo scripts/generate-commands.ts (com gate de CI usando --check), então esta tabela é deliberadamente grosseira: grr --help e grr schema são a fonte da verdade, e cada um dos 401 métodos é um comando real e tipado.

GrupoO que cobreMétodos
grr authlogin [--device] [--account name], status [--account name], setup [--client-id] [--client-secret] [--print-only] [--force] [--enable-apis]—
grr ask"<request>" [--run] [--service] [--method] — linguagem natural para um método tipado + parâmetros via um modelo System One; imprime o plano por padrão-
grr mcpum servidor MCP (JSON-RPC sobre stdio) expondo cada método como uma ferramenta tipada; --readonly para somente leitura-
grr apilist [--service X] [--filter substr] [--grouped], describe <id>, call <id> …, refresh [--service X] — cada método por id, a saída de emergência plana401
grr schematoda a árvore de comandos como JSON—
grr transportversão HTTP negociada + recursos de runtime—
grr skillsinstall [--dir PATH] [--claude] [--force], list — os 16 arquivos de skill empacotados (a skill principal, uma por serviço e seu índice) no diretório de skills do usuário (~/.agents/skills, offline; --claude espelha para ~/.claude/skills)—
grr gmailmensagens, threads, rascunhos, rótulos, histórico, anexos, filtros, encaminhamento, POP/IMAP, send-as, CSE, delegados, observadores79
grr calendarcalendários, eventos, instâncias, ACL, free/busy, cores, configurações38
grr drivearquivos, permissões, comentários, respostas, revisões, alterações, drives, apps, aprovações64
grr peoplecontatos, conexões, grupos de contatos, outros contatos, pessoas do diretório24
grr chatespaços, membros, mensagens, reações, mídia, emojis personalizados, estado de leitura54
grr formscorpos de formulários, respostas, observadores, configurações de publicação10
grr taskslistas de tarefas e as tarefas dentro delas14
grr docsdocumentos get / create / batchUpdate3
grr sheetsplanilhas, valores, operações em lote, metadados de desenvolvedor17
grr slidesapresentações, páginas, miniaturas5
grr scriptprojetos de script, implantações, versões, processos, funções em execução16
grr analyticsadmincontas, propriedades, fluxos de dados, dimensões e métricas personalizadas, eventos de conversão55
grr analyticsdatarelatórios padrão, em tempo real, dinâmicos e em lote, exportações de público11
grr searchconsoleconsultas de análise de pesquisa, sitemaps, sites, inspeção de URL11

Perfis de segurança. --readonly, --deny-service <name> e --deny-verb <VERB> são flags globais honradas pela árvore gerada, grr api call, grr ask e grr mcp igualmente — elas são analisadas antes ou depois do subcomando e transformam métodos destrutivos em erros acionáveis:

grr --readonly gmail users messages delete --user-id me --id abc   # refused: DELETE
grr --deny-service chat chat spaces list                            # refused: the chat service

A árvore gerada

Todos os comandos de serviço acima são gerados a partir do índice consolidado por scripts/generate-commands.ts — não há comandos por serviço escritos à mão nem clientes por serviço escritos à mão. scripts/generate-commands.ts lê o índice de Discovery consolidado (src/discovery/*.json, ~430 KiB nos 14 serviços) e emite toda a árvore para src/commands/generated.rs — 401 folhas, 994 flags tipadas, usando a API builder do clap. Um workflow diário busca novamente o Google Discovery Service, regenera o índice junto com a árvore de comandos, as skills de agente por serviço e a tabela de cobertura do site, e abre um PR, para que novas superfícies de API cheguem até você sem esperar por um lançamento do grr. A árvore e o índice são artefatos gerados: nunca os edite manualmente.

As regras, para que você possa prever qualquer comando sem memorizá-lo:

  • A regra de nomenclatura. Uma folha espelha seu id de método Discovery: gmail.users.messages.list → grr gmail users messages list. Recursos se aninham como subcomandos; cada folha também carrega seu nome de método puro como um alias visível (list, get — métodos camelCase mantêm sua capitalização, ex.: getProfile).
  • Flags tipadas por método. Os nomes dos parâmetros vêm dos mesmos ids: userId → --user-id, maxResults → --max-results. Inteiros são analisados como i64, booleanos são flags de presença, parâmetros repetidos se repetem (--label-ids a --label-ids b), parâmetros de enum validam seus valores, e parâmetros obrigatórios são aplicados pelo clap.
  • A regra de colisão. Um parâmetro chamado format, query, params, body-file, dry-run ou help colidiria com as saídas de escape compartilhadas, então ele é exposto como --param-format / --param-query / … (veja RESERVED_FLAG_IDS em scripts/script-utils.ts).
  • Corpos não tipados. Os esquemas de solicitação do Discovery não fazem parte do índice, então os corpos POST/PATCH/PUT passam por --params <JSON> (mesclados; flags tipadas vencem) ou --body-file <PATH|-> literalmente.
  • Cada folha também carrega as saídas de escape: --params <JSON>, --body-file, --query KEY=VALUE repetível, --dry-run e -f json|jsonl|table|pretty.

O despacho resolve o id da folha contra o índice embutido e canaliza para um caminho de chamada compartilhado — o mesmo mecanismo que grr api call usa. As duas rotas são intercambiáveis:

grr api call gmail.users.messages.list --param userId=me --dry-run
grr gmail users messages list --user-id me --dry-run
# byte-identical output

grr api permanece como a saída de escape plana: list [--service] [--filter] [--grouped] para navegar, describe <id> para parâmetros e escopos, call <id> para invocar, refresh [--service] para puxar o índice adiante entre lançamentos. Como o índice é embutido em vez de buscado, tanto grr api list quanto grr schema funcionam sem nenhuma rede.

A autorização é verificada por método: grr auth login consente com um conjunto fixo de escopos, e cada chamada compara o escopo de menor privilégio do método com esse conjunto em vez de escalar silenciosamente — então um método que precisa de algo que você nunca concedeu imprime uma nota nomeando o escopo e pode falhar com um 403 por extenso em vez de um erro opaco. Docs, Sheets e Slides funcionam através do escopo drive que o grr já possui; Tasks precisa do escopo tasks, que este build não solicita, então uma chamada de Tasks imprime uma nota nomeando o escopo e pode retornar 403. As APIs deles (tasks.googleapis.com, docs.googleapis.com, sheets.googleapis.com, slides.googleapis.com) também precisam estar habilitadas no seu projeto Cloud — veja docs/gcp-setup.md.

Filosofia de design

  • Zero configuração. Os binários de lançamento carregam um cliente OAuth compilado por build.rs, então uma instalação nova executa grr auth login sem nada para configurar. ~/.grr/config.toml é a substituição, não o pré-requisito, e contém apenas o cliente OAuth (ID, opcionalmente um segredo) mais — se você apontar grr ask para seu próprio modelo — o bloco [systemone] dele (veja grr ask e System One). Escopos, URI de redirecionamento, tamanhos de pool, timeouts e política de repetição são constantes de tempo de compilação ajustadas para os frontends do Google (src/core/http.rs). GRR_CONFIG_PATH substitui a localização do arquivo, RUST_LOG o nível de log (existem variáveis de ambiente GRR_OAUTH__* para substituições headless) — nada mais é configurável, de propósito.
  • Serviços gerados e namespaced. A árvore de comandos é compilada a partir do índice de Discovery — a mesma descrição legível por máquina que o Google publica — então adições de métodos chegam como um PR diário em vez de um backlog escrito à mão. Mail é grr gmail …; Calendar, Drive, People, Chat, Forms, Tasks, Docs, Sheets e Slides ficam ao lado dele, e preocupações de nível de conta permanecem no nível superior (grr auth, grr api, grr ask, grr mcp, grr transport, grr schema, grr skills). Um login cobre todos os serviços.
  • Instalações com automigração. Um binário mais novo traz as skills de agente que instalou para a versão mais recente por conta própria: arquivos que você nunca tocou são substituídos, arquivos que você editou recebem um merge de três vias contra os bytes que o grr escreveu por último, e um conflito deixa seu arquivo intacto com a versão recebida ao lado dele (.grr-incoming). Arquivos que o grr não instalou nunca são tocados. A verificação é preguiçosa — uma comparação de versão; nada é hashado até que algo realmente precise de merge.
  • Pureza do stdout. Logs vão para o stderr, resultados vão para o stdout, então | jq sempre funciona. -f jsonl transmite arrays com um objeto por linha.
  • Armazenamento de token com prioridade para keyring. Tokens vivem no keyring do SO (Windows Credential Manager, macOS Keychain, Linux Secret Service via D-Bus), com fallback automático para <cache dir>/grr/token.json em sistemas headless. Um token encontrado no arquivo de fallback é importado automaticamente para o keyring na primeira vez que é visto.
  • Prioridade para agentes. grr schema despeja a árvore de comandos completa como JSON com zero configuração — o contrato legível por máquina para agentes de IA, descobrível sem tocar em um arquivo de configuração ou raspar --help. Um CLI rápido substitui servidores MCP por serviço: sem configuração de MCP, apenas grr schema. Também há uma skill de agente empacotada em skills/grr/SKILL.md — veja Agent skills.

Skills de agente

O grr inclui uma skill de agente empacotada: skills/grr/SKILL.md — a disciplina de descoberta primeiro (schema → api list → api describe → --dry-run), a regra de nomenclatura por id de método e o contrato de saída em um arquivo, escrito para qualquer agente de IA. A skill principal mais as 14 skills geradas por serviço são compiladas no binário, então grr skills install as escreve em ~/.agents/skills/ sem rede (Codex, opencode, Cursor, Gemini CLI, Copilot CLI e omp leem esse local; --claude espelha em ~/.claude/skills/ para Claude Code, que não lê mais nada):

grr skills install            # all 16 into ~/.agents/skills/ (idempotent; identical files are a no-op)
grr skills install --claude   # also mirror into ~/.claude/skills/
grr skills install --force    # replace files that differ from the packaged copy
grr skills list               # the packaged set, and what each target directory holds

ou instale direto do repositório com o CLI de skills:

npx skills add https://github.com/debanjanbasu/grr-cli

O guia de agentes do site carrega o mesmo contrato para humanos e autores de harness.

Desempenho

  • HTTP/3 (QUIC) por padrão — h3 com conhecimento prévio, com uma sonda autenticada na inicialização e fallback silencioso para HTTP/2; grr transport mostra o que foi realmente negociado.
  • Runtime Tokio multi-threaded, dimensionado automaticamente para os núcleos — sem pool de threads para ajustar.
  • Válvula de solicitações em voo — um semáforo (não um pool de threads) limita solicitações HTTP concorrentes a 64, ficando abaixo dos limites de taxa por usuário do Gmail para que rajadas não causem autodano em 429s. 429s são repetidos respeitando Retry-After (esperas limitadas a 30s); o timeout de solicitação inteira é de 30s.
  • Compressão sempre ativa — descompressão de resposta gzip, deflate, zstd e brotli.
  • E/S de arquivo io_uring é uma dependência específica de alvo somente Linux, detectada automaticamente em tempo de execução; não é um recurso do Cargo.

Números medidos de inicialização, tamanho do binário e latência de solicitação contra os outros CLIs do Google Workspace estão em grr-cli.pages.dev/compare/, verificados todas as noites por um workflow automatizado e remedidos sempre que uma nova versão é lançada.

Arquitetura

grr-cli é um crate publicado na raiz do repositório. src/lib.rs constrói o alvo de biblioteca grr_cli; src/main.rs é um wrapper fino sobre src/cli.rs, e o binário é nomeado grr.

.
├── src/
│   ├── core/                 # auth/device/oauth/server/store, http.rs,
│   │                         # config.rs, config_loader.rs, error.rs,
│   │                         # runtime.rs (the io_uring probe)
│   ├── commands/             # auth.rs, api.rs, setup.rs, transport.rs,
│   │                         # skills.rs, mcp.rs, ask.rs, safety.rs (the static
│   │                         # + generated.rs (GENERATED — the
│   │                         # whole service tree, ~470 KiB) and gen_dispatch.rs
│   │                         # (resolves leaf ids, funnels into the shared path)
│   ├── discovery.rs          # loader over the embedded index
│   ├── discovery/             # generated *.json index (~430 KiB, committed,
│   │                         # refreshed daily by workflow PR)
│   ├── schema.rs
│   ├── output.rs
│   ├── cli.rs
│   ├── lib.rs
│   └── main.rs
└── tests/                    # 5 integration test files

Um núcleo compartilhado, sem módulos de cliente por serviço: o CLI fala Discovery através de um único caminho de chamada (src/commands/api.rs), e os modelos tipados de solicitação/resposta da era da biblioteca 0.3.x se foram. O repositório também contém o assets/, site/ (o site Astro em grr-cli.pages.dev, implantado a partir do main pelo Cloudflare Pages), packaging/ e o material scripts/ usado para o site do projeto e distribuição.

Desenvolvimento

O grr requer Rust nightly — o script de build falha com uma mensagem clara em qualquer outra toolchain. rust-toolchain.toml flutua no nightly mais recente e fornece os componentes necessários para o build, enquanto .cargo/config.toml define o cfg reqwest_unstable para HTTP/3.

cargo build
cargo test
cargo clippy --all-targets -- -D warnings
cargo fmt --all --check
cargo run -- api list

node scripts/fetch-discovery.ts          # refresh the Discovery index
node scripts/generate-commands.ts        # regenerate the service command tree
node scripts/generate-skills.ts          # regenerate skills/<service>/SKILL.md
node scripts/generate-coverage.ts        # regenerate the site coverage table
node scripts/generate-changelog.ts       # regenerate CHANGELOG.md + site data

Cada gerador recebe --check e sai com código 1 quando sua saída está desatualizada — esse é o portão de CI. Mude o índice ou o gerador, nunca src/commands/generated.rs à mão.

  • Testes nunca tocam credenciais reais — caminhos de token são injetados, e o wiremock serve os endpoints da API.
  • RUST_LOG=debug rastreia solicitações; o nível padrão silencia os avisos inofensivos de IPv6 do quinn_udp (info,quinn_udp=error).
  • Um build local precisa de um cliente OAuth antes que uma chamada ao vivo possa funcionar: copie .env.example para .env e preencha (compilado por build.rs), ou execute grr auth setup para escrever ~/.grr/config.toml. Veja CONTRIBUTING.md.
  • cargo run -- api list e cargo run -- schema não precisam de nenhum cliente — o índice é embutido.

Empacotamento e status

CanalInstalaçãoStatus
GitHub ReleasesBinários para 5 plataformas (macOS arm64, Linux x86_64, Linux aarch64, Windows x86_64, Windows on ARM) construídos em tags v*, empacotados com UPX, .tar.zst no unix e .zip no Windowsao vivo — cada push para main lança; releases sempre carrega o mais novo
crates.iocargo install grr-cli (binário instala como grr; precisa de nightly + RUSTFLAGS="--cfg reqwest_unstable" para o build padrão de CLI HTTP/3, e não traz cliente OAuth embutido)ao vivo — um crate, publicado em cada lançamento. Publicação confiável usa OIDC (sem tokens de API armazenados)
wingetwinget install debanjanbasu.grrainda não publicado — a primeira submissão parou porque os arquivos nomeavam o binário pelo alvo (windows-x86_64.exe) enquanto o manifesto prometia grr.exe; a validação do winget nunca conseguia encontrar o instalador aninhado. Ambos os lados estão corrigidos (arquivos v0.8.1 enviam grr.exe; node scripts/generate-winget.ts <tag> deriva o manifesto do arquivo lançado e acompanha cada lançamento como grr-<tag>-winget-manifests.tar.gz)
Homebrewbrew tap debanjanbasu/tap && brew trust debanjanbasu/tap && brew install grr (tap: debanjanbasu/homebrew-tap, fórmula Formula/grr.rb, atualizada automaticamente em cada lançamento)ao vivo (macOS arm64 + Linux x86_64/arm64)

O projeto publica um pacote, grr-cli, cujo binário é grr. Tags v* disparam o workflow de lançamento, e a publicação no crates.io é tratada por publicação confiável.

Licença

MIT — veja LICENSE.