5 min read
ai

Hermes Agent: Installation Deep Dive and Optimization

In a previous post, I covered what Hermes Agent is and why it matters. This time, I’m diving into the actual installation process — the choices I made, the problems I hit, and the optimizations I applied for my setup.


What the Installer Actually Does

Hermes Agent provides a one-liner installer:

Terminal window
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash

But what does that script actually do? After reading through all 1,133 lines, here’s the execution order:

  1. OS detection — identifies Linux, macOS, or Windows (bails on native Windows, recommends WSL2)
  2. Installs uv — the fast Python package manager from Astral, if not already present
  3. Ensures Python 3.11 — downloads and manages it via uv (no system Python needed)
  4. Checks for Git — exits with distro-specific install instructions if missing
  5. Installs Node.js 22 — downloads the binary to ~/.hermes/node/ and symlinks to ~/.local/bin/
  6. Installs system packagesripgrep (fast search) and ffmpeg (TTS audio), using apt/brew/pacman or cargo as fallback
  7. Clones the repo — tries SSH first, falls back to HTTPS, to ~/.hermes/hermes-agent/. If already cloned, runs git pull (stashing local changes with a restore prompt)
  8. Creates a Python venv — via uv venv with Python 3.11
  9. Installs Python dependenciesuv pip install -e ".[all]" with fallback to base install
  10. Installs Node.js dependenciesnpm install + Playwright Chromium, plus WhatsApp bridge deps
  11. Sets up the hermes CLI — symlinks the venv entry point to ~/.local/bin/hermes and adds it to PATH in shell config
  12. Creates config — copies .env and config.yaml templates to ~/.hermes/, creates SOUL.md persona file, syncs bundled skills
  13. Runs setup wizard — interactive hermes setup for API key configuration
  14. Optionally starts the gateway — if a messaging token is configured, offers to install as a systemd service or background process

The script is well-designed for curl | bash piping — it reads interactive prompts from /dev/tty instead of stdin, so non-interactive mode works without hanging.


PyTorch CPU-Only Optimization

By default, uv pip install -e ".[all]" pulls in the full PyTorch build with CUDA support — which is unnecessary if you’re running on CPU or using an API-based LLM provider. The full CUDA build is several gigabytes larger.

I modified the installer to use the CPU-only PyTorch wheels by adding --extra-index-url https://download.pytorch.org/whl/cpu:

Terminal window
uv pip install --index-strategy unsafe-best-match \
--extra-index-url https://download.pytorch.org/whl/cpu \
-e ".[all]"

The --index-strategy Gotcha

Without --index-strategy unsafe-best-match, this breaks. Here’s why:

uv has strict security around index priority. When a package (like requests) is found on the first index that contains it, uv only considers versions from that index — even if the version it needs is on a different index. Since PyTorch’s CPU wheel index hosts an outdated requests==2.28.1, uv refuses to look at PyPI for requests>=2.33.0.

The --index-strategy unsafe-best-match flag tells uv to pick the best matching version across all indexes, not just the first one. This way, PyTorch packages come from the CPU wheel index while everything else resolves from PyPI normally.

The error you’d see without this flag:

hint: `requests` was found on https://download.pytorch.org/whl/cpu, but not at
the requested version (requests>=2.33.0,<3). A compatible version may be available
on a subsequent index (e.g., https://pypi.org/simple). By default, uv will only
consider versions that are published on the first index that contains a given
package, to avoid dependency confusion attacks.

Playwright Browser Reuse

Hermes Agent uses Playwright for browser automation. If you already have Playwright installed globally (like I do at version 1.59.1), you might wonder if it downloads another browser.

The answer depends on version matching:

  • Browser binaries are stored in ~/.cache/ms-playwright/ with version-pinned directories (e.g., chromium-1208)
  • If the Playwright version in Hermes Agent’s package.json matches your global install, it reuses the cached browser — no extra download
  • If versions differ, a separate Chromium directory gets created alongside your existing ones — nothing gets overwritten

No special configuration needed. They coexist peacefully.


Can You Replace Node.js with Bun?

I looked into this since I prefer Bun’s speed. Hermes Agent’s Node.js dependencies are:

Root package.json:

PackageBun Compatible
agent-browser ^0.13.0Likely yes
@askjo/camoufox-browser ^1.0.0Uncertain — Firefox fork with possible native bindings

WhatsApp bridge:

PackageBun Compatible
@whiskeysockets/baileys 7.0.0-rc.9Yes — pure JS WebSocket library
express ^4.21.0Yes
qrcode-terminal ^0.12.0Yes
pino ^9.0.0Partial — core works, some transports may break

The dealbreaker: The installer runs npx playwright install --with-deps chromium, which uses Node.js APIs to detect the OS and install system libraries. Playwright’s --with-deps flag is known to be Node-specific and doesn’t work reliably under Bun.

Given that the installer isolates Node.js in ~/.hermes/node/ (~50MB) without interfering with anything else on the system, I decided to keep Node.js for this project. The risk/reward of swapping to Bun isn’t worth it here.


RL Training vs. Built-In Learning

One thing that confused me during installation: the [rl] extra is not included in [all]. The pyproject.toml has this:

all = [
"hermes-agent[modal]",
"hermes-agent[messaging]",
"hermes-agent[cron]",
# ... everything else ...
# rl is NOT here
]

At first I thought: does Hermes Agent actually learn without RL?

Yes, absolutely. The “learning” in Hermes Agent has nothing to do with RL training:

  • Memory — persists knowledge across sessions in ~/.hermes/memories/
  • Auto-generated skills — creates reusable skills from experience in ~/.hermes/skills/
  • Conversation history — searches past conversations to recall context
  • Self-improvement loop — creates skills from experience and improves them during use

The RL training ([rl] extra + tinker-atropos submodule) is for fine-tuning the LLM model weights — a separate, advanced workflow for researchers. It’s what Nous Research uses to produce models like DeepHermes-ToolCalling-Specialist-Atropos on HuggingFace.

The RL extra is excluded from [all] because:

  1. It pulls in atroposlib and tinker via git+https://... — slow and can fail on network issues
  2. It transitively depends on PyTorch (even if you’re using CPU-only wheels, it’s still heavy)
  3. It requires the tinker-atropos git submodule to be cloned separately
  4. Only researchers doing RL training need it

You can install it manually anytime:

Terminal window
git submodule update --init tinker-atropos
uv pip install -e "./tinker-atropos"

Regular learning works out of the box without any of this.


Firecrawl Setup

Firecrawl (web scraping) is already included as a core Python dependency (firecrawl-py>=4.16.0). No extra installation needed — it’s part of the base dependencies, not even an extra.

To enable it, just add your API key to ~/.hermes/.env:

FIRECRAWL_API_KEY=fc-your-key-here

Sign up at firecrawl.dev to get an API key.


What Gets Installed with [all]

For reference, here’s everything that .[all] pulls in:

Core (always installed): openai, anthropic, httpx, requests, rich, prompt_toolkit, pyyaml, jinja2, pydantic, fire, tenacity, python-dotenv, exa-py, firecrawl-py, parallel-web, fal-client, edge-tts, PyJWT

Extras included in [all]:

ExtraPurpose
messagingTelegram, Discord bots via python-telegram-bot, discord.py
cronScheduled tasks via croniter
cliTerminal menu UI
devpytest, debugpy, mcp
tts-premiumElevenLabs voice
voiceLocal STT with faster-whisper, audio input
mcpModel Context Protocol
modalModal cloud compute
daytonaDaytona dev environments
ptyPTY process management
honchoHoncho AI integration
homeassistantHome Assistant control
smsSMS via aiohttp
slackSlack messaging
acpAgent Client Protocol
dingtalk, feishuChinese messaging platforms

Excluded from [all] (install manually):

ExtraReason
matrixpython-olm is broken on modern macOS
rlHeavy ML dependencies, git submodules
yc-benchBenchmark tool, requires Python 3.12+

My Final Installation Command

After all the modifications, here’s what worked for my setup:

Terminal window
# Clone with submodules
git clone --recurse-submodules https://github.com/NousResearch/hermes-agent.git
cd hermes-agent
# Install uv
curl -LsSf https://astral.sh/uv/install.sh | sh
# Create venv
uv venv venv --python 3.11
export VIRTUAL_ENV="$(pwd)/venv"
# Install with CPU-only PyTorch
uv pip install --index-strategy unsafe-best-match \
--extra-index-url https://download.pytorch.org/whl/cpu \
-e ".[all]"
# Node.js dependencies (browser tools + WhatsApp)
npm install
npx playwright install chromium
# Configure
mkdir -p ~/.hermes/{cron,sessions,logs,memories,skills,pairing,hooks,image_cache,audio_cache,whatsapp/session}
cp cli-config.yaml.example ~/.hermes/config.yaml
cp .env.example ~/.hermes/.env
# Make hermes available globally
mkdir -p ~/.local/bin
ln -sf "$(pwd)/venv/bin/hermes" ~/.local/bin/hermes
# Run setup wizard
hermes setup

Post-Installation: Setting Up CLI Skills

Hermes Agent ships with bundled skills, but its real power comes from creating project-specific skills that teach it how to use the CLIs already on your system. Rather than calling APIs directly, Hermes can delegate to system-installed tools — which means your other agents (Claude Code, Codex, etc.) and Hermes all share the same tools and authentication.

Here’s how I set up three essential skills: web search, library documentation, and issue tracking.

Hermes has built-in web search via the TAVILY_API_KEY env var, but I prefer using the Tavily CLI directly. This way every agent on my laptop uses the same interface.

Terminal window
# Install
npm install -g @tavily/cli
# Authenticate (one-time)
tvly login --api-key tvly-YOUR_KEY
# Verify
tvly auth

The CLI supports --json output for agent-friendly parsing:

Terminal window
# Search with AI-generated answer
tvly search "Hermes Agent skills" --max-results 5 --include-answer basic --json
# Extract content from URLs
tvly extract https://example.com https://other.com --json
# Deep research (multi-step, takes minutes)
tvly research "comprehensive analysis of X" --json
# Crawl a website
tvly crawl https://example.com --max-depth 2 --limit 20 --json

To create the skill, Hermes uses its skill_manage tool — but the key insight is that the skill file is just a markdown document at ~/.hermes/skills/research/tvly/SKILL.md. Hermes auto-loads skills when their trigger conditions match the current task.

Context7 CLI (ctx7) for Library Documentation

When coding, you often need up-to-date API docs. Context7 provides this without web searches — it serves curated, versioned documentation for libraries directly from the terminal.

Terminal window
# Install (via npm)
npm install -g @upstash/context7
# Authenticate (one-time)
ctx7 login
# Verify
ctx7 whoami

The workflow is two-step: resolve a library name to an ID, then query docs:

Terminal window
# Find the library
ctx7 library "react" --json
# Returns IDs like /facebook/react, /reactjs/react.dev with trust scores
# Query documentation
ctx7 docs /facebook/react "useEffect cleanup" --json
# Returns code snippets with descriptions and source links

Each result includes a benchmarkScore and trustScore to help pick the best source. If a library has tagged versions (e.g., v19_2_0), you can query specific versions.

Beads (bd) for Issue Tracking

Beads is a dependency-aware issue tracker backed by Dolt (versioned SQL). No server needed — it embeds a Dolt database in your project’s .beads/ directory.

Terminal window
# Install (Go binary)
go install github.com/steveyegge/beads/cmd/bd@latest
# Initialize in a project
cd ~/my-project
bd init
# Verify
bd where

Once initialized, bd manages issues with dependency tracking:

Terminal window
# Session start
bd prime # Load workflow context
bd ready # Show unblocked work
# Create and manage issues
bd create "Fix auth bug" -t bug -p 1
bd update <id> --claim # Atomically claim work
bd dep add <a> <b> # B blocks A
bd close <id>
# Cross-session memory
bd remember "auth uses JWT not sessions" --key auth-jwt
bd recall auth-jwt
# Sync with team
bd dolt push # Push to Dolt remote

What makes bd powerful for multi-agent workflows:

  • bd ready shows only issues with no blocking dependencies — perfect for agents to self-assign work
  • bd dep add prevents agents from duplicating effort on dependent tasks
  • bd worktree creates parallel git worktrees that share the same issue database
  • bd mol pour instantiates reusable workflow templates (molecules) from formulas

Registering as a Hermes Skill

For each CLI, creating a Hermes skill is straightforward. Skills live at ~/.hermes/skills/<category>/<name>/SKILL.md with YAML frontmatter and a markdown body containing usage instructions, examples, and pitfalls.

---
name: tvly
description: "Tavily CLI for web search, extraction, crawling, and deep research. Triggers: web search, tavily, tvly."
---

The critical part is the description field — Hermes scans all skill descriptions against the current task and auto-loads matching skills. For tvly, triggers include “web search”, “tavily”, and “tvly”. For ctx7, triggers include “library docs”, “framework documentation”, and “API reference”.

Hermes also persists user preferences in memory so it doesn’t need to re-learn them each session. For example, I told it to always prefer system-installed CLIs over npx or bunx, and to ask before installing anything not already on the system. These preferences survive across sessions.

Integrating with Other Agents

The nice thing about using CLIs instead of direct API calls: every agent benefits. bd has built-in setup recipes for Claude Code, Codex, OpenCode, Cursor, Windsurf, and others:

Terminal window
bd setup claude # Install Claude Code hooks (SessionStart, PreCompact)
bd setup codex # Add to AGENTS.md
bd setup opencode # Add to AGENTS.md

This injects beads workflow instructions into each agent’s config file — CLAUDE.md, AGENTS.md, or rules files. For Hermes, I registered a custom recipe:

Terminal window
bd setup --add hermes ~/.beads/recipes/hermes.md

This writes beads rules into AGENTS.md that tell Hermes to use bd instead of its built-in todo tool, and to run bd prime at session start for workflow context.

The same principle applies to tvly and ctx7 — since they’re system CLIs, any agent with terminal access can use them. No API keys to manage per-agent, no MCP servers to configure, no duplicate setup.


References

  1. Nous Research. Hermes Agent Documentation — Installation. Accessed 5 Apr. 2026.
  2. Nous Research. Hermes Agent GitHub Repository. Accessed 5 Apr. 2026.
  3. Astral. uv pip install — Index Strategy. Accessed 5 Apr. 2026.
  4. PyTorch. Installing CPU-Only PyTorch. Accessed 5 Apr. 2026.
  5. Tavily. Tavily CLI Documentation. Accessed 5 Apr. 2026.
  6. Context7. Context7 — LLM Context as a Service. Accessed 5 Apr. 2026.
  7. Steve Yegge. Beads — Dependency-Aware Issue Tracker. Accessed 5 Apr. 2026.

This article was written by opencode (GLM-5-Turbo | Z.AI Coding Plan).