Pular para o conteúdo principal

Documentação oficial desta página · v0.20.6

Atualizar e Desinstalar

Atualizar​

Um comando só:

hermes update

Ele puxa o código mais recente da main, atualiza as dependências e pergunta sobre as opções de configuração novas que surgiram desde a sua última atualização.

dica

O hermes update detecta sozinho as opções novas e pergunta se você quer acrescentá-las. Se você pulou essa pergunta, rode hermes config check para ver o que está faltando e depois hermes config migrate para acrescentar de forma interativa.

O que acontece durante uma atualização​

  1. Retrato antes de atualizar — por padrão é salvo um retrato leve do estado (dados de pareamento, tarefas de cron, config.yaml, .env, auth.json e os outros arquivos de estado que mudam em tempo de execução; arquivos individuais acima de 1 GiB são pulados, para um banco de sessões grande não travar a atualização). Como a troca de código e o reinício dos gateways afetam todos os perfis, o mesmo retrato é tirado de cada perfil da instalação — cada um no seu próprio diretório state-snapshots/ — e a rede de proteção das tarefas de cron confere cada perfil contra o retrato dele. Controlado por updates.pre_update_backup (quick por padrão, full para um zip de todo o HERMES_HOME, off para desligar). A recuperação está no fluxo de restauração descrito em Checkpoints e Rollback. Retratos rápidos servem para recuperar arquivo perdido, não para desfazer código — para voltar a um ponto coerente no tempo, use --backup (modo completo).
  2. Git pull — puxa o código mais recente da branch main e atualiza os submódulos.
  3. Validação de sintaxe e reversão automática — depois do pull, o Hermes compila os nove arquivos críticos que toda invocação do hermes importa ao iniciar. Se algum não compilar (um marcador de conflito de merge órfão, um arquivo truncado por acidente), o Hermes roda git reset --hard <sha-anterior> para reverter a instalação e o seu shell continuar funcionando. Rode o hermes update de novo quando a correção chegar no upstream.
  4. Instalação de dependências — roda uv pip install -e ".[all]" para pegar o que mudou.
  5. Migração de configuração — detecta as opções novas desde a sua versão e pergunta sobre elas.
  6. Reinício automático dos gateways — os gateways em execução são atualizados no fim, para o código novo valer na hora. Gateways gerenciados por serviço (systemd no Linux, launchd no macOS) são reiniciados pelo gerenciador. Gateways manuais são relançados quando o Hermes consegue ligar o PID em execução a um perfil. Backends de hermes serve e hermes dashboard lançados na mão recebem o mesmo tratamento: cada um registra o endereço em que escuta no registro de processos da instalação, então a atualização o para antes da troca de código e o relança depois no mesmo host e porta — um Desktop remoto apontado para aquele endereço reconecta, em vez de ficar órfão. Backends que pertencem a um Desktop em execução ficam por conta do próprio aplicativo.

Atualizar por outra branch: --branch​

Por padrão o hermes update segue a origin/main. Passe --branch <nome> para atualizar por outra branch — útil para canais de teste, branches de recurso ou candidatas a versão:

hermes update --branch release-candidate
hermes update --check --branch experimental # só mostra o quanto está atrás

Se o seu clone local estiver em outra branch, o Hermes guarda o trabalho não commitado num stash, move o HEAD para a branch de destino e então puxa. Branches que não existem localmente passam a seguir a origin/<nome> automaticamente (git checkout -B <nome> origin/<nome>). Branches que não existem em lugar nenhum falham de forma limpa — o stash é restaurado antes de sair, então você nunca fica num estado estranho. A lógica de sincronização com o fork upstream, que só vale na main, é pulada nas outras branches.

Clone parado numa branch de recurso​

Se o clone ficou numa branch de recurso (por causa de alguma ferramenta, de um experimento com worktree ou de um checkout manual), o hermes update volta sozinho para o destino da atualização sempre que a árvore de trabalho estiver limpa:

  • Branch totalmente incorporada (todo commit já está na origin/main — o git cherry não aponta nada pendente): a atualização avisa — Checkout was parked on '<branch>' (fully merged) — switched back to main — e fica na main.
  • Branch com commits ainda não incorporados, mas árvore limpa: a atualização muda para a main mesmo assim, para poder prosseguir — é disso que dependem os chamadores não interativos (o botão de atualizar do desktop, o /update do gateway, o cron), que não têm como resolver um cancelamento. Seus commits ficam intactos: o git checkout nunca descarta trabalho commitado, e a atualização imprime um aviso em destaque, com o nome da branch, quantos commits ela tem e o comando git checkout <branch> para retomar depois.

Se você roda uma branch própria de propósito (correções locais mantidas em cima da main), defina updates.parked_branch_strategy: update_in_place no config.yaml. A atualização passa a mesclar a origin/main na sua branch, em vez de sair dela — o clone não se move, seus commits sobrevivem e o código em execução avança. Fast-forward quando dá; havendo divergência, um merge de verdade protegido por uma tag pre-update-<carimbo>, parando limpo (sem mudar nada) em caso de conflito. O hermes update --switch-branch força o caminho de troca por uma execução — útil numa branch de recurso longa, que não pode acumular commits de merge vindos de atualização.

Quando a branch tem mudanças não commitadas (árvore suja), o Hermes não mexe nela. A atualização de código é marcada como SKIPPED, com um aviso em destaque nomeando a branch, quanto ela está atrás da origin/main e os comandos exatos para resolver — em vez de fingir que deu certo. A linha final sempre mostra a branch e o HEAD reais (✓ Update complete! [main @ 30fcf9580]), então o desvio fica visível. Defina updates.auto_switch_parked_branch: false no config.yaml para desligar a troca automática (o aviso de cancelamento continua).

Mudanças locais em atualizações não interativas​

Quando você roda hermes update num terminal, o Hermes guarda as mudanças não commitadas num stash, puxa e então pergunta se deve restaurá-las — como sempre foi.

Quando a atualização roda sem terminal — pelo botão de atualizar do aplicativo ou disparada pelo gateway — não há pergunta a responder. A opção updates.non_interactive_local_changes decide o destino do que foi guardado:

# ~/.hermes/config.yaml
updates:
non_interactive_local_changes: stash # padrão: guarda e restaura sozinho
# non_interactive_local_changes: discard # joga fora as edições locais no código
  • stash (padrão) — guarda, puxa e restaura suas mudanças em cima do código novo. Nada se perde; se a restauração der conflito, o conteúdo fica preservado num stash do git para recuperação manual.
  • discard — guarda e descarta o stash depois do pull, então a atualização sempre cai numa árvore limpa. Use só em máquinas onde você nunca pretende manter edições no código do Hermes. O descarte é do stash (não é git reset --hard + git clean -fd), então caminhos ignorados como node_modules, venv e saídas de build nunca são tocados.

No aplicativo desktop isso fica em Settings → Advanced → In-App Update Local Changes.

Atualizações pelo desktop nunca restauram sozinhas. O atualizador do desktop chama hermes update --keep-stash: as edições locais ainda são guardadas para a atualização poder seguir, mas não são reaplicadas depois — ficam paradas no git stash, e o log da atualização imprime o comando git stash apply <ref> exato para trazê-las de volta. Isso evita que edições locais peguem carona em silêncio numa atualização de desktop e quebrem a instalação recém atualizada. (O non_interactive_local_changes: discard ainda vence, se você optou por descartar.) Para restaurar na mão:

cd ~/.hermes/hermes-agent # ou a raiz da sua instalação
git stash list --format='%gd %H %s' # ache a entrada hermes-update-autostash
git stash apply stash@{0}

Você pode passar --keep-stash num hermes update de terminal também, se quiser o mesmo comportamento de nunca reaplicar.

Só conferir: hermes update --check​

Quer saber se há atualização antes de puxar? Rode hermes update --check — ele busca e compara os commits com a origin/main. Nenhum arquivo é alterado, nenhum gateway é reiniciado. Serve em scripts e tarefas de cron que dependem de "existe atualização?".

Prévia da frota: hermes update --plan​

Antes de atualizar uma máquina com vários perfis ou serviços, o hermes update --plan imprime o plano completo sem mudar nada: o tipo de instalação (clone git, imagem Docker, gerenciada por Nix ou apt), cada serviço do Hermes em execução em todos os perfis com o supervisor dele (systemd, launchd, manual) e a versão de código que ele está realmente servindo, e o mecanismo de reinício que cada um vai receber. Backends de hermes serve e hermes dashboard lançados na mão também aparecem (pelo registro de processos), com o endereço registrado e o mecanismo "parar antes da troca de código, relançar com os argumentos registrados". Em instalações gerenciadas por imagem ou pacote, o plano informa que a instalação não é atualizável no lugar e diz qual é o comando certo. É só leitura, seguro numa frota em produção.

O mesmo inventário fica embutido no recibo de toda atualização de verdade (~/.hermes/logs/update_receipts/), então depois dá para comparar o que o atualizador viu com o que ele fez.

Recibos de atualização e conferência de versão da frota​

Toda execução do hermes update grava um recibo legível por máquina em ~/.hermes/logs/update_receipts/ (os últimos 20 são mantidos; latest.json sempre aponta para o mais recente): o plano da frota antes de atualizar, cada passo dado, o que foi pulado e por quê, o resultado do reinício dos gateways e a matriz final de versões. Depois da fase de reinício, o atualizador compara o código em execução de cada gateway vivo com o clone recém atualizado e imprime uma matriz por perfil — um gateway ainda servindo código antigo é reportado em destaque, com o comando exato de reinício, e a atualização sai com código diferente de zero, para nenhuma automação tratar uma frota com versões misturadas como saudável. Tanto o --plan quanto essa conferência perguntam diretamente a cada gateway em execução pelo socket local de controle (gateway.sock no diretório de dados do perfil, um named pipe no Windows) quando ele está disponível, então a informação de versão e supervisor vem do próprio gateway; gateways de versões mais antigas continuam sendo descobertos pelos arquivos de estado, como antes.

Backup completo antes de atualizar: --backup​

Para perfis valiosos (gateways de produção, instalações compartilhadas de equipe), dá para pedir um backup completo do HERMES_HOME antes do pull (configuração, autenticação, sessões, skills, pareamento):

hermes update --backup

Ou torne isso o padrão de toda execução:

# ~/.hermes/config.yaml
updates:
pre_update_backup: full

O updates.pre_update_backup é um botão só, com três modos: quick (padrão — o retrato leve descrito acima), full (o retrato rápido mais um zip completo do HERMES_HOME; pode acrescentar minutos em diretórios grandes) e off (sem backup nenhum antes de atualizar — o --no-backup faz o mesmo por uma execução). Os valores booleanos antigos continuam funcionando: true é full, false é off.

Vai mudar de máquina?

Backup de atualização protege uma atualização no lugar. Se você está migrando a instalação inteira para outro hardware, use hermes backup e hermes import — veja exportar o Hermes para outra máquina e hermes backup vs hermes profile export.

Windows: outro hermes.exe em execução​

No Windows, o hermes update se recusa a rodar quando detecta outro processo hermes.exe segurando o executável do ambiente virtual — mais comum: o backend do Hermes Desktop, um REPL hermes aberto em outro terminal, ou um gateway em execução:

$ hermes update
✗ Another hermes.exe is running:
PID 12345 hermes.exe

Updating now would fail to overwrite ...\venv\Scripts\hermes.exe because
Windows blocks REPLACE on a running executable.

Close Hermes Desktop, exit any open `hermes` REPLs, and
stop the gateway (`hermes gateway stop`) before retrying.
Override with `hermes update --force` if you've already
confirmed those processes will not write to the venv.

Feche os processos listados e tente de novo. Se você tem certeza de que o processo simultâneo não vai atrapalhar (raro — normalmente só quando um antivírus é identificado errado), passe --force para pular a checagem. Nesse caso o atualizador ainda vai tentar renomear o .exe várias vezes, com espera crescente, e, em travas teimosas, agendar a substituição para o próximo boot com MoveFileEx(MOVEFILE_DELAY_UNTIL_REBOOT), para a atualização conseguir terminar.

Uma segunda proteção, separada, se recusa a mexer no ambiente virtual enquanto qualquer processo estiver rodando a partir do interpretador Python dele (o backend do Desktop, um gateway, um REPL Python). Esses processos mantêm arquivos de extensão nativa (.pyd) travados, e uma sincronização de dependências que morre no meio com erro de acesso negado deixa a instalação entre versões. Essa proteção não é ignorada pelo --force; se você tem certeza de que os processos detectados são falso positivo, use o explícito hermes update --force-venv.

No Windows, recriar o venv é transacional​

Quando o instalador do Windows precisa recriar um venv existente, ele primeiro move o diretório antigo para um nome único venv.stale.*, depois cria e verifica o substituto. A árvore antiga só é apagada depois que a instalação de dependências termina e os imports básicos passam na árvore nova — até lá ela é a fonte de reversão (registrada em venv.pending-backup).

Se o movimento não puder ser concluído, o instalador para e deixa o venv em uso intocado. Se o uv falhar, ou disser que deu certo sem criar o interpretador, qualquer substituição parcial é movida para venv.failed.* e o venv anterior é restaurado. Assim as checagens de saúde continuam utilizáveis mesmo depois de uma instalação que falhou.

Um diretório venv.stale.* ou venv.failed.* pode ficar para trás quando outro processo ainda segura um arquivo. Feche o Hermes Desktop, os gateways e os processos Python que usam a instalação, e tente de novo; os diretórios parados são limpos, na medida do possível, depois de uma recriação bem-sucedida.

A saída esperada é assim:

$ hermes update
Updating Hermes Agent...
📥 Pulling latest code...
Already up to date. (or: Updating abc1234..def5678)
📦 Updating dependencies...
✅ Dependencies updated
🔍 Checking for new config options...
✅ Config is up to date (or: Found 2 new options — running migration...)
🔄 Restarting gateways...
✅ Gateway restarted
✅ Hermes Agent updated successfully!

Validação recomendada depois de atualizar​

O hermes update cuida do caminho principal, mas uma conferência rápida confirma que tudo entrou direito:

  1. git status --short — se a árvore estiver suja sem motivo, investigue antes de continuar.
  2. hermes doctor — confere configuração, dependências e saúde dos serviços.
  3. hermes --version — confirme que a versão subiu como esperado.
  4. Se você usa o gateway: hermes gateway status.
  5. Se o doctor apontar problemas de auditoria do npm: rode npm audit fix no diretório indicado.
Árvore suja depois de atualizar

Se o git status --short mostrar mudanças inesperadas depois do hermes update, pare e investigue antes de seguir. Em geral significa que modificações locais foram reaplicadas em cima do código novo, ou que algum passo de dependência atualizou arquivos de trava.

Se o terminal cair no meio da atualização​

O hermes update se protege contra perda acidental do terminal:

  • A atualização ignora SIGHUP, então fechar a sessão SSH ou a janela do terminal não a mata mais no meio. Os processos filhos de pip e git herdam essa proteção, então o ambiente Python não fica pela metade por causa de uma conexão que caiu.
  • Toda a saída é espelhada em ~/.hermes/logs/update.log enquanto a atualização roda. Se o terminal sumir, reconecte e olhe o log para ver se a atualização terminou e se o reinício do gateway deu certo:
tail -f ~/.hermes/logs/update.log
  • Ctrl-C (SIGINT) e desligamento do sistema (SIGTERM) continuam sendo respeitados — esses são cancelamentos deliberados, não acidentes.

Não é mais preciso embrulhar o hermes update em screen ou tmux para sobreviver a uma queda de terminal.

Conferir sua versão​

hermes --version

Compare com a versão mais recente na página de releases do GitHub.

Atualizar pelas plataformas de mensagem​

Dá para atualizar direto do Telegram, Discord, Slack, WhatsApp ou Teams, mandando:

/update

Isso puxa o código novo, atualiza as dependências e reinicia os gateways em execução. O bot fica fora do ar por alguns segundos durante o reinício (normalmente de 5 a 15) e volta.

Atualização manual​

Se você instalou na mão (não pelo instalador rápido):

cd /caminho/para/hermes-agent
# Ative o venv que você criou na instalação (fora da árvore do código)
export VIRTUAL_ENV="$HOME/.hermes/venvs/hermes-dev"
export PATH="$VIRTUAL_ENV/bin:$PATH"

# Puxe o código mais recente
git pull origin main

# Reinstale (pega as dependências novas)
uv pip install -e ".[all]"

# Confira as opções de configuração novas
hermes config check
hermes config migrate # acrescenta o que estiver faltando, de forma interativa

Como voltar atrás​

Se uma atualização trouxer problema, dá para voltar a uma versão anterior:

cd /caminho/para/hermes-agent

# Liste as versões recentes
git log --oneline -10

# Volte para um commit específico
git checkout <hash-do-commit>
uv pip install -e ".[all]"

# Reinicie o gateway, se estiver rodando
hermes gateway restart

Para voltar a uma tag de versão específica (troque pela sua tag anterior — uma versão recente como v2026.5.16, ou qualquer tag mais antiga de git tag --sort=-version:refname):

git checkout vX.Y.Z
uv pip install -e ".[all]"
aviso

Voltar atrás pode causar incompatibilidade de configuração, se opções novas tiverem sido acrescentadas. Rode hermes config check depois de voltar e remova do config.yaml as opções não reconhecidas, se aparecer erro.

Instalações gerenciadas por imagem (Docker): o marcador de procedência​

As imagens Docker publicadas trazem um marcador pequeno, só de leitura (/etc/hermes/image-provenance.json), que identifica o sistema de arquivos como gerenciado por imagem, de forma definitiva. O hermes update, o hermes update --check e o botão de atualizar do painel consultam esse marcador antes de mexer em qualquer coisa: numa instalação por imagem, eles recusam de forma limpa (código de saída 2), imprimem o comando certo (docker pull nousresearch/hermes-agent:latest) e gravam um recibo de recusa, para as ferramentas de frota verem que a tentativa aconteceu. O marcador vence mesmo quando um clone do código está montado dentro do container — a recusa se baseia no que o sistema de arquivos em execução é, não no que ele parece. Marcador danificado também recusa (falha fechada). Instalações gerenciadas por Nix e apt recusam pelo mesmo caminho, usando a detecção que já existia.

Aviso para quem usa Nix​

O Nix deixou de ser um caminho de instalação oficialmente suportado — veja Nix e NixOS. Se você instalou por flake, as atualizações passam pelo gerenciador de pacotes do Nix:

# Atualize o input do flake
nix flake update hermes-agent

# Ou reconstrua com o mais recente
nix profile upgrade hermes-agent

Instalações Nix são imutáveis — voltar atrás é responsabilidade do sistema de gerações do Nix:

nix profile rollback

Desinstalar​

hermes uninstall

O desinstalador oferece a opção de manter seus arquivos de configuração (~/.hermes/) para uma reinstalação futura.

Está mudando de máquina, e não indo embora?

Leve sua instalação antes de apagar qualquer coisa: o hermes backup captura o diretório ~/.hermes inteiro, credenciais incluídas, enquanto o hermes profile export empacota um perfil só, sem credenciais, de propósito (então a exportação sozinha não é um backup completo). Veja hermes backup vs hermes profile export.

Desinstalação manual​

rm -f ~/.local/bin/hermes
rm -rf /caminho/para/hermes-agent
rm -rf ~/.hermes # opcional — mantenha se pretende reinstalar
informação

Se você instalou o gateway como serviço do sistema, pare e desabilite antes:

hermes gateway stop
# Linux: systemctl --user disable hermes-gateway
# macOS: launchctl remove ai.hermes.gateway