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¶
One-Line Install (Recommended)¶
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:
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:
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:
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:
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).
Session Search¶
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.
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
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.
Modal¶
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:
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¶
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
Best practices:
- Never commit
.envfiles to version control - Use per-profile
.envfiles (~/.hermes/profiles/<name>/.env) to isolate credentials between use cases - In Docker, pass keys with
-eflags instead of writing them to the mounted.env - Forward only required keys to sandboxes with
docker_forward_envorenv_passthrough - Run
hermes security auditafter 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¶
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>
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¶
Sources¶
- Installation
- Platform Support
- Quickstart
- Docker
- CLI Commands Reference
- Configuration Guide
- Environment Variables Reference
- Messaging Gateway
- Security
- API Server
- Web Dashboard
- Persistent Memory
- Skills System
- Package Management (PM)
- README (OpenClaw migration)