Windows(原生)指南——早期 Beta

:::warning 早期 Beta Windows 原生支持是早期 beta。它可以安装、运行并通过了我们的 Windows-footgun lint,但尚未经过像 Linux/macOS/WSL2 路径那样的规模测试。预计会有粗糙的边缘——特别是在子进程处理、路径 quirks 和非 ASCII 控制台输出方面。遇到问题时请提交 issue 并附上复现步骤。如果你今天需要一个经过实战考验的设置,请改用 macOS 安装程序。 :::

Hermes 可在 Windows 10 和 Windows 11 上原生运行——无需 WSL、无需 Cygwin、无需 Docker。本页是深入指南:哪些功能原生可用、哪些是 WSL 专属、安装程序实际做了什么,以及你可能需要调整的 Windows 特定设置。

如果你只是想安装,主页安装页面上的命令就足够了。当出现意外时再回来查阅。

:::tip 想要 WSL? 如果你更喜欢真正的 POSIX 环境(用于仪表盘的嵌入式终端、fork 语义、Linux 风格的文件监视器等),请参阅 Windows(WSL2)指南。两者可以共存:原生数据在 %LOCALAPPDATA%\\hermes 下,WSL 数据在 ~/.hermes 下。 :::

快速安装

打开 PowerShell(或 Windows Terminal)并运行:

iex (irm https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.ps1)

无需管理员权限。安装程序会将文件放到 %LOCALAPPDATA%\\hermes\\,并将 hermes 添加到你的用户 PATH——完成后打开一个新的终端。

安装程序选项(需要使用脚本块形式传递参数):

& ([scriptblock]::Create((irm https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.ps1))) -NoVenv -SkipSetup -Branch main
参数默认值用途
-Branchmain克隆特定分支(用于测试 PR)
-Commit未设置固定安装到特定 commit SHA(覆盖 -Branch
-Tag未设置固定安装到特定 git 标签(例如 v0.14.0
-NoVenv关闭跳过虚拟环境创建(高级——你自己管理 Python)
-SkipSetup关闭跳过安装后的 hermes setup 向导
-HermesHome%LOCALAPPDATA%\\hermes覆盖数据目录
-InstallDir%LOCALAPPDATA%\\hermes\\hermes-agent覆盖代码位置

安装程序会自动重试不稳定的 git 拉取,并从任何下载的 install.ps1 负载中剥离 BOM,因此在 HTTP 传输过程中获取的 UTF-8 BOM 不再破坏 [scriptblock]::Create((irm ...)) 形式。

桌面安装程序(备选)

还有一个精简的 GUI 安装程序——如果你更愿意双击 .exe 而不是打开 PowerShell,这很有用。下载 Hermes Desktop,运行安装程序,首次启动时 GUI 在底层调用 install.ps1 来通过 uv 配置 Python、Node、PortableGit 以及下面描述的其他依赖引导程序。首次运行后,桌面应用和 PowerShell 安装的 hermes CLI 共享相同的 %LOCALAPPDATA%\\hermes\\hermes-agent 安装和 %USERPROFILE%\\.hermes 数据目录——在 GUI 和 CLI 之间自由切换。

当你想要熟悉的 Windows 安装体验或将 Hermes 交给非开发人员时,使用桌面安装程序;当你已经在终端中时,使用 PowerShell 命令。

依赖引导(dep_ensure

首次启动时(以及在检测到缺少工具时按需),Hermes 运行一个小的 Python 引导程序——hermes_cli/dep_ensure.py——检查并延迟安装它所需的非 Python 依赖。在 Windows 上,相关依赖包括:

依赖Hermes 为什么需要它
PortableGit为终端工具提供 bash.exe 和为会话内克隆提供 git。在安装时配置,不由 dep_ensure 处理。
Node.js 22浏览器工具(agent-browser)、TUI 的 Web 桥接和 WhatsApp 桥接所需。
ffmpegTTS / 语音消息的音频格式转换。
ripgrep快速文件搜索——如果不可用则回退到 grep
npm 包agent-browser、Playwright Chromium 以及每个工具集的 Node 依赖在首次使用浏览器工具时安装一次。

每个依赖都有 shutil.which(...) 风格的检查;如果某个二进制文件丢失且运行是交互式的,dep_ensure 会提供安装选项(将实际安装逻辑委托给 scripts\install.ps1 -ensure <dep>)。非交互式运行(网关、cron、无头桌面启动)会跳过提示,改为显示清晰的 this feature needs <dep> 错误。

安装程序实际做了什么

从上到下,按顺序:

  1. 引导 uv——Astral 的快速 Python 管理器。安装到 %USERPROFILE%\\.local\\bin
  2. 通过 uv 安装 Python 3.11。无需现有 Python。
  3. 安装 Node.js 22(如果可用则使用 winget,否则在 %LOCALAPPDATA%\\hermes\\node 下解压可移植的 Node tarball)。用于浏览器工具和 WhatsApp 桥接。
  4. 安装可移植 Git——如果 git 已在 PATH 上,安装程序会直接使用;否则它下载一个精简的、自包含的 PortableGit(约 45 MB,来自官方的 git-for-windows 发行版)到 %LOCALAPPDATA%\\hermes\\git。无需管理员权限,无需 Windows 安装程序注册表,不会与机器上的其他任何东西冲突。
  5. 克隆仓库%LOCALAPPDATA%\\hermes\\hermes-agent 并在其中创建一个虚拟环境。
  6. 分层 uv pip install——首先尝试 .[all],如果 git+https 依赖在 GitHub 上因速率限制不稳定,则逐步回退到较小的集合([messaging,dashboard,ext][messaging].)。防止”单个不稳定依赖导致安装到最精简层级”的故障模式。
  7. 根据 .env 自动安装消息 SDK——如果存在 TELEGRAM_BOT_TOKEN / DISCORD_BOT_TOKEN / SLACK_BOT_TOKEN / SLACK_APP_TOKEN / WHATSAPP_ENABLED,则运行 python -m ensurepip --upgrade 和针对性的 pip install 调用,使每个平台的 SDK 真正可导入。
  8. 设置 HERMES_GIT_BASH_PATH 为解析到的 bash.exe,使 Hermes 在新 shell 中确定性地找到它。
  9. %LOCALAPPDATA%\\hermes\\bin 添加到用户 PATH——让你在打开新终端后可以使用 hermes 命令。
  10. 运行 hermes setup——正常的首次运行向导(模型、提供商、工具集)。使用 -SkipSetup 可跳过。

功能矩阵

除了仪表盘的内嵌终端面板外,所有功能都在 Windows 上原生运行。

功能Windows 原生WSL2
CLI(hermes chathermes setuphermes gateway 等)
交互式 TUI(hermes --tui
消息网关(Telegram、Discord、Slack、WhatsApp、15+ 平台)
定时调度器
浏览器工具(通过 Node 使用 Chromium)
MCP 服务器(stdio 和 HTTP)
本地 Ollama / LM Studio / llama-server✓(通过 WSL 网络)
Web 仪表盘(会话、任务、指标、配置)
仪表盘 /chat 嵌入式终端面板✗(需要 POSIX PTY)
登录时自动启动✓(schtasks)✓(systemd)

仪表盘的 /chat 标签通过 POSIX PTY(ptyprocess)嵌入一个真正的终端。Windows 原生没有等效的原语;Python 的 pywinpty / Windows ConPTY 可以工作但需要单独实现——作为未来工作处理。仪表盘的其他部分原生工作——只有那一个标签显示”请使用 WSL2”的横幅。

Hermes 如何在 Windows 上运行 shell 命令

Hermes 的终端工具通过 Git Bash 运行命令,与 Claude Code 使用的策略相同。这绕过了 POSIX vs Windows 的差距,而无需重写每个工具。

bash.exe 的解析顺序:

  1. 如果设置了 HERMES_GIT_BASH_PATH 环境变量,则使用。
  2. %LOCALAPPDATA%\\hermes\\git\\usr\\bin\\bash.exe(安装程序管理的 PortableGit)。
  3. %LOCALAPPDATA%\\hermes\\git\\bin\\bash.exe(较旧的 Git-for-Windows 布局)。
  4. 系统 Git-for-Windows 安装(%ProgramFiles%\\Git\\bin\\bash.exe 等)。
  5. MSYS2、Cygwin 或 PATH 上的任何 bash.exe 作为最后手段。

安装程序显式设置 HERMES_GIT_BASH_PATH,因此新的 PowerShell 会话不必重新发现。如果你希望 Hermes 使用特定的 bash,可以覆盖它——例如你的系统 Git Bash 或通过符号链接的 WSL 托管的 bash。

陷阱: MinGit 的布局与完整的 Git-for-Windows 安装程序不同——bash 位于 usr\\bin\\bash.exe,而不是 bin\\bash.exe。Hermes 会检查两者。如果你手动解压 MinGit zip,确保选择的是非 busybox 变体(MinGit-*-64-bit.zip,而不是 MinGit-*-busybox*.zip)——busybox 构建提供的是 ash 而不是 bash,且大多数核心工具缺失。

Windows 上的 UTF-8 控制台

Python 在 Windows 上的默认 stdio 使用控制台的活动代码页(通常是 cp1252 或 cp437)。Hermes 的横幅、斜杠命令列表、工具反馈、Rich 面板和技能描述都包含 Unicode。如果不加处理,任何这些都会崩溃并显示 UnicodeEncodeError: 'charmap' codec can't encode character…

修复位于 hermes_cli/stdio.py::configure_windows_stdio() 中,在每个入口点(cli.py::mainhermes_cli/main.py::maingateway/run.py::main)早期调用。它:

  1. 通过 kernel32.SetConsoleCP / SetConsoleOutputCP 将控制台代码页切换到 CP_UTF8(65001)。
  2. 重新配置 sys.stdout / sys.stderr / sys.stdin 为 UTF-8,带 errors='replace'
  3. 设置 PYTHONIOENCODING=utf-8PYTHONUTF8=1(通过 setdefault,因此用户显式值优先),使子 Python 进程继承 UTF-8。
  4. 如果既未设置 EDITOR 也未设置 VISUAL,则设置 EDITOR=notepad(见下面的编辑器部分)。

幂等。在非 Windows 系统上无操作。

选择退出: 环境中设置 HERMES_DISABLE_WINDOWS_UTF8=1 回退到传统的 cp1252 stdio 路径。用于定位编码 bug;正常操作中不太可能需要。

编辑器(Ctrl-X Ctrl-E/edit

在 #21561 之前,在 Windows 上按 Ctrl-X Ctrl-E 或输入 /edit 会静默地什么都不做。prompt_toolkit 有一个硬编码的 POSIX 绝对回退列表(/usr/bin/nano/usr/bin/pico/usr/bin/vi 等),在 Windows 上永远无法解析——即使安装了完整的 Git for Windows。

Hermes 的 Windows stdio shim 现在默认设置 EDITOR=notepad。Notepad 随每个 Windows 安装提供,并可作为阻塞编辑器工作——subprocess.call(["notepad", file]) 在窗口关闭前一直阻塞。

用户覆盖仍然优先(它们在 setdefault 之前被检查):

编辑器PowerShell 命令
VS Code$env:EDITOR = "code --wait"
Notepad++$env:EDITOR = "'C:\\Program Files\\Notepad++\\notepad++.exe' -multiInst -nosession"
Neovim$env:EDITOR = "nvim"
Helix$env:EDITOR = "hx"

VS Code 上的 --wait 标志至关重要——没有它,编辑器会立即返回,Hermes 会收到一个空白缓冲区。

在你的 PowerShell 配置文件中永久设置:

# 在 $PROFILE 中
$env:EDITOR = "code --wait"

或者作为系统设置中的用户环境变量,以便每个新 shell 都能获取到。

CLI 中的 Ctrl+Enter 换行

Windows Terminal 将 Ctrl+Enter 作为专用键序列传递。Hermes 将其绑定为”插入换行符”,因此你可以在 CLI 中编写多行提示词,而无需回退到 EscEnter。在 Windows Terminal、VS Code 集成终端以及任何遵循 VT 转义序列的现代 Windows 控制台主机中均可使用。

在传统的 cmd.exe 控制台上,Ctrl+Enter 会退化为普通 Enter——改用 Esc Enter,或升级到 Windows Terminal(免费,Windows 11 默认安装)。

在 Windows 登录时运行网关

Windows 上的 hermes gateway install 使用计划任务,并回退到启动文件夹——无需管理员权限。

安装

hermes gateway install

底层执行的操作:

  1. schtasks /Create /SC ONLOGON /RL LIMITED /TN HermesGateway——注册一个任务,在登录时以标准(非提升)权限运行。无 UAC 提示。
  2. 如果 schtasks 被组策略阻止,回退到在 %APPDATA%\\Microsoft\\Windows\\Start Menu\\Programs\\Startup 中写入一个 start /min cmd.exe /d /c <wrapper> 快捷方式。效果相同,稍显粗糙。
  3. 通过 pythonw.exe 分离生成网关——而不是 python.exepythonw.exe 没有附加控制台,这使其免疫于来自兄弟进程的 CTRL_C_EVENT 广播(一个真实存在的问题,过去当你 Ctrl+C 同一进程组中的任何内容时,会杀死网关)。

生成时使用的标志:DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP | CREATE_NO_WINDOW | CREATE_BREAKAWAY_FROM_JOB

管理

hermes gateway status      # 合并视图:schtasks + 启动文件夹 + 运行中的 PID
hermes gateway start       # 立即启动计划任务
hermes gateway stop        # 优雅的 SIGTERM 等价(通过 psutil 的 TerminateProcess)
hermes gateway restart
hermes gateway uninstall   # 移除 schtasks 条目、启动文件夹快捷方式、pid 文件

hermes gateway status 是幂等的——连续调用一千次也永远不会意外杀死网关。(在 PR #21561 之前,它通过 os.kill(pid, 0) 在 C 级别与 CTRL_C_EVENT 冲突而静默地杀死——如果你关心这个故事,请参见下面的”进程管理内部机制”。)

为什么不是 Windows 服务?

服务需要管理员权限才能安装,并将网关的生命周期绑定到机器启动,而非用户登录。典型的 Hermes 用户想要的是:登录 → 网关可用,注销 → 网关消失。计划任务完全可以做到这一点,无需提升权限。如果你真的想要一个服务,可以手动使用 nssmsc create——但你可能不需要。

数据布局

路径内容
%LOCALAPPDATA%\\hermes\\hermes-agent\\Git 检出 + 虚拟环境。可以安全地 Remove-Item -Recurse 并重新安装。
%LOCALAPPDATA%\\hermes\\git\\PortableGit(仅在安装程序配置时存在)。
%LOCALAPPDATA%\\hermes\\node\\可移植 Node.js(仅在安装程序配置时存在)。
%LOCALAPPDATA%\\hermes\\bin\\hermes.cmd shim,添加到用户 PATH。
%USERPROFILE%\\.hermes\\你的配置、认证、技能、会话、日志。在重新安装后保留。

这种拆分是有意的:%LOCALAPPDATA%\\hermes 是可丢弃的基础设施(你可以删除它,命令会重新创建)。%USERPROFILE%\\.hermes 是你的数据——配置、记忆、技能、会话历史——与 Linux 安装形状相同。在机器之间镜像它,你的 Hermes 就随你移动。

覆盖 HERMES_HOME 设置环境变量指向不同的数据目录。与 Linux 上的工作方式相同。

浏览器工具

浏览器工具使用 agent-browser(一个 Node 辅助程序)来驱动 Chromium。在 Windows 上:

  • 安装程序通过 npm 将 agent-browser 放在 PATH 上。
  • shutil.which("agent-browser", path=...) 自动拾取 .cmd shim——CreateProcessW 无法执行无扩展名的 shebang,因此 Hermes 总是解析到 .CMD 包装器。不要手动调用 shebang 脚本;始终通过 .cmd
  • Playwright Chromium 在首次运行时自动安装(npx playwright install chromium)。如果安装失败,hermes doctor 会显示它并提供一个修复提示。

在 Windows 上运行 Hermes——实用说明

安装后的 PATH

安装程序通过 [Environment]::SetEnvironmentVariable%LOCALAPPDATA%\\hermes\\bin 添加到你的用户 PATH。现有的终端不会获取到此更改——安装后打开一个新的 PowerShell 窗口(或 Windows Terminal 标签)。关闭并重新打开,不要手动 $env:PATH += …,除非你知道自己在做什么。

验证:

Get-Command hermes        # 应打印 C:\Users\<you>\AppData\Local\hermes\bin\hermes.cmd
hermes --version

环境变量

Hermes 同时遵循 $env:X(进程范围)和用户环境变量(永久的,在系统属性 → 环境变量中设置)。在 %USERPROFILE%\\.hermes\\.env 中设置 API 密钥是正常路径——与 Linux 相同:

OPENROUTER_API_KEY=sk-or-...
TELEGRAM_BOT_TOKEN=...

不要将密钥放在用户环境变量中,除非你特别希望每个 Windows 进程都能看到它们(这不是你想要的)。

Windows 特定环境变量

这些仅影响 Windows 原生安装:

变量效果
HERMES_GIT_BASH_PATH覆盖 bash.exe 发现。指向任何 bash——完整的 Git-for-Windows、通过符号链接的 WSL bash、MSYS2、Cygwin。安装程序自动设置此变量。
HERMES_DISABLE_WINDOWS_UTF8设置为 1 以禁用 UTF-8 stdio shim 并回退到区域设置代码页。用于定位编码 bug。
EDITOR / VISUAL用于 /editCtrl-X Ctrl-E 的编辑器。如果两者都未设置,Hermes 默认使用 notepad

卸载

从 PowerShell:

hermes uninstall

这是干净的方式——移除 schtasks 条目、启动文件夹快捷方式、hermes.cmd shim,删除 %LOCALAPPDATA%\\hermes\\hermes-agent\\,并修剪用户 PATH。它保留 %USERPROFILE%\\.hermes\\(你的配置、认证、技能、会话、日志)以防你重新安装。

要彻底删除所有内容:

hermes uninstall
Remove-Item -Recurse -Force "$env:USERPROFILE\.hermes"
Remove-Item -Recurse -Force "$env:LOCALAPPDATA\hermes"

hermes uninstall CLI 子命令还处理了 schtasks 条目以不同任务名称注册的情况(旧安装)——它按安装路径搜索,而非硬编码的任务名称。

进程管理内部机制

这是背景资料——除非你在调试”它自杀了”的怪异问题,否则跳过。

在 Linux 和 macOS 上,POSIX 习惯用法 os.kill(pid, 0) 是一个无操作权限检查:“这个 PID 还活着吗,我能给它发信号吗?“在 Windows 上,Python 的 os.killsig=0 映射到 CTRL_C_EVENT——它们在整数值 0 处冲突——并通过 GenerateConsoleCtrlEvent(0, pid) 路由,将 Ctrl+C 广播到包含目标 PID 的整个控制台进程组。这是 bpo-14484,自 2012 年以来一直开放。它不会被修复,因为更改它会破坏依赖当前行为的脚本。

后果:任何在 Windows 上通过 os.kill(pid, 0) 执行”检查此 PID 是否存活”的代码路径都会静默杀死目标。Hermes 将每个这样的站点(11 个文件中的 14 处)迁移到了 gateway.status._pid_exists(),后者使用 psutil.pid_exists()(在 Windows 上又使用 OpenProcess + GetExitCodeProcess——无信号)。如果你在编写插件或补丁,请直接使用 psutil.pid_exists()gateway.status._pid_exists()——绝不要使用 os.kill(pid, 0)

scripts/check-windows-footguns.py 在 CI 中强制执行此规则:任何新的 os.kill(pid, 0) 调用都会导致 Windows footguns (blocking) 检查失败,除非该行带有 # windows-footgun: ok — <reason> 标记。

常见陷阱

安装后立即出现 hermes: command not found 打开一个新的 PowerShell 窗口。安装程序将 %LOCALAPPDATA%\\hermes\\bin 添加到用户 PATH,但现有 shell 需要重新启动才能获取。在此期间,你可以运行 & "$env:LOCALAPPDATA\\hermes\\bin\\hermes.cmd"

运行工具时出现 WinError 193: %1 is not a valid Win32 application 你遇到了绕过 .cmd shim 的 shebang 脚本调用。Hermes 通过 shutil.which(cmd, path=local_bin) 解析命令,以便 PATHEXT 拾取 .CMD——如果你通过硬编码路径调用工具,请改用 .cmd 变体(例如 npx.cmd,而不是 npx)。

[scriptblock]::Create(...) 失败,显示 The assignment expression is not valid 你下载的 install.ps1 获取到了 UTF-8 BOM。irm | iex 形式会自动剥离 BOM;[scriptblock]::Create((irm ...)) 不会。重新运行简单的 irm | iex 形式,或手动下载脚本并通过 [IO.File]::WriteAllText($path, $text, (New-Object Text.UTF8Encoding $false)) 以无 BOM 方式保存。

网关在重启后无法保持运行。 检查 hermes gateway status——它合并了 schtasks 条目、启动文件夹快捷方式(如果使用)和实时 PID。如果 schtasks 已注册但未运行,组策略可能阻止了 ONLOGON 触发器。运行 schtasks /Query /TN HermesGateway /V /FO LIST 查看任务的失败原因,或通过卸载并重新安装并设置 HERMES_GATEWAY_FORCE_STARTUP=1 回退到启动文件夹路径。

设置 $env:EDITOR/edit 仍然无反应。 你只在当前进程中设置了它;关闭并重新打开 shell,或在系统属性 → 环境变量中设置为用户范围。在新的 PowerShell 窗口中用 echo $env:EDITOR 验证。

浏览器工具启动但工具超时。 Chromium 在首次运行时自动安装。如果安装失败(GitHub 速率限制、Playwright CDN 问题),运行 hermes doctor——它会显示缺少的 Chromium 并打印确切的 npx playwright install chromium 命令来修复。

agent-browser 因奇怪的 Node 版本错误失败。 安装程序在 %LOCALAPPDATA%\\hermes\\node 配置了 Node 22,但你的 PATH 可能首先有一个更旧的系统 Node 18。要么将 Hermes 的 node 目录移到 PATH 更靠前的位置,要么删除系统安装(如果你不在其他地方使用 Node)。

中文 / 日文 / 阿拉伯字符在 CLI 中显示为 ? UTF-8 stdio shim 未激活。检查是否设置了 HERMES_DISABLE_WINDOWS_UTF8Get-ChildItem env:HERMES_DISABLE_WINDOWS_UTF8)。如果它是空的且你仍然看到 ?,控制台主机(非常旧的 cmd.exe)可能根本不支持 UTF-8——切换到 Windows Terminal。

网关无法发送 Telegram 图片——“BadRequest: payload contains invalid characters”。 这与 Windows 无关,但有时首先在这里出现。通常意味着你的文件路径在 JSON 正文中包含未转义的反斜杠。Telegram 应该接收 Hermes 规范化的路径,而不是原始的 Windows 路径——如果你在自定义插件中看到这个,确保传递的是 Hermes 提供的路径,而不是来自用户输入的 str(Path(...))

git pull 后出现”在我的另一台机器上能工作”的编码怪异问题。 如果你在 Windows 上使用非 UTF-8 编辑器(旧版 Windows 上的记事本、某些中文输入法)编辑了 Hermes 配置或技能,文件可能已用 BOM 保存。Hermes 在大多数配置读取上容忍 utf-8-sig,但折叠的 YAML 标量(description: >)内部的 BOM 会静默破坏 YAML 解析。将文件重新保存为不带 BOM 的纯 UTF-8。

接下来去哪里

  • 安装——完整安装页面,包括 Linux/macOS/WSL2/Termux。
  • Windows(WSL2)指南——如果你想要 POSIX 语义或仪表盘终端面板。
  • CLI 参考——每个 hermes 子命令。
  • FAQ——常见的非 Windows 特定问题。
  • 消息网关——在 Windows 上运行 Telegram/Discord/Slack。