Hermes Agent on Native Windows: A Deep Dive into the Early Beta Experience

Core Question: How can you install, configure, and run Hermes Agent natively on Windows 10/11 without the overhead of WSL, Cygwin, or Docker?

Hermes Agent now runs natively on Windows 10 and Windows 11. This is a significant shift for users who prefer a lean environment without the complexity of the Windows Subsystem for Linux (WSL). However, as an “Early Beta” release, it comes with caveats—specifically regarding subprocess handling and console output. This guide provides a comprehensive, technical deep dive into the native Windows implementation, detailing exactly what works, how the installer functions under the hood, and the specific adjustments required for a stable production experience.


1. The Strategic Value of Native Windows Support

Core Question: What are the functional trade-offs between running Hermes natively on Windows versus using the WSL2 version?

For many developers, WSL2 has become the default bridge between Windows and Linux environments. However, the native Windows version of Hermes eliminates the middleman, reducing resource overhead and simplifying file system interactions. It is designed for users who want the agent to integrate directly with their Windows workflow.

1.1 Feature Matrix: Native vs. WSL2

While the goal is feature parity, the underlying OS primitives differ. The table below outlines exactly what you get with the native version compared to the WSL2 installation.

Feature Native Windows Support WSL2 Support Notes
CLI Tools ✓ Full Support ✓ Full Support Includes hermes chat, setup, gateway.
Interactive TUI ✓ Full Support ✓ Full Support The --tui mode functions correctly.
Messaging Gateway ✓ Full Support ✓ Full Support Telegram, Discord, Slack, WhatsApp, etc.
Cron Scheduler ✓ Full Support ✓ Full Support
Browser Tool ✓ Full Support ✓ Full Support Chromium driven by Node.js.
MCP Servers ✓ Full Support ✓ Full Support Supports stdio and HTTP modes.
Local AI Models ✓ Full Support ✓ Full Support Ollama / LM Studio integration.
Web Dashboard ✓ Full Support ✓ Full Support Sessions, jobs, metrics views.
Dashboard Embedded Terminal ✗ Not Supported ✓ Supported Native Windows lacks POSIX PTY.
Auto-start at Login ✓ Supported ✓ Supported Native uses Task Scheduler; WSL uses systemd.

1.2 The Missing Piece: Dashboard Embedded Terminal

The only feature currently missing in the native build is the dashboard’s embedded terminal pane. This feature relies heavily on POSIX PTY (Pseudo-Terminal) primitives, which do not have a direct equivalent in the standard Windows API (ConPTY requires separate implementation logic).

Author’s Insight:
While the absence of the embedded terminal is a limitation, it is rarely a blocker for automation tasks. The web dashboard remains fully functional for monitoring. If your workflow relies heavily on a terminal multiplexer inside the web UI, WSL2 is the superior choice. Otherwise, the native version provides a cleaner, lighter experience.

Image Source: Unsplash


2. The Installation Mechanism: A Technical Breakdown

Core Question: What exactly happens to your system when you run the installation script?

Hermes adopts a “zero-dependency” installation philosophy. You do not need to pre-install Python, Node.js, or Git. The installer acts as a bootstrap, provisioning a self-contained environment that won’t conflict with your existing development tools.

2.1 Quick Install Command

Open PowerShell or Windows Terminal and execute:

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

This command requires no administrator rights. It deploys files to %LOCALAPPDATA%\hermes\ and modifies the User PATH variable.

Critical Step: You must close and reopen your terminal window after installation for the PATH changes to take effect.

2.2 The 10-Step Bootstrap Process

Understanding the installer’s logic is crucial for debugging. Here is the sequential breakdown of the operations performed:

  1. Bootstrapping uv: The script installs uv, Astral’s high-speed Python package manager, into %USERPROFILE%\.local\bin. This replaces the need for standard pip in many contexts and significantly speeds up dependency resolution.
  2. Installing Python 3.11: Using uv, Python 3.11 is installed. This is isolated from any system-wide Python installations.
  3. Installing Node.js 22: The script checks for winget. If available, it uses it; otherwise, it downloads a portable Node.js tarball and unpacks it to %LOCALAPPDATA%\hermes\node. Node.js is essential for the browser automation tool and WhatsApp bridge.
  4. Installing Portable Git: If git is not found on the system PATH, the script downloads a trimmed PortableGit (~45 MB). Crucially, this is a self-contained extraction—no registry modifications or admin rights are required, ensuring it doesn’t interfere with existing Git configurations.
  5. Cloning the Repository: The Hermes Agent code is cloned into %LOCALAPPDATA%\hermes\hermes-agent, and a virtual environment is created inside it.
  6. Tiered Dependency Installation: This is a robustness feature. The installer attempts to install the full dependency set .[all]. If GitHub rate limits cause a failure, it automatically falls back to smaller sets ([messaging,dashboard,ext] -> [messaging] -> .). This prevents a single flaky dependency from breaking the entire installation.
  7. Auto-Installing Messaging SDKs: The script intelligently detects tokens in your .env file (e.g., TELEGRAM_BOT_TOKEN). If found, it automatically runs pip install for the relevant SDKs, ensuring messaging platforms work immediately.
  8. Setting HERMES_GIT_BASH_PATH: To ensure stability, the installer explicitly sets this environment variable to the resolved path of bash.exe, preventing discovery issues in fresh shells.
  9. Updating User PATH: Adds %LOCALAPPDATA%\hermes\bin to the User PATH, exposing the hermes command globally.
  10. Running hermes setup: Launches the first-run wizard to configure your model provider and tools. This can be skipped with -SkipSetup if you are scripting the installation.

2.3 Advanced Configuration Parameters

For power users automating deployments, the installer accepts parameters via a scriptblock:

& ([scriptblock]::Create((irm https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.ps1))) -NoVenv -SkipSetup -Branch main
Parameter Default Purpose
-Branch main Clone a specific branch (useful for testing PRs).
-NoVenv Off Skip virtual environment creation (advanced).
-SkipSetup Off Skip the post-install wizard.
-HermesHome %LOCALAPPDATA%\hermes Override the default data directory.
-InstallDir ...\hermes-agent Override the code location.

3. Shell Command Execution Strategy on Windows

Core Question: How does Hermes execute shell commands on Windows, which lacks a native POSIX shell?

One of the biggest hurdles for Linux-centric tools on Windows is the absence of a standard Bash shell. Hermes solves this by routing terminal tool commands through Git Bash, mirroring the strategy used by tools like Claude Code. This avoids the need to rewrite tool logic for PowerShell syntax.

3.1 The bash.exe Resolution Order

Hermes employs a hierarchical search to locate a valid Bash executable. This ensures it works whether you use the bundled PortableGit or a system-wide installation.

  1. Environment Variable: Check HERMES_GIT_BASH_PATH if explicitly set.
  2. Bundled PortableGit: Check %LOCALAPPDATA%\hermes\git\usr\bin\bash.exe.
  3. Legacy Layout: Check %LOCALAPPDATA%\hermes\git\bin\bash.exe.
  4. System Git: Check standard paths like %ProgramFiles%\Git\bin\bash.exe.
  5. Fallback: Scan PATH for MSYS2, Cygwin, or other bash.exe instances.

Author’s Reflection:
This resolution logic is a testament to practical engineering. Instead of forcing users to configure paths manually, it gracefully degrades from the most controlled environment (the bundled portable version) to the system environment. However, if you choose to use a manual MinGit zip, be careful: select the non-busybox variant (MinGit-*-64-bit.zip). The busybox versions ship with ash instead of bash, which will break compatibility.


4. Handling UTF-8 and Console Encoding

Core Question: Why do special characters crash some CLI tools on Windows, and how does Hermes prevent it?

Windows console encoding is historically notorious. By default, Windows consoles often use legacy code pages (like cp1252 or cp437), which cannot handle Unicode characters (Emojis, Chinese characters, etc.) commonly found in modern CLI interfaces.

4.1 The Automated Fix

Hermes intercepts this issue early in the startup process via hermes_cli/stdio.py::configure_windows_stdio(). This function executes a four-step protocol:

  1. Switch Code Page: It calls kernel32.SetConsoleCP to force the console to CP_UTF8 (65001).
  2. Reconfigure Stdio: It wraps sys.stdout, sys.stderr, and sys.stdin to explicitly use UTF-8 encoding with errors='replace'.
  3. Subprocess Inheritance: It sets PYTHONIOENCODING=utf-8 and PYTHONUTF8=1 so that any child Python processes also inherit the correct encoding.
  4. Default Editor: It defaults EDITOR to notepad if unset.

4.2 Troubleshooting Encoding Issues

If you see question marks ? or boxes for non-ASCII characters:

  • Check Environment: Ensure HERMES_DISABLE_WINDOWS_UTF8 is NOT set to 1.
  • Terminal Choice: Legacy cmd.exe has poor UTF-8 support. Upgrading to Windows Terminal is strongly recommended for a seamless experience.

5. Editor Integration and Multi-line Input

Core Question: How can you use advanced editors like VS Code for multi-line input in the Hermes CLI?

In Linux/Unix environments, the shortcut Ctrl-X Ctrl-E typically opens the default editor for composing complex commands. On Windows, this previously failed because underlying libraries (like prompt_toolkit) hardcoded POSIX paths (/usr/bin/vi).

5.1 Configuring VS Code

Hermes now defaults to notepad if no editor is set, which works but is basic. For a professional workflow, configure VS Code.

Run this in PowerShell to set it for the current session:

$env:EDITOR = "code --wait"

Why --wait?
This flag is critical. Without it, VS Code will open the file and immediately return control to Hermes, which would then try to read an empty buffer. --wait forces the CLI to pause until you close the editor tab.

To make this permanent, add the line above to your PowerShell $PROFILE script.

5.2 Ctrl+Enter Support

Modern Windows terminals (Windows Terminal, VS Code Integrated Terminal) support Ctrl+Enter as a distinct key sequence. Hermes binds this to “Insert Newline,” allowing you to type multi-line prompts naturally without resorting to Esc-then-Enter.


6. Process Management: Gateway Service on Windows

Core Question: How does Hermes achieve background operation on Windows without using Windows Services?

Users often want the Hermes Gateway to run silently in the background and start automatically when they log in. On Linux, systemd handles this. On Windows, Hermes uses Scheduled Tasks.

6.1 Why Not a Windows Service?

Windows Services run at the machine level (before login) and require Administrator privileges for installation. Hermes is designed as a user-space tool. Scheduled Tasks with an ONLOGON trigger perfectly match the requirement: “Start when I log in, stop when I log out,” all without UAC prompts.

6.2 Management Commands

To install the gateway service:

hermes gateway install

Under the hood, this executes schtasks /Create /SC ONLOGON /RL LIMITED. If Group Policy blocks scheduled tasks, it gracefully falls back to placing a shortcut in the Windows Startup folder.

Management Utilities:

hermes gateway status    # View status (Task Scheduler + Startup + PID)
hermes gateway start     # Start the task
hermes gateway stop      # Graceful stop
hermes gateway uninstall # Remove the task

6.3 The “Footgun” Internals

Author’s Note on Process Management:
Developers debugging Windows processes should be aware of a classic Python pitfall. The POSIX idiom os.kill(pid, 0) is used to check if a process is alive. On Windows, Python maps signal 0 to CTRL_C_EVENT. This doesn’t just check the PID; it broadcasts a Ctrl+C signal to the entire console process group, potentially killing unrelated processes sharing the console. Hermes mitigates this by migrating all checks to psutil.pid_exists(). If you are extending Hermes, never use os.kill(pid, 0) on Windows.


7. Data Layout and Uninstallation

Core Question: Where does Hermes store its files, and how do I cleanly remove it?

Understanding the directory structure is vital for backup strategies.

7.1 Directory Structure

Path Contents Persistence
%LOCALAPPDATA%\hermes\hermes-agent\ Git repo & Virtualenv. Disposable. Can be deleted and reinstalled.
%LOCALAPPDATA%\hermes\git\ Portable Git. Disposable. Managed by installer.
%LOCALAPPDATA%\hermes\node\ Portable Node.js. Disposable. Managed by installer.
%USERPROFILE%\.hermes\ User Data: Config, Auth, Skills, Logs. Persistent. Survives reinstalls.

The split between %LOCALAPPDATA% (infrastructure) and %USERPROFILE% (data) ensures that your configuration and memories are never lost during an upgrade or reinstallation.

7.2 Uninstallation

To uninstall the application binaries:

hermes uninstall

To completely wipe all traces (including your configuration), manually remove the data directories:

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

8. Browser Tool & Practical Troubleshooting

Core Question: What are the most common errors encountered during setup, and how are they resolved?

8.1 Browser Tool Architecture

The browser tool uses agent-browser, a Node.js helper. On Windows, CreateProcessW cannot execute extensionless shebang scripts directly. Hermes resolves this by always invoking the .CMD wrapper generated by npm.

8.2 Common Pitfalls & Solutions

1. hermes: command not found after install.

  • Cause: The PATH update hasn’t propagated to your current terminal session.
  • Solution: Close the terminal and open a new one. Do not manually append to $env:PATH.

2. WinError 193: %1 is not a valid Win32 application.

  • Cause: Attempting to run a Node script directly without the .cmd shim.
  • Solution: Ensure you are invoking npx.cmd rather than npx if calling manually. Hermes handles this internally via shutil.which.

3. Gateway cannot send Telegram photos (“Invalid characters”).

  • Cause: Unescaped Windows backslashes in JSON payloads within custom plugins.
  • Solution: Ensure your plugins use Hermes-normalized paths, not raw str(Path(...)) outputs from user input, which may contain unescaped backslashes.

4. Weird encoding issues after git pull.

  • Cause: Files edited in legacy Notepad or certain IMEs may have been saved with a UTF-8 BOM (Byte Order Mark).
  • Solution: Re-save files as “UTF-8 without BOM” using an editor like VS Code.

9. Practical Summary & Checklist

9.1 Deployment Checklist

  1. Environment: Ensure you are on Windows 10 or 11.
  2. Install: Run irm ... | iex in PowerShell.
  3. Refresh: Restart terminal. Verify with hermes --version.
  4. Configure: Run hermes setup to input API keys.
  5. Service: Run hermes gateway install for background operation.
  6. Editor (Optional): Set $env:EDITOR = "code --wait" in your profile.

9.2 One-Page Summary

  • Status: Early Beta. Core CLI and Gateway functions are stable.
  • Installation: Zero-dependency, no admin rights required. Uses Portable Python/Node/Git.
  • Shell: Bridges commands via Git Bash for POSIX compatibility.
  • Encoding: Auto-configures Console to UTF-8 (Code Page 65001).
  • Service: Utilizes Task Scheduler (User scope) instead of Windows Services.
  • Key Warning: Avoid os.kill(pid, 0) in custom plugins; use psutil.

Frequently Asked Questions (FAQ)

Q1: Do I need to install Python or Node.js manually before running the Hermes installer?
No. The Hermes installer includes a bootstrap process that automatically installs isolated versions of Python 3.11 and Node.js 22. It will not interfere with your system-wide installations.

Q2: Why is the embedded terminal in the Dashboard missing on Native Windows?
The embedded terminal requires POSIX PTY (Pseudo-Terminal) primitives, which are native to Unix-like systems. Windows has a different terminal architecture (ConPTY). Full support for this specific feature is planned for future updates; currently, it is only available via the WSL2 installation.

Q3: I ran the installer, but the hermes command is not recognized. What did I miss?
The installer adds hermes to your User PATH environment variable. Existing terminal windows do not automatically refresh this variable. You must close your current PowerShell window and open a brand new one to recognize the command.

Q4: How do I set up VS Code as my editor for multi-line input?
In your PowerShell profile ($PROFILE), add the line: $env:EDITOR = "code --wait". The --wait parameter is essential; it ensures Hermes waits for you to save and close the file in VS Code before proceeding.

Q5: My output is showing strange characters or question marks. How do I fix encoding?
Hermes attempts to force UTF-8 encoding automatically. If issues persist, verify that the environment variable HERMES_DISABLE_WINDOWS_UTF8 is not set to 1. Additionally, switching from the legacy cmd.exe to the modern Windows Terminal application usually resolves display issues.

Q6: Why does Hermes use Scheduled Tasks instead of a Windows Service for the Gateway?
Windows Services run at the machine level and require Administrator privileges. Hermes is designed to run at the user level. Scheduled Tasks allow the agent to start when you log in and stop when you log out, which fits the typical usage pattern better and avoids UAC prompts.

Q7: How can I completely uninstall Hermes from my system?
Run the command hermes uninstall. This removes the binaries and scheduled tasks. To delete your configuration and data, you must also manually delete the folder %USERPROFILE%\.hermes and %LOCALAPPDATA%\hermes.

Q8: I am getting a “WinError 193” when using tools. What causes this?
This error typically occurs when Windows tries to execute a script intended for Linux/Unix (like an extensionless Node script) directly. Hermes mitigates this by using .cmd shims. If you are writing custom plugins, ensure you are not bypassing these shims by hardcoding paths to script files instead of the command names.