Um comando para atualizar todos os plugins: o hermes plugins update agora mostra a lista primeiro

De volta de uma semana de folga, você roda hermes plugins list e encontra doze plugins instalados, sete deles marcados com atualização disponível. Você lembra que dois desses trouxeram correções de bug. Então começa a digitar nomes — hermes plugins update foo, depois bar — e lá pela quarta você perde a conta de quais faltam, desiste e promete que resolve isso depois.
É aquele tipo de tarefa que nunca quebra nada, mas não para de custar. Uma mudança mesclada em 19 de outubro resolve: agora hermes plugins update funciona sem nome de plugin — audita primeiro, atualiza uma vez só.
Por que antes era obrigatório passar um nome
O subcomando update fazia exatamente uma coisa: receber um nome, descobrir como aquele plugin foi instalado e puxar a versão mais nova. Ele não sabia o que mais estava instalado, então sem nome só conseguia imprimir um erro de uso:
$ hermes plugins update
usage: hermes plugins update [-h] name
hermes plugins update: error: the following arguments are required: name
Atualizar em massa significava escrever seu próprio loop, e loop é fácil de escrever mal. O nome do diretório é mesmo o nome do plugin? Instalações por catálogo e por Git atualizam de formas diferentes — você ramifica por isso? Se um falha, você continua? Todo esse julgamento morava na sua cabeça.
Agora: sem nome quer dizer “audite todos”
hermes plugins update
Num terminal ele roda uma sonda check-updates somente leitura e imprime uma tabela:
| # | Plugin | Current | Latest | Update |
|---|---|---|---|---|
| 1 | hermes-dreaming | 2.9.3 | 2.9.5 | catalog re-pin |
| 2 | obsidian-sync | a1b2c3d4 | 9f8e7d6c | git pull |
Abaixo da tabela ele nomeia cada plugin que pula e o motivo — por exemplo skipped foo (pip): pip distribution; Hermes does not upgrade it. Depois pergunta uma única vez:
Update all 2? [Y/n]:
Enter ou y e ele atualiza cada um. Cada plugin continua passando pelo caminho completo de plugin único — isso não é um force-push. Se uma versão nova pede capabilities novas (uma ferramenta nova, acesso novo ao sistema de arquivos), esse prompt ainda aparece por plugin; se o catálogo aponta de novo para um commit de release, isso também ainda pergunta. O objetivo de agrupar é eliminar digitação repetida, não eliminar consentimento informado.
Uma falha não interrompe o resto
O pior comportamento em lote é “o terceiro plugin falhou, então os quatro últimos nunca rodaram”. Aqui cada plugin é independente:
- Uma falha imprime a linha de erro daquele plugin e segue em frente;
- A execução termina com um resumo dividido em
✓ updated,= already currente✗ failed(com a primeira linha do motivo da falha); - O código de saída é 1 se algo falhou, 0 se tudo deu certo;
- Sem nada a fazer, ele diz
No plugin updates to apply.e sai com 0.
Isso o torna seguro para colocar atrás de um condicional no shell ou num job agendado:
hermes plugins update --yes || echo "some plugin failed to update"
Rodando em scripts, cron e pipes
Sem terminal (cron, CI, um pipe para tee), o padrão é não fazer nada: ele imprime a lista, sai com 1 e avisa para rodar de novo com --yes. Esse conservadorismo é proposital — upgrade em massa nunca deve mudar coisas em silêncio num ambiente sem supervisão.
Com --yes, as atualizações realmente rodam, mas o consentimento falha fechado:
- Capabilities novas pedidas por uma versão nova não são concedidas; o plugin fica restrito;
- Um commit de catálogo re-apontado não é aplicado;
- Tudo o que não precisa de consentimento extra atualiza normalmente.
--yes também só é válido sem nome. hermes plugins update foo --yes é recusado, para ninguém ler isso como “atualize este aqui e aprove automaticamente tudo o que ele pedir”.
Se você realmente quer atualizações sem supervisão para alguns plugins, esse é um interruptor separado e explícito:
plugins:
auto_apply: true # tracked Git installs only; default false
auto_apply cobre apenas plugins Git rastreados. Ele não toca em linhas pinned, colocadas manualmente, com procedência divergente ou distribuição pip. As duas rotas passam pelo mesmo scan de segurança pré-atualização.
Quais plugins são pulados, e por quê
A atualização em massa só age sobre os dois tipos que o update consegue de fato mover: instalações por catálogo (re-apontadas para o commit revisado do catálogo) e instalações Git rastreadas (puxadas). Todo o resto é pulado nominalmente em vez de ser “atualizado” em silêncio:
| Caso | Motivo do pulo |
|---|---|
| distribuição pip | O Hermes não faz upgrade de pacotes PyPI — isso é trabalho do pip |
| pinned (versão ou commit) | Pinado significa que você quer aquilo parado onde está |
| needs fixing | Conserte o estado da instalação primeiro |
| status desconhecido | Não alcança o remoto, então não vai adivinhar |
Se você fez git clone de um plugin direto no diretório de plugins, ele não é uma instalação rastreada — rode hermes plugins adopt <name> antes, para o Hermes saber de onde ele veio. Isso é intencional: ele não vai puxar um diretório cuja procedência não entende.
Mais um detalhe de segurança: se uma versão nova muda o manifesto, ou introduz ou substitui um update_url, o Hermes recusa o endereço novo até você aprovar:
hermes plugins trust-update-url my-plugin
Isso é uma checagem de procedência de feed, não um sandbox. Protege contra “o canal de atualização foi trocado pelo servidor de outra pessoa”; não protege contra código em que você já confia fazer algo ruim.
Quando as checagens acontecem, e como verificar
hermes plugins update roda a mesma sonda que hermes plugins check-updates, que é somente leitura e não mexe nos arquivos do plugin — boa para monitoramento:
hermes plugins check-updates # report only, changes nothing
O gateway também roda uma checagem agendada, espaçada por plugins.auto_update_check_hours (24 horas por padrão, 0 desativa). O recibo dela aparece em hermes pm status e na visão de status de sincronização do Desktop. Isso controla apenas com que frequência o Hermes olha — nada atualiza por padrão a menos que você rode update ou opte por auto_apply.
Conselhos práticos
- Olhe antes de pular. Se você não sabe o tamanho do atraso, rode
hermes plugins check-updatesprimeiro; ele não toca em nada. - Rode
hermes plugins listdepois. A atualização em massa ainda pergunta por plugin. Se você martelou Enter num prompt de autorização, aquele plugin termina restrito em vez de quebrado, e nada grita com você — vale uma olhada. - Não confie nos padrões em CI. Sem terminal ele se recusa a atualizar e sai com 1; se seu pipeline trata código diferente de zero como falha, passe
--yesexplicitamente ou deixe upgrades fora do CI. - “Versão nova” significa coisas diferentes por tipo de instalação. Uma instalação por catálogo vai para um commit que o catálogo revisou; uma instalação Git segue o HEAD da branch upstream. A segunda tem um raio de impacto bem maior.
Dois posts anteriores dão o contexto: como o catálogo de plugins funciona e o portão de supply chain de CI por trás dele. Se você mantém plugins portáteis, o portão de trust MCP para plugins portáteis cobre a outra metade da história de confiança. A lista completa de subcomandos está na referência do comando plugins.
A versão curta
Upgrade em massa não é a parte difícil — manter “em massa” e “consentimento informado” juntos é. Esta mudança traça a linha com clareza: a digitação repetida vai embora, e toda decisão que importa (capabilities novas, um commit de catálogo re-apontado, uma origem de atualização alterada) continua aparecendo na sua frente, uma de cada vez. Para quem roda uma dúzia de plugins, essa é a diferença entre “eu vejo isso depois” e uma linha por semana.