🤖HermesBlog
Hermes 官方教程 · 第4篇2026/8/9· Easy Understand Hermes Agent

更新与卸载,保持你的 Hermes 最新

Hermes Agent 官方教程第四篇:更新与卸载。升级不丢数据。

给 Hermes 做保养:更新与卸载仪表盘

更新与卸载,保持你的 Hermes 最新

嘿,朋友们!今天咱们来聊聊怎么让 Hermes 始终保持最新状态,以及哪天想卸载了该怎么办。别担心,这比想象中简单多了。

一键更新,就是这么简单

老规矩,先上命令:

hermes update

就这么一行,Hermes 会自动帮你完成所有脏活累活。它会从 main 分支拉取最新代码、更新依赖,还会自动检测新增的配置选项并提示你设置。要是当时手滑跳过了配置提示,别慌,随时可以手动补救:

hermes config check    # 看看缺了哪些配置
hermes config migrate  # 交互式补全配置

关闭被动更新提示

如果你用的是固定版本,或者在非交互环境里跑 Hermes,可以关掉 CLI 的版本和横幅更新检查:

hermes config set updates.check false

这会同时屏蔽缓存的更新提示和被动的更新检查网络请求,默认值是 true。注意:手动执行 hermes update --checkhermes update 仍然照常工作,这个开关也不管桌面应用自己的更新器。

更新时到底发生了什么?

你可能会好奇,这行命令背后到底干了啥?其实 Hermes 做了八件事:

  1. 更新前快照:默认会保存一份轻量级状态快照(包括配对数据、定时任务、config.yaml.envauth.json 等运行时文件),单个超过 1GiB 的大文件会自动跳过,所以不用担心更新变慢。因为代码切换和网关重启会触及每个 profile,所以安装里的每个 profile 都会各存一份快照到自己的 state-snapshots/ 目录。由 updates.pre_update_backup 控制(默认 quickfull 会打包整个 HERMES_HOME 的 zip,off 关闭)。想要更全面的备份?用 --backup 参数开启完整模式。快照是尽力而为的:万一失败,更新会打印 ⚠ Pre-update snapshot FAILED 警告然后继续,不会卡住你。

  2. 拉取代码:从 main 分支拉取最新代码并更新子模块。

  3. 语法校验 + 自动回滚:这是最贴心的设计!拉完代码后,Hermes 会立刻编译 9 个关键文件。万一发现语法错误(比如合并冲突残留),它会自动 git reset --hard 回滚,保证你的终端永远能用。通过校验后,更新器会在新拉下来的代码上重新执行自己(update.log 里会看到 === hermes update continued on the pulled code ===),所以后面的步骤不会新旧模块混着跑。要是你一瞬间看到两个 hermes update 进程,那就是它在交接班。

  4. 安装依赖:自动运行 uv pip install -e ".[all]" 安装新增或变更的依赖。就算代码已经是最新的,只要虚拟环境不健康(核心导入失败),或者装着的 hermes-agent 还是旧版本(说明上次的依赖安装被中断了),这一步照样会跑——所以 ✓ Already up to date! 不会掩盖一个半更新的环境。

  5. 配置迁移:检测新配置项并引导你设置。

  6. 桌面端重建(stage-and-swap):如果 Hermes 桌面应用是从这个 checkout 构建的,它会重新构建,让 GUI 和新代码保持一致。重建会先打包到 apps/desktop/release/ 旁边的临时暂存目录,验证通过后才重命名覆盖旧版本。任何一步失败(Electron 下载损坏、依赖缺失、磁盘满)都会保留旧应用不动、仍可启动,更新会报告 ⚠ Update partially complete,之后运行 hermes desktop 会重试重建。在 macOS 上,重建好的包还会用 ditto(保留签名)复制覆盖掉过期的 /Applications/Hermes.app~/Applications/Hermes.app,这样你从 Finder 和 Dock 点开的版本才和后端一致;如果那份已安装的副本正在运行,更新不会动它,只会提示你退出后再跑一次 hermes update

  7. 网关自动重启:更新完成后,运行中的网关会自动重启。系统服务(systemd/launchd)走服务管理器,手动启动的也会在能对应上 profile 时自动重新拉起。手动启动的 hermes serve / hermes dashboard 后端不一样:更新器会让它们继续跑,请它们的主人自己重启。桌面应用自己拉起的后端也归应用自己管。

  8. 多路复用迁移(多 profile 安装):当新代码验证通过后,如果一个安装有两个或更多 profile、且仍然每个 profile 各跑一个网关,在没有阻碍的情况下会被折叠成单个多路复用的默认网关(等同于 hermes gateway migrate --multiplex --yes);如果存在阻碍(比如两个 profile 共用一个 bot token,或某个次要 profile 绑定了没有 /p/<profile>/ 入口的端口),更新会打印阻碍项和修复方法,不做任何改动。单 profile 安装永远不会被触碰。

更新前先看一眼计划

机器上跑了好几个 profile 或服务?更新前可以先跑:

hermes update --plan

它会只读地打印安装类型、各 profile 下正在运行的 Hermes 服务、它们的监管方式和实际运行的代码版本,以及每个服务会怎么重启。手动启动的 hermes serve / hermes dashboard 后端也会列出来(带记录的绑定地址),但重启交给它们的主人,更新器不会去停或重启。镜像或包管理器安装的会直接告诉你该用哪条外部更新命令。这个命令不改任何东西,在活着的集群上跑也安全。

另外,每次 hermes update 都会在 ~/.hermes/logs/update_receipts/ 写一份机器可读的回执(保留最近 20 份,latest.json 永远指向最新那份),记录更新前的集群计划、每一步做了什么、跳过了什么及原因、网关重启结果和最终的版本矩阵。重启阶段之后,更新器还会把每个活着的网关实际运行的代码和新代码对比,打印一份按 profile 的矩阵——还在跑旧代码的网关会被大声点名并给出确切的重启命令,更新也会以非零状态退出,这样自动化就不会把混版本的集群当成健康的。

为什么网关重启可能要等一会儿

重启是“先排空”的:运行中的网关会拒绝新的回合,然后等待进行中的工作(聊天回合、定时任务、API 运行)完成后再退出,上限由 agent.restart_after_turn_timeout 控制(默认 30 分钟),所以长时间运行的任务不会被中途切断。等待期间,更新器每 30 秒会打印网关还在等什么。想立刻停止等待,可以结束或杀掉列出的工作,或者在 config.yaml 里调低 agent.restart_after_turn_timeout(设为 0 会立即进入强制排空)。

进阶玩法:更新到其他分支

默认跟踪 origin/main,但如果你想体验测试版或候选版本:

hermes update --branch release-candidate
hermes update --check --branch experimental  # 只查看落后多少,不实际更新

如果你的本地 checkout 停在别的分支,Hermes 会自动暂存未提交的改动、切换到目标分支再拉取。分支不存在?会自动从 origin 创建跟踪。失败也会干净退出,不会把你晾在半路。非 main 分支上会自动跳过 main 专属的 fork-upstream 同步逻辑。

停在功能分支怎么办?

有时候你可能不小心把 checkout 停在了某个功能分支。Hermes 会智能处理:

  • 分支已完全合并:自动切回 main,并告诉你一声。
  • 分支有未合并提交但工作区干净:照样切回 main 继续更新(桌面端更新按钮、网关 /update、定时任务都依赖这个行为),你的提交一个都不会丢,更新后会打印提示和找回命令。
  • 工作区有未提交改动:Hermes 不会碰它,更新标记为 SKIPPED 并给出警告和解决命令。

如果你故意维护自定义分支,可以在 config.yaml 里设置:

updates:
  parked_branch_strategy: update_in_place

这样更新会直接把 origin/main 合并进你的分支,而不是切走。冲突时干净停止,不会搞乱你的代码。想临时改回切换路径,可以用 hermes update --switch-branch。另外,设置 updates.auto_switch_parked_branch: false 可以完全关掉自动切换(跳过警告还是会照常出现)。

非交互更新时的本地改动

在终端里跑 hermes update 时,Hermes 会暂存未提交的源码改动、拉取,然后询问是否恢复——和以前一样,交互式更新没有任何变化。

自动暂存只管源码树里的改动。在扁平安装(git checkout 根目录同时也是 $HERMES_HOME,比如用 HERMES_INSTALL_DIR=$HERMES_HOME 装的,或者老安装器建的)里,profile 的运行时状态(state.db 及其 WAL/SHM 文件、state-snapshots/backups/sessions/cron/jobs.jsoncron/*.dbconfig.yamlauth.jsonmemories/、锁和 pid 文件等)都是 checkout 里的未跟踪文件。这些路径被 git 忽略,所以自动暂存不会碰它们,网关更新期间数据库安然无恙。如果你在扁平安装的根目录放了别的未跟踪文件,最好挪出去或加进 .git/info/exclude;任何未跟踪又没被忽略的文件都会被当成源码改动卷进暂存。

但当更新没有终端时(比如桌面/聊天应用的“更新”按钮,或网关触发的更新),没有提示可回答。这时由 updates.non_interactive_local_changes 决定暂存的改动怎么处理:

# ~/.hermes/config.yaml
updates:
  non_interactive_local_changes: stash   # 默认:保留并自动恢复
  # non_interactive_local_changes: discard  # 丢弃本地源码改动
  • stash(默认)——自动暂存、拉取,然后自动把你的改动恢复到更新后的代码上。不会丢失;如果恢复时冲突,会保留在 git stash 里供手动恢复。
  • discard——自动暂存并在拉取后丢弃 stash,让更新总是落在干净的工作区上。只在你从不打算保留 Hermes 源码本地改动的机器上使用。它用的是 stash-drop(不是 git reset --hard + git clean -fd),所以 node_modulesvenv、构建产物等被忽略的路径永远不会被碰。

在桌面应用里,这个选项位于 Settings → Advanced → In-App Update Local Changes

桌面端更新从不自动恢复。 桌面更新器调用的是 hermes update --keep-stash:本地源码改动仍会被暂存以便更新进行,但之后不会重新应用——它们留在 git stash 里,更新日志会打印出恢复用的 git stash apply <ref> 命令。

卸载

(注:官方文档暂未提供卸载章节,建议直接删除安装目录和 HERMES_HOME 下的配置即可,后续文档更新会补充详细步骤。)


保持更新,让 Hermes 始终跑在最新状态,享受最好的体验!有问题随时回来翻翻文档,咱们下期见!🚀

📖 官方文档

本文根据 Hermes Agent 官方文档编写,原文见:官方文档 › getting-started/updating