Hermes is an agent for one person. The credentials, the memory, the sessions and the cron jobs all belong to that person. But the only declarative path was a NixOS system service. Issue #9056 asks for the user-level equivalent. 25 public Nix configurations already write one by hand, and several of them copy nix/nixosModules.nix and edit the systemd part. This module is not a second copy of that file. The code that both modules share moves into nix/moduleCommon.nix: - the options - the renderers for config.yaml, .env and the documents - the activation body - the command lines of the processes nixosModules.nix keeps only the parts that need root. Those parts are the service user, stateDir, addToSystemPackages, container mode and tmpfiles. The file goes from 1008 lines to 666. `services.hermes-agent` is now the same option set on both modules. A NixOS example works on Home Manager without a change, and an option added one time appears on both. The Home Manager module is different only where it must be. It uses systemd.user.services on Linux and launchd.agents on Darwin. It uses home.activation and not system.activationScripts. It sets HERMES_HOME directly, with the default ~/.hermes, so an existing directory continues to work. It uses the modes 0600 and 0700, because the state has one user and does not need the group-shared umask of the NixOS module. It does not support container mode, which needs root and the Docker socket. The change also makes four corrections that apply to both modules: - backend.mode runs `hermes serve` or `hermes dashboard`. Both modules had only the gateway. But Hermes Desktop and the web dashboard connect to a different process, so six of the configurations in public repos add a second unit by hand. serve and dashboard are one entry point with one flag of difference, and you can run only one of them. Thus the option is an enum. The NixOS module asserts against container mode with a backend, and does not make a unit that cannot start. - hermesHomeFiles installs files into HERMES_HOME. The `documents` option installs into the working directory, which is correct for AGENTS.md but wrong for SOUL.md and memories/. Hermes reads those files from HERMES_HOME, in agent/prompt_builder.py:2095. A SOUL.md in `documents` made a workspace file that Hermes never loaded as the identity. The documentation said this in prose, but two directory diagrams showed the opposite. This change corrects both. A key in either option can now contain subdirectories. - `documents` needs an explicit `workingDirectory`. The default of that option is bad on both modules. It is the home directory of the user on Home Manager, and ${stateDir}/workspace on NixOS. A user who declares workspace files without a directory therefore gets a place that the user did not select. The place is also different on each module. The modules now refuse that combination. The test is on the priority of the option and not on its value. An option that nothing sets keeps the priority of its own default, and each definition from a user is stronger. Thus a directory with the same text as the default still counts as a selection, and so does a mkDefault. A comparison of values detects neither case. - Each activation writes .env again from a base in the Nix store, and does not add to the file that exists. Thus a second activation cannot put the same secret in the file two times, and a removed environmentFile goes away. environmentFiles keeps the type `listOf str` and not `path`, so Nix cannot copy a sops-nix or agenix path into the Nix store, which all users can read. - HERMES_MANAGED and the .managed marker now hold the name of the system that manages the install. Thus a refusal says "managed by home-manager" and not "managed by NixOS", and `hermes update` gives the Nix guidance for both shapes. The CLI does not print a rebuild command for each system. It names the owner, and the user knows their own tool. A bare `true` and an empty marker still mean NixOS, so this does not change an existing install. Verification. Six new checks, all built: nixos-module evaluates the module with evalModules and the NixOS module list. It asserts both units, one HERMES_HOME, and that the module refuses container mode with a backend. home-manager-module evaluates the module with the homeManagerConfiguration function of home-manager. The process assertions run against systemd units on Linux and launchd agents on Darwin. module-option-parity asserts that each shared option is on both modules, and that the two exclusion lists name only options that exist. env-file-assembly runs the real .env script and checks the contents, the mode, that a second run gives the same bytes, and that a removed file goes away. workspace-files-need-a-directory checks that the module refuses `documents` without a directory, and accepts a directory that has the same text as the default. service-argv runs each command line that the modules build through the real parser of the CLI, with one sentinel flag added, and requires that argparse refuses only the sentinel. `nix flake check` passes, with 21 checks in total. The CLI branches that treat an install as a Nix install move to one helper, is_nix_install_method. Four call sites in main.py, web_server.py, update_cmd.py and doctor.py tested the literal set {"nix", "nixos"}, and each one missed home-manager. recommended_update_command asks the managed state before the code-scoped stamp again, because a managed install can carry a stale stamp that names an update path the managed guard refuses. The metrics contract gets a home-manager bucket, so a Home Manager install does not report as unknown. Each check was mutation-probed. 22 faults were injected, and the checks caught all 22: - a lost --no-open - a backend that runs the gateway - an overwritten config.yaml - documents in the wrong directory - a different HERMES_HOME on the two processes - a lost HERMES_HOME export - a missing backend unit - a removed assertion - an .env file that grows at each activation - an install that reports NixOS - an empty .managed marker - an option on the NixOS module only - a stale entry in an exclusion list - a renamed subcommand - an unknown flag - the workspace-files assertion always passes - the assertion compares values instead of priorities - an off-by-one that lets an untouched default through - the assertion also fires for hermesHomeFiles - a mkDefault no longer counts as a selection - the Home Manager module stops wiring the assertion - the NixOS module stops wiring the assertion The 16 Python tests in tests/hermes_cli/test_managed_install_shapes.py were probed the same way. 8 faults were injected and 8 were caught. These tests fail on this tree. They fail in the same way on the stashed HEAD, and they have no relation to Nix: - test_git_probe_tree_kill.py (2 tests) - test_update_import_guard.py (1 test) - test_telegram_media_read_timeout.py (2 tests) - test_teams.py (a collection error) Closes #9056 # Conflicts: # hermes_cli/main.py # hermes_cli/update_cmd.py # hermes_cli/web_server.py
Hermes Agent ☤
The self-improving AI agent built by Nous Research. It's the only agent with a built-in learning loop — it creates skills from experience, improves them during use, nudges itself to persist knowledge, searches its own past conversations, and builds a deepening model of who you are across sessions. Run it on a $5 VPS, a GPU cluster, or serverless infrastructure that costs nearly nothing when idle. It's not tied to your laptop — talk to it from Telegram while it works on a cloud VM.
Use any model you want — Nous Portal, OpenRouter, OpenAI, your own endpoint, and many others. Switch with hermes model — no code changes, no lock-in.
| A real terminal interface | Full TUI with multiline editing, slash-command autocomplete, conversation history, interrupt-and-redirect, and streaming tool output. |
| Lives where you do | Telegram, Discord, Slack, WhatsApp, Signal, and CLI — all from a single gateway process. Voice memo transcription, cross-platform conversation continuity. |
| A closed learning loop | Agent-curated memory with periodic nudges. Autonomous skill creation after complex tasks. Skills self-improve during use. FTS5 session search with LLM summarization for cross-session recall. Honcho dialectic user modeling. Compatible with the agentskills.io open standard. |
| Scheduled automations | Built-in cron scheduler with delivery to any platform. Daily reports, nightly backups, weekly audits — all in natural language, running unattended. |
| Delegates and parallelizes | Spawn isolated subagents for parallel workstreams. Write Python scripts that call tools via RPC, collapsing multi-step pipelines into zero-context-cost turns. |
| Runs anywhere, not just your laptop | Seven terminal backends — local, Docker, SSH, Singularity, Modal, Daytona, and Vercel Sandbox. Daytona and Modal offer serverless persistence — your agent's environment hibernates when idle and wakes on demand, costing nearly nothing between sessions. Run it on a $5 VPS or a GPU cluster. |
| Research-ready | Batch trajectory generation, trajectory compression for training the next generation of tool-calling models. |
Quick Install
Linux, macOS, WSL2, Termux
curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash
Windows (native, PowerShell)
Heads up: Native Windows runs Hermes without WSL — CLI, gateway, TUI, and tools all work natively. If you'd rather use WSL2, the Linux/macOS one-liner above works there too. Found a bug? Please file issues.
Run this in PowerShell:
iex (irm https://hermes-agent.nousresearch.com/install.ps1)
The installer handles everything: uv, Python 3.11, Node.js, ripgrep, ffmpeg, and a portable Git Bash (MinGit, unpacked to %LOCALAPPDATA%\hermes\git — no admin required, completely isolated from any system Git install). Hermes uses this bundled Git Bash to run shell commands.
If you already have Git installed, the installer detects it and uses that instead. Otherwise a ~45MB MinGit download is all you need — it won't touch or interfere with any system Git.
Android / Termux: The tested manual path is documented in the Termux guide. On Termux, Hermes installs a curated
.[termux]extra because the full.[all]extra currently pulls Android-incompatible voice dependencies.Windows: Native Windows is fully supported — the PowerShell one-liner above installs everything. If you'd rather use WSL2, the Linux command works there too. Native Windows install lives under
%LOCALAPPDATA%\hermes; WSL2 installs under~/.hermesas on Linux.
After installation:
source ~/.bashrc # reload shell (or: source ~/.zshrc)
hermes # start chatting!
Troubleshooting
Windows Defender or antivirus flags uv.exe as malware
If your antivirus (Bitdefender, Windows Defender, etc.) quarantines uv.exe from the Hermes bin folder (%LOCALAPPDATA%\hermes\bin\uv.exe), this is a false positive. The file is Astral's uv — the Rust Python package manager Hermes bundles to manage its Python environment. ML-based antivirus engines commonly flag unsigned Rust binaries that download and install packages.
To verify your copy is authentic:
# Install GitHub CLI if needed
winget install --id GitHub.cli
# Login to GitHub
gh auth login
# Run verification
$uv = "$env:LOCALAPPDATA\hermes\bin\uv.exe"
$ver = (& $uv --version).Split(' ')[1]
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$zip = "$env:TEMP\uv.zip"
Invoke-WebRequest "https://github.com/astral-sh/uv/releases/download/$ver/uv-x86_64-pc-windows-msvc.zip" -OutFile $zip -UseBasicParsing
gh attestation verify $zip --repo astral-sh/uv
Expand-Archive $zip "$env:TEMP\uv_x" -Force
(Get-FileHash "$env:TEMP\uv_x\uv.exe").Hash -eq (Get-FileHash $uv).Hash
If attestation says "Verification succeeded" and the last line prints True, you're good.
To whitelist Hermes:
- Windows Defender: Run PowerShell as Admin →
Add-MpPreference -ExclusionPath "$env:LOCALAPPDATA\hermes\bin" - Bitdefender: Add an exception in the Bitdefender console (Protection > Antivirus > Settings > Manage Exceptions)
- Whitelist the folder, not the file hash — Hermes updates
uvand the hash changes every version
For more context, see the upstream Astral reports: astral-sh/uv#13553, astral-sh/uv#15011, astral-sh/uv#10079.
Getting Started
hermes # Interactive CLI — start a conversation
hermes model # Choose your LLM provider and model
hermes tools # Configure which tools are enabled
hermes config set # Set individual config values
hermes config get # Print individual config values
hermes gateway # Start the messaging gateway (Telegram, Discord, etc.)
hermes setup # Run the full setup wizard (configures everything at once)
hermes claw migrate # Migrate from OpenClaw (if coming from OpenClaw)
hermes update # Update to the latest version
hermes doctor # Diagnose any issues
Skip the API-key collection — Nous Portal
Hermes works with whatever provider you want — that's not changing. But if you'd rather not collect five separate API keys for the model, web search, image generation, TTS, and a cloud browser, Nous Portal covers all of them under one subscription:
- 300+ models — pick any of them with
/model <name> - Tool Gateway — web search (Firecrawl), image generation (FAL), text-to-speech (OpenAI), cloud browser (Browser Use), all routed through your sub. No extra accounts.
One command from a fresh install:
hermes setup --portal
That logs you in via OAuth, sets Nous as your provider, and turns on the Tool Gateway. Check what's wired up any time with hermes portal info. Full details on the Tool Gateway docs page.
You can still bring your own keys per-tool whenever you want — the gateway is per-backend, not all-or-nothing.
CLI vs Messaging Quick Reference
Hermes has two entry points: start the terminal UI with hermes, or run the gateway and talk to it from Telegram, Discord, Slack, WhatsApp, Signal, or Email. Once you're in a conversation, many slash commands are shared across both interfaces.
| Action | CLI | Messaging platforms |
|---|---|---|
| Start chatting | hermes |
Run hermes gateway setup + hermes gateway start, then send the bot a message |
| Start fresh conversation | /new or /reset |
/new or /reset |
| Change model | /model [provider:model] |
/model [provider:model] |
| Set a personality | /personality [name] |
/personality [name] |
| Retry or undo the last turn | /retry, /undo |
/retry, /undo |
| Compress context / check usage | /compress, /usage, /insights [--days N] |
/compress, /usage, /insights [days] |
| Browse skills | /skills or /<skill-name> |
/<skill-name> |
| Interrupt current work | Ctrl+C or send a new message |
/stop or send a new message |
| Platform-specific status | /platforms |
/status, /sethome |
For the full command lists, see the CLI guide and the Messaging Gateway guide.
Documentation
All documentation lives at hermes-agent.nousresearch.com/docs:
| Section | What's Covered |
|---|---|
| Quickstart | Install → setup → first conversation in 2 minutes |
| CLI Usage | Commands, keybindings, personalities, sessions |
| Configuration | Config file, providers, models, all options |
| Messaging Gateway | Telegram, Discord, Slack, WhatsApp, Signal, Home Assistant |
| Security | Command approval, DM pairing, container isolation |
| Tools & Toolsets | 40+ tools, toolset system, terminal backends |
| Skills System | Procedural memory, Skills Hub, creating skills |
| Memory | Persistent memory, user profiles, best practices |
| MCP Integration | Connect any MCP server for extended capabilities |
| Cron Scheduling | Scheduled tasks with platform delivery |
| Context Files | Project context that shapes every conversation |
| Architecture | Project structure, agent loop, key classes |
| Contributing | Development setup, PR process, code style |
| CLI Reference | All commands and flags |
| Environment Variables | Complete env var reference |
Migrating from OpenClaw
If you're coming from OpenClaw, Hermes can automatically import your settings, memories, skills, and API keys.
During first-time setup: The setup wizard (hermes setup) automatically detects ~/.openclaw and offers to migrate before configuration begins.
Anytime after install:
hermes claw migrate # Interactive migration (full preset)
hermes claw migrate --dry-run # Preview what would be migrated
hermes claw migrate --preset user-data # Migrate without secrets
hermes claw migrate --overwrite # Overwrite existing conflicts
What gets imported:
- SOUL.md — persona file
- Memories — MEMORY.md and USER.md entries
- Skills — user-created skills →
~/.hermes/skills/openclaw-imports/ - Command allowlist — approval patterns
- Messaging settings — platform configs, allowed users, working directory
- API keys — allowlisted secrets (Telegram, OpenRouter, OpenAI, Anthropic, ElevenLabs)
- TTS assets — workspace audio files
- Workspace instructions — AGENTS.md (with
--workspace-target)
See hermes claw migrate --help for all options, or use the openclaw-migration skill for an interactive agent-guided migration with dry-run previews.
Contributing
We welcome contributions! See the Contributing Guide for development setup, code style, and PR process.
Quick start for contributors — use the standard installer, then work from the
full git checkout it creates at $HERMES_HOME/hermes-agent (usually
~/.hermes/hermes-agent). This matches the layout used by hermes update, the
managed venv, lazy dependencies, gateway, and docs tooling.
curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash
cd "${HERMES_HOME:-$HOME/.hermes}/hermes-agent"
uv pip install -e ".[all,dev]"
scripts/run_tests.sh
Manual clone fallback (for throwaway clones/CI where you intentionally do not want the managed install layout):
Create the venv outside the cloned source tree — a venv inside the directory the agent operates from can be wiped by a relative-path command the agent runs against its own checkout, destroying the running runtime mid-session.
curl -LsSf https://astral.sh/uv/install.sh | sh
uv venv ~/.hermes/venvs/hermes-dev --python 3.11
source ~/.hermes/venvs/hermes-dev/bin/activate
uv pip install -e ".[all,dev]"
scripts/run_tests.sh
Community
- 💬 Discord
- 📚 Skills Hub
- 🐛 Issues
- 🔌 computer-use-linux — Linux desktop-control MCP server for Hermes and other MCP hosts, with AT-SPI accessibility trees, Wayland/X11 input, screenshots, and compositor window targeting.
- 🔌 HermesClaw — Community WeChat bridge: Run Hermes Agent and OpenClaw on the same WeChat account.
License
MIT — see LICENSE.
Built by Nous Research.
