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 current e ✗ 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-updates primeiro; ele não toca em nada.
  • Rode hermes plugins list depois. 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 --yes explicitamente 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.