Skip to content

How-to Guides

Task recipes for installing, configuring, securing, operating, and troubleshooting Hermes Agent. Commands were checked against the v0.21.x docs (2026-09). For defaults and full option tables see Reference; for the reasoning behind the design see Explanation.

Install paths changed in v0.20.0 (2026-08-03)

Supported install channels are now the shell/PowerShell installers, desktop bundles, Docker, and (best effort) Nix and Termux. pip install, uv tool install, and Homebrew installs are unsupported. The installer URL moved from raw.githubusercontent.com/.../scripts/install.sh to hermes-agent.nousresearch.com/install.sh.

Installation

Linux, macOS (Apple Silicon), and WSL2:

curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash
source ~/.bashrc    # or: source ~/.zshrc
hermes              # start chatting

The script clones the source to ~/.hermes/hermes-agent/, bootstraps uv, and hands dependency preparation to PM, which supplies pinned Python 3.14, Node.js, npm, ripgrep, FFmpeg, and the browser tools. Useful flags: --skip-browser (leave out agent-browser + Chromium), --non-interactive (skip setup prompts), --include-desktop (build the desktop app from source), --verbose.

Windows (Native)

In PowerShell:

iex (irm https://hermes-agent.nousresearch.com/install.ps1)

Installs under %LOCALAPPDATA%\hermes. Equivalent flags: -SkipBrowser, -NonInteractive, -IncludeDesktop, -HermesHome, -InstallDir. If antivirus quarantines %LOCALAPPDATA%\hermes\bin\uv.exe, the README documents it as a false positive and shows how to verify it with gh attestation verify.

Desktop App

Download the macOS DMG (Apple Silicon) or the Windows .appinstaller (signed MSIX, Windows 11 22H2+) from hermes-agent.nousresearch.com. After a CLI-only install you can build and launch the desktop app with:

hermes desktop

Docker

mkdir -p ~/.hermes
# First run: interactive setup wizard, writes ~/.hermes/.env
docker run -it --rm -v ~/.hermes:/opt/data nousresearch/hermes-agent setup

# Then run the gateway (and API server on 8642) in the background
docker run -d --name hermes --restart unless-stopped \
  -v ~/.hermes:/opt/data -p 8642:8642 \
  nousresearch/hermes-agent gateway run

Image tags: latest/stable (release-gated), main (development), versioned tags, and calendar tags such as v2026.9.24. Docker installs do not support hermes update: pull a new image instead. Inside the image, gateway run is supervised by s6-overlay and restarts automatically.

Docker API key injection

Pass keys with -e flags (for example -e OPENROUTER_API_KEY=...) instead of writing them into the mounted .env. This suits CI/CD pipelines and secrets-manager integrations where keys should not be stored on disk.

Android / Termux

On aarch64 Android, add the signed Hermes APT repository (see the Termux guide), then:

pkg install hermes-agent

Do not use the desktop/server installer script on Termux.

Install via pip / uv

Not supported. The last PyPI upload is hermes-agent 0.19.0 (2026-07-20), and the platform-support page lists pip install hermes-agent and uv tool install hermes-agent as unsupported. Migrate existing pip installs to the shell installer. Existing data in ~/.hermes/ is kept.

From Source (Contributors)

Clone the repo and follow the PM developer workflow (run the setup script once, then source ./activate). Tests run in a separate environment described in Contributing. The older uv venv --python 3.11 + uv pip install -e ".[all,dev]" recipe predates PM and Python 3.14 and is no longer documented.

Run as a Non-Sudo Service User (Linux)

# as the service user
curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash
export PATH="$HOME/.local/bin:$PATH"
hermes doctor
# as an administrator, so the user service survives logout
sudo loginctl enable-linger SERVICE_USER

Configuration

Setup Wizard

hermes setup                     # First run: full wizard. Existing install: reconfigure with current values as defaults
hermes setup --portal            # Nous Portal OAuth + provider + Tool Gateway in one step
hermes setup model               # Model provider only
hermes setup terminal            # Terminal backend only
hermes setup gateway             # Messaging platforms only
hermes setup tools               # Enable/disable tools
hermes setup agent               # Agent behavior settings
hermes setup --quick             # Only prompt for missing items
hermes setup --non-interactive   # Use defaults / env values
hermes setup --reset             # Reset to defaults first

Config Management

UPPER_SNAKE names go to ~/.hermes/.env; dotted keys go to ~/.hermes/config.yaml.

hermes config show               # Current values
hermes config edit               # Open config.yaml in $EDITOR
hermes config get model.default  # One value (secrets masked; --raw to reveal)
hermes config set KEY VAL        # Set a value (type-checked against the schema)
hermes config unset KEY          # Revert to the built-in default
hermes config check              # Missing or stale options after an update
hermes config migrate            # Interactively add new options

Examples:

hermes config set model.provider openrouter
hermes config set terminal.backend docker
hermes config set OPENROUTER_API_KEY sk-or-...   # Saved to .env

Model Provider Setup

hermes model                     # Interactive provider/model picker (also auxiliary-model routing)
hermes auth add openrouter --type oauth    # Browser login instead of pasting a key
hermes auth add openai-codex --browser     # ChatGPT/Codex subscription via PKCE
hermes portal info               # Nous Portal login and Tool Gateway routing
hermes fallback                  # Providers to try when the primary errors

Hermes is LLM-agnostic: more than 40 providers, including Nous Portal, OpenRouter, Anthropic, OpenAI, Gemini, Bedrock, Vertex, Azure AI Foundry, DeepSeek, xAI, LM Studio, and any OpenAI-compatible custom endpoint (see Reference: Inference Providers). Switch mid-session with /model provider:model.

Route Side Tasks to a Cheaper Model

Vision, compression, titles, the background learning review, and the curator all default to your main model (auto). Pin a cheaper model per task:

auxiliary:
  background_review:
    provider: openrouter
    model: google/gemini-3-flash-preview

Or run hermes model and choose "Auxiliary models".

CLI Commands

Chat

hermes                                   # Interactive chat (default)
hermes chat -q "Summarize the latest PRs"            # Seeds an interactive session (v0.21+)
hermes chat --oneshot -q "Summarize the latest PRs"  # Answer and exit
hermes chat --provider openrouter --model anthropic/claude-sonnet-4.6
hermes chat --toolsets web,terminal,skills
hermes chat -Q -q "Return only JSON"                 # Quiet programmatic mode
hermes chat -q "Inspect this repo" --format stream-json
hermes chat --worktree -q "Review this repo and open a PR"
hermes chat --safe-mode -q "Is this bug mine or Hermes'?"
hermes -c                                # Continue the most recent session
hermes -p work                           # Use the "work" profile

Behavior change in v0.21

On a real TTY, hermes chat -q now seeds an interactive session instead of exiting after one answer. Scripts that relied on the old behavior should add --oneshot (or use -Q, or non-TTY stdio).

There is no hermes search command. Past conversations are searched by the agent through its session_search tool (just ask "what did we decide about X last week?"), or by you from the CLI:

hermes sessions browse           # Interactive picker with search and resume
hermes sessions list             # Recent sessions
hermes sessions export out.jsonl # Export to JSONL
hermes sessions prune --older-than 90d --dry-run
hermes sessions optimize         # Merge FTS5 segments + VACUUM

Skill Management

hermes skills browse                              # Browse hub skills (official first)
hermes skills search kubernetes                   # Search all sources
hermes skills search react --source skills-sh     # Search the skills.sh directory
hermes skills inspect openai/skills/k8s           # Preview before installing
hermes skills install openai/skills/k8s           # Install with security scan
hermes skills install official/security/1password
hermes skills list --source hub                   # List hub-installed skills
hermes skills check                               # Check for upstream updates
hermes skills update                              # Reinstall with upstream changes
hermes skills audit                               # Re-scan hub skills for security
hermes skills uninstall k8s                       # Remove a hub skill
hermes skills reset google-workspace              # Un-stick a bundled skill from "user-modified"
hermes skills reset google-workspace --restore    # Also restore the bundled version
hermes skills trust                               # Allow project skills in this repo
hermes skills opt-out                             # Stop seeding bundled skills
hermes skills publish skills/my-skill --to github --repo owner/repo
hermes skills tap add myorg/skills-repo           # Add a custom GitHub source

In chat, /learn <path, URL, or description> authors a new skill from source material, and /<skill-name> loads a skill (up to 5 can be stacked in one message).

Curate What the Agent Learned

hermes journey                   # Timeline of learned skills and memories
hermes journey list              # Node ids
hermes journey delete <node> -y  # Archive a skill or remove a memory chunk
hermes journey edit <node>       # Open it in $EDITOR
hermes curator status            # Skill usage stats and curator state
hermes curator run --dry-run     # Preview what the curator would change
hermes curator pin <skill>       # Protect a skill from auto-archival
hermes curator restore <skill>   # Bring back an archived skill
hermes curator rollback --list   # Snapshots of ~/.hermes/skills/

Require Approval for Memory and Skill Writes

For shared bots, small models, or regulated environments, stage every self-improvement write for review:

hermes config set memory.write_approval true
hermes config set skills.write_approval true
hermes config set display.memory_notifications verbose

Then review in any chat surface:

/memory pending          /skills pending
/memory approve all      /skills diff <id>
/memory reject <id>      /skills approve <id>

External Memory Provider (Honcho and Others)

hermes memory setup              # Pick a provider (honcho, mem0, openviking, ...)
hermes memory setup honcho       # Configure Honcho directly
hermes memory status             # What is active
hermes memory off                # Back to built-in MEMORY.md/USER.md only

The hermes honcho subcommand appears only while Honcho is the active provider:

hermes honcho status             # Connection and key settings
hermes honcho mode hybrid        # Recall mode: hybrid | context | tools
hermes honcho strategy           # per-directory | per-repo | per-session | global
hermes honcho map my-project     # Map the current directory to a session name

Gateway

hermes gateway setup             # Interactive platform setup
hermes gateway run               # Foreground (recommended for WSL, Docker, Termux)
hermes gateway install           # Install as a systemd/launchd service
hermes gateway start             # Start the installed service
hermes gateway stop              # Stop the service or foreground process
hermes gateway restart --all     # Restart every profile's gateway
hermes gateway status            # Service status
hermes gateway list              # All profiles and whether their gateway runs

On WSL, prefer tmux new -s hermes 'hermes gateway run'; WSL's systemd support is unreliable.

System

hermes doctor                    # Health check, install provenance, storage problems
hermes status                    # Agent, auth, and platform status
hermes logs -f                   # Follow agent.log
hermes logs gateway --since 1h   # Gateway log, last hour
hermes dump                      # Copy-pasteable setup summary for bug reports
hermes backup                    # Zip of HERMES_HOME (WAL-safe)
hermes --version

Terminal Backend Setup

Local (Default)

Commands run on the host. No additional configuration.

terminal:
  backend: local
  cwd: "."
  timeout: 180

Dangerous command checks active

The local and SSH backends route commands through the hardline blocklist and the approval layer (approvals.mode: smart by default). Interactive prompts offer [o]nce, [s]ession, [a]lways, or [d]eny.

Docker

terminal:
  backend: docker
  docker_image: "nikolaik/python-nodejs:python3.11-nodejs20"
  docker_forward_env: ["GITHUB_TOKEN"]   # forward secrets from the host env
  docker_volumes:
    - "/home/user/projects:/workspace/projects"
  container_persistent: true              # false = fresh container per session
  docker_network: true                    # false = --network=none

By default Hermes starts one long-lived container and reuses it across sessions, /new, subagents, and Hermes restarts (found by label). The container is not removed when a session ends. Set container_persistent: false when each conversation needs its own sandbox. Use Podman with HERMES_DOCKER_BINARY=podman. Security hardening is applied automatically (see Explanation: Sandboxing).

SSH

# ~/.hermes/.env
TERMINAL_SSH_HOST=my-server.example.com
TERMINAL_SSH_USER=ubuntu
TERMINAL_SSH_KEY=~/.ssh/id_ed25519      # optional
terminal:
  backend: ssh
  persistent_shell: true

Hermes connects with BatchMode=yes and StrictHostKeyChecking=accept-new and keeps one bash -l alive. Variables listed in env_passthrough travel via OpenSSH SendEnv, so the server's sshd_config needs a matching AcceptEnv.

Daytona

terminal:
  backend: daytona
  container_persistent: true    # stop/resume instead of delete
  container_disk: 10240         # Daytona caps disk at 10 GiB

Requires DAYTONA_API_KEY. Sandboxes are named hermes-{task_id}.

Singularity

terminal:
  backend: singularity
  singularity_image: "docker://nikolaik/python-nodejs:python3.11-nodejs20"

For HPC cluster environments. Uses Singularity/Apptainer containers.

terminal:
  backend: modal
  modal_image: "nikolaik/python-nodejs:python3.11-nodejs20"
  container_persistent: true    # snapshot/restore the filesystem

Requires MODAL_TOKEN_ID + MODAL_TOKEN_SECRET or ~/.modal.toml. Snapshots are tracked in ~/.hermes/modal_snapshots.json. Live processes do not survive a snapshot.

Vercel Sandbox

terminal:
  backend: vercel_sandbox
  vercel_runtime: node24        # node24 | node22 | python3.13
  cwd: /vercel/sandbox

Set VERCEL_TOKEN, VERCEL_PROJECT_ID, and VERCEL_TEAM_ID for long-running deployments. For local development only, a short-lived OIDC token works: VERCEL_OIDC_TOKEN="$(vc project token)" hermes chat. Leave container_disk at its default; Vercel Sandbox does not support it.

Environment Passthrough

Forward host environment variables to sandboxed backends:

terminal:
  env_passthrough: [GITHUB_TOKEN, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY]

Hermes provider credentials (for example OPENAI_API_KEY) are never forwarded, even if listed.

Multi-Platform Channel Configuration

Telegram

# Interactive
hermes gateway setup   # Select Telegram, enter bot token

# Manual (~/.hermes/.env)
TELEGRAM_BOT_TOKEN=123456789:ABCdefGHIjklMNOpqrSTUvwxYZ
TELEGRAM_ALLOWED_USERS=123456789    # Comma-separated for multiple users

Discord

DISCORD_BOT_TOKEN=your-bot-token
DISCORD_ALLOWED_USERS=your-user-id

Slack

# Required
SLACK_BOT_TOKEN=xoxb-your-bot-token-here
SLACK_APP_TOKEN=xapp-your-app-token-here   # Socket Mode
SLACK_ALLOWED_USERS=U01ABC2DEF3            # Comma-separated Member IDs

# Optional: default channel for cron delivery
SLACK_HOME_CHANNEL=C01234567890
SLACK_HOME_CHANNEL_NAME=general

hermes slack can generate an app manifest that exposes every Hermes command as a native slash command.

Other Platforms

Run hermes gateway setup and pick the platform; it writes credentials to the active profile's .env. Platform-specific Python dependencies are prepared on demand by PM (lazy install). If you disabled lazy installs (security.allow_lazy_installs: false) or run a locked-down image, prepare them explicitly:

hermes pm status                 # What PM has prepared
hermes pm doctor                 # Diagnose missing tools/deps
hermes pm repair                 # Repair the environment

WhatsApp has two adapters: hermes whatsapp (personal-account bridge) and hermes whatsapp-cloud (Meta Business Cloud API, needs a public webhook). Per-profile bot tokens live in ~/.hermes/profiles/<name>/.env.

Removed recipe

Earlier versions of this page used pip install "hermes-agent[telegram]" to add platform dependencies. That no longer applies: pip installs are unsupported and PM manages extras.

Migrate from OpenClaw

hermes claw migrate --dry-run            # Preview
hermes claw migrate                      # Interactive, full preset
hermes claw migrate --preset user-data   # Without secrets
hermes claw migrate --overwrite          # Overwrite conflicts

The migration imports SOUL.md, MEMORY.md/USER.md entries, user skills (to ~/.hermes/skills/openclaw-imports/), command allowlists, messaging settings, allowlisted API keys, TTS assets, and optionally AGENTS.md. hermes setup detects ~/.openclaw on first run and offers the same migration. To bring over a Claude Code or Codex CLI setup instead, use hermes import-agent.

API Key Management

API keys live in ~/.hermes/.env (per profile) and are managed via the CLI:

hermes config set OPENROUTER_API_KEY sk-or-...   # Auto-routed to .env
hermes config set ANTHROPIC_API_KEY sk-ant-...
hermes auth list                                 # Stored credentials and OAuth logins
hermes secrets                                   # Pull keys from Bitwarden Secrets Manager instead

File permissions

Restrict .env to owner-only access:

chmod 600 ~/.hermes/.env

Best practices:

  • Never commit .env files to version control
  • Use per-profile .env files (~/.hermes/profiles/<name>/.env) to isolate credentials between use cases
  • In Docker, pass keys with -e flags instead of writing them to the mounted .env
  • Forward only required keys to sandboxes with docker_forward_env or env_passthrough
  • Run hermes security audit after updates to check installed packages and plugins against OSV

Channel Authentication

The gateway denies everyone by default. Grant access with allowlists or DM pairing:

Method Setting Notes
Platform allowlist TELEGRAM_ALLOWED_USERS, DISCORD_ALLOWED_USERS, SLACK_ALLOWED_USERS, WHATSAPP_ALLOWED_USERS, ... Comma-separated platform user IDs
Global allowlist GATEWAY_ALLOWED_USERS Checked for every platform
DM pairing hermes pairing approve <platform> <code> Unknown users get an 8-character code; you approve it on the CLI
Allow-all (avoid) <PLATFORM>_ALLOW_ALL_USERS=true, GATEWAY_ALLOW_ALL_USERS=true Anyone who can message the bot gets a fully tooled agent
hermes pairing list                          # Pending and approved users
hermes pairing approve telegram ABCD1234
hermes pairing revoke telegram 123456789

Allow-all means remote shell access

Every authorized user can drive terminal and file tools. Never combine GATEWAY_ALLOW_ALL_USERS=true with the local backend or approvals.mode: off.

Network Security

API Server Binding

The OpenAI-compatible API server runs inside the gateway. Enable it in ~/.hermes/.env:

API_SERVER_ENABLED=true
API_SERVER_KEY=choose-a-long-random-value   # required for every deployment, including loopback
API_SERVER_HOST=127.0.0.1                   # default; change only behind a TLS proxy
API_SERVER_PORT=8642
# API_SERVER_CORS_ORIGINS=http://localhost:3000   # only if a browser calls Hermes directly
hermes gateway run
curl http://localhost:8642/v1/chat/completions \
  -H "Authorization: Bearer $API_SERVER_KEY" -H "Content-Type: application/json" \
  -d '{"model": "hermes-agent", "messages": [{"role": "user", "content": "Hello"}]}'

The API server gives full access to the toolset, including terminal commands. Keep API_SERVER_CORS_ORIGINS narrow. Webhook and API-server sessions deny dangerous commands by default (approvals.unattended_mode: deny).

Web Dashboard

hermes dashboard                 # http://127.0.0.1:9119, no login on loopback

For remote access, configure an auth provider first. A non-loopback bind refuses to start without one:

# ~/.hermes/.env
HERMES_DASHBOARD_BASIC_AUTH_USERNAME=admin
HERMES_DASHBOARD_BASIC_AUTH_PASSWORD=choose-a-strong-password
HERMES_DASHBOARD_BASIC_AUTH_SECRET=<32+ random bytes, e.g. openssl rand -base64 32>
hermes dashboard --host 0.0.0.0 --port 9119 --no-open

Dashboard exposure

The dashboard reads and writes .env, so it exposes every API key. Even with basic auth, put it behind a reverse proxy with TLS. The old --insecure flag is a deprecated no-op and no longer bypasses authentication.

Gateway Network Exposure

Platform adapters use outbound connections (long polling, WebSocket, Socket Mode) and need no inbound ports in most configurations. Exceptions:

  • Webhook mode (Telegram, Feishu, WeCom) and WhatsApp Cloud API need an inbound HTTPS endpoint
  • Webhook subscriptions (hermes webhook subscribe) need the webhook platform reachable; each route gets an HMAC secret
  • API server listens on 8642

Put webhook endpoints behind a reverse proxy with TLS termination.

Monitoring and Logging

hermes logs list                 # Available log files with sizes
hermes logs -f                   # Follow agent.log
hermes logs errors -n 100        # Warnings and errors only
hermes logs gateway --level WARNING --since 30m
hermes doctor                    # System health check
hermes gateway status            # Gateway process status
hermes insights                  # Token/cost/activity analytics
hermes memory status             # Memory provider status

Log files live in ~/.hermes/logs/ (agent.log, errors.log, gateway.log, gui.log, desktop.log); non-default profiles use <profile>/logs/.

Upgrading

Source installs:

hermes update --check            # Is an update available?
hermes update --plan             # What would restart, read-only
hermes update                    # Pull, prepare deps via PM, restart gateways
hermes update --backup           # Also take a full zip of HERMES_HOME first
hermes update --set-channel stable   # Track release tags instead of main

hermes update tracks main by default. stable follows release tags and canary follows published canary commits. It syncs newly bundled skills (unless you opted out) and never overwrites user-modified skills. Afterwards:

hermes config check              # Identify new config options
hermes config migrate            # Interactively add missing options

Docker: docker pull nousresearch/hermes-agent:latest and recreate the container. Desktop bundles, Nix, and Termux update through their own package owner.

Troubleshooting

Gateway fails to start

hermes doctor                          # Missing deps, config, storage problems
hermes pm doctor                       # Missing platform dependencies
hermes logs gateway -n 100             # Last gateway lines
hermes config show                     # Verify configuration

If the log says "No user allowlists configured", set a platform allowlist or approve users via DM pairing.

Model provider errors

hermes doctor                          # Validates API key connectivity
hermes model                           # Reconfigure provider/model
hermes auth list                       # Check OAuth logins; re-add with hermes auth add <provider>

"I told it to remember, and the next session it forgot"

cat ~/.hermes/memories/MEMORY.md       # Did the memory tool actually write?
hermes profile list                    # Are you on the profile you wrote to?

Weak tool-calling models often claim a save without calling the memory tool. Also check /memory pending (write approval), and remember that new entries appear only in the next session. Run /new after saving.

Skill loading issues

hermes skills audit                    # Re-scan for security issues
hermes skills check                    # Check for version mismatches
hermes skills trust                    # Project skills are ignored until trusted
hermes curator list-archived           # Was it archived for inactivity?
hermes skills reset <name> --restore   # Restore the bundled version

Isolate a bug from your own setup

hermes chat --safe-mode -q "reproduce the problem"   # No config, rules, plugins, hooks, or MCP

Sources