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.
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
- Retrato antes de atualizar — por padrão é salvo um retrato leve do estado (dados de
pareamento, tarefas de cron,
config.yaml,.env,auth.jsone 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óriostate-snapshots/— e a rede de proteção das tarefas de cron confere cada perfil contra o retrato dele. Controlado porupdates.pre_update_backup(quickpor padrão,fullpara um zip de todo oHERMES_HOME,offpara 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). - Git pull — puxa o código mais recente da branch
maine atualiza os submódulos. - 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
hermesimporta ao iniciar. Se algum não compilar (um marcador de conflito de merge órfão, um arquivo truncado por acidente), o Hermes rodagit reset --hard <sha-anterior>para reverter a instalação e o seu shell continuar funcionando. Rode ohermes updatede novo quando a correção chegar no upstream. - Instalação de dependências — roda
uv pip install -e ".[all]"para pegar o que mudou. - Migração de configuração — detecta as opções novas desde a sua versão e pergunta sobre elas.
- 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 serveehermes dashboardlanç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— ogit cherrynão aponta nada pendente): a atualização avisa —Checkout was parked on '<branch>' (fully merged) — switched back to main— e fica namain. - Branch com commits ainda não incorporados, mas árvore limpa: a atualização muda para a
mainmesmo assim, para poder prosseguir — é disso que dependem os chamadores não interativos (o botão de atualizar do desktop, o/updatedo gateway, o cron), que não têm como resolver um cancelamento. Seus commits ficam intactos: ogit checkoutnunca descarta trabalho commitado, e a atualização imprime um aviso em destaque, com o nome da branch, quantos commits ela tem e o comandogit 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 comonode_modules,venve 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.
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:
git status --short— se a árvore estiver suja sem motivo, investigue antes de continuar.hermes doctor— confere configuração, dependências e saúde dos serviços.hermes --version— confirme que a versão subiu como esperado.- Se você usa o gateway:
hermes gateway status. - Se o
doctorapontar problemas de auditoria do npm: rodenpm audit fixno diretório indicado.
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 depipegitherdam 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.logenquanto 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]"
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.
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
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