| A real terminal interface | Not a web UI — a full TUI with multiline editing, slash-command autocomplete, conversation history, interrupt-and-redirect, and streaming tool output. Built for people who live in the terminal and want an agent that keeps up. |
| Lives where you do | Telegram, Discord, Slack, WhatsApp, and CLI — all from a single gateway process. Send it a voice memo from your phone, get a researched answer with citations. Cross-platform message mirroring means a conversation started on Telegram can continue on Discord. |
| Grows the longer it runs | Persistent memory across sessions — the agent remembers your preferences, your projects, your environment. When it solves a hard problem, it writes a skill document for next time. Skills are searchable, shareable, and compatible with the agentskills.io open standard. A Skills Hub lets you install community skills or publish your own. |
| Scheduled automations | Built-in cron scheduler with delivery to any platform. Set up a daily AI funding report delivered to Telegram, a nightly backup verification on Discord, a weekly dependency audit that opens PRs, or a morning news briefing — all in natural language. The gateway runs them unattended. |
| Delegates and parallelizes | Spawn isolated subagents for parallel workstreams — each gets its own conversation and terminal. The agent can also write Python scripts that call its own tools via RPC, collapsing multi-step pipelines into a single turn with zero intermediate context cost. |
| Real sandboxing | Five terminal backends — local, Docker, SSH, Singularity, and Modal — with persistent workspaces, background process management, with the option to make these machines ephemeral. Run it against a remote machine so it can't modify its own code. |
| Research-ready | Batch runner for generating thousands of tool-calling trajectories in parallel. Atropos RL environments for training models with reinforcement learning on agentic tasks. Trajectory compression for fitting training data into token budgets. |
---
## Quick Install
**Linux/macOS:**
```bash
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
```
**Windows (PowerShell):**
```powershell
irm https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.ps1 | iex
```
The installer will:
- Install [uv](https://docs.astral.sh/uv/) (fast Python package manager) if not present
- Install Python 3.11 via uv if not already available (no sudo needed)
- Clone to `~/.hermes/hermes-agent` (with submodules: mini-swe-agent, tinker-atropos)
- Create a virtual environment with Python 3.11
- Install all dependencies and submodule packages
- Symlink `hermes` into `~/.local/bin` so it works globally (no venv activation needed)
- Run the interactive setup wizard
After installation, reload your shell and run:
```bash
source ~/.bashrc # or: source ~/.zshrc
hermes setup # Configure API keys (if you skipped during install)
hermes # Start chatting!
```
---
## Getting Started
The installer (`hermes setup`) walks you through selecting a provider and model. Once that's done:
```bash
hermes # Start chatting!
hermes model # Switch provider or model interactively
hermes tools # See all available tools
```
This lets you switch between **Nous Portal** (subscription), **OpenRouter** (200+ models, pay-per-use), or a **custom endpoint** (VLLM, SGLang, any OpenAI-compatible API) at any time.
---
## Updating
```bash
hermes update # Update to latest version (prompts for new config)
```
**Uninstalling:**
```bash
hermes uninstall # Uninstall (can keep configs for later reinstall)
```
Or manually:
```bash
rm -f ~/.local/bin/hermes
rm -rf /path/to/hermes-agent
rm -rf ~/.hermes # Optional — keep if you plan to reinstall
```
---
## Inference Providers
You need at least one way to connect to an LLM. Use `hermes model` to switch providers and models interactively, or configure directly:
| Provider | Setup |
|----------|-------|
| **Nous Portal** | `hermes login` (OAuth, subscription-based) |
| **OpenRouter** | `OPENROUTER_API_KEY` in `~/.hermes/.env` |
| **Custom Endpoint** | `OPENAI_BASE_URL` + `OPENAI_API_KEY` in `~/.hermes/.env` |
**Note:** Even when using Nous Portal or a custom endpoint, some tools (vision, web summarization, MoA) use OpenRouter independently. An `OPENROUTER_API_KEY` enables these tools.
---
## Configuration
All your settings are stored in `~/.hermes/` for easy access:
```
~/.hermes/
├── config.yaml # Settings (model, terminal, TTS, compression, etc.)
├── .env # API keys and secrets
├── auth.json # OAuth provider credentials (Nous Portal, etc.)
├── SOUL.md # Optional: global persona (agent embodies this personality)
├── memories/ # Persistent memory (MEMORY.md, USER.md)
├── skills/ # Agent-created skills (managed via skill_manage tool)
├── cron/ # Scheduled jobs
├── sessions/ # Gateway sessions
└── logs/ # Logs
```
### Managing Configuration
```bash
hermes config # View current configuration
hermes config edit # Open config.yaml in your editor
hermes config set KEY VAL # Set a specific value
hermes config check # Check for missing options (after updates)
hermes config migrate # Interactively add missing options
# Examples:
hermes config set model anthropic/claude-opus-4
hermes config set terminal.backend docker
hermes config set OPENROUTER_API_KEY sk-or-... # Saves to .env
```
### Optional API Keys
| Feature | Provider | Env Variable |
|---------|----------|--------------|
| Web scraping | [Firecrawl](https://firecrawl.dev/) | `FIRECRAWL_API_KEY` |
| Browser automation | [Browserbase](https://browserbase.com/) | `BROWSERBASE_API_KEY`, `BROWSERBASE_PROJECT_ID` |
| Image generation | [FAL](https://fal.ai/) | `FAL_KEY` |
| Premium TTS voices | [ElevenLabs](https://elevenlabs.io/) | `ELEVENLABS_API_KEY` |
| OpenAI TTS + voice transcription | [OpenAI](https://platform.openai.com/api-keys) | `VOICE_TOOLS_OPENAI_KEY` |
| RL Training | [Tinker](https://tinker-console.thinkingmachines.ai/) + [WandB](https://wandb.ai/) | `TINKER_API_KEY`, `WANDB_API_KEY` |
---
## Messaging Gateway
Chat with Hermes from Telegram, Discord, Slack, or WhatsApp. The gateway is a single background process that connects to all your configured platforms, handles sessions, runs cron jobs, and delivers voice messages.
### Starting the Gateway
```bash
hermes gateway # Run in foreground
hermes gateway install # Install as systemd service (Linux)
hermes gateway start # Start the systemd service
hermes gateway stop # Stop the systemd service
hermes gateway status # Check service status
```
The installer will offer to set this up automatically if it detects a bot token.
### Telegram Setup
1. **Create a bot:** Message [@BotFather](https://t.me/BotFather) on Telegram, use `/newbot`
2. **Get your user ID:** Message [@userinfobot](https://t.me/userinfobot) — it replies with your numeric ID
3. **Configure:**
```bash
# Add to ~/.hermes/.env:
TELEGRAM_BOT_TOKEN=123456:ABC-DEF...
TELEGRAM_ALLOWED_USERS=YOUR_USER_ID # Comma-separated for multiple users
```
4. **Start the gateway:** `hermes gateway`
### Discord Setup
1. **Create a bot:** Go to [Discord Developer Portal](https://discord.com/developers/applications)
2. **Enable intents:** Bot → Privileged Gateway Intents → enable Message Content Intent
3. **Get your user ID:** Enable Developer Mode in Discord settings, right-click your name → Copy ID
4. **Invite to your server:** OAuth2 → URL Generator → scopes: `bot`, `applications.commands` → permissions: Send Messages, Read Message History, Attach Files
5. **Configure:**
```bash
# Add to ~/.hermes/.env:
DISCORD_BOT_TOKEN=MTIz...
DISCORD_ALLOWED_USERS=YOUR_USER_ID
```
### Slack Setup
1. **Create an app:** Go to [Slack API](https://api.slack.com/apps), create a new app
2. **Enable Socket Mode:** In app settings → Socket Mode → Enable
3. **Get tokens:**
- Bot Token (`xoxb-...`): OAuth & Permissions → Install to Workspace
- App Token (`xapp-...`): Basic Information → App-Level Tokens → Generate
4. **Configure:**
```bash
# Add to ~/.hermes/.env:
SLACK_BOT_TOKEN=xoxb-...
SLACK_APP_TOKEN=xapp-...
SLACK_ALLOWED_USERS=U01234ABCDE # Comma-separated Slack user IDs
```
### WhatsApp Setup
WhatsApp doesn't have a simple bot API like Telegram or Discord. Hermes supports two approaches:
**Option A — WhatsApp Business API** (requires [Meta Business verification](https://business.facebook.com/)):
- Production-grade, but requires a verified business account
- Set `WHATSAPP_ENABLED=true` in `~/.hermes/.env` and configure the Business API credentials
**Option B — whatsapp-web.js bridge** (personal accounts):
1. Install Node.js if not already present
2. Set up the bridge:
```bash
# Add to ~/.hermes/.env:
WHATSAPP_ENABLED=true
WHATSAPP_ALLOWED_USERS=YOUR_PHONE_NUMBER # e.g. 15551234567
```
3. On first launch, the gateway will display a QR code — scan it with WhatsApp on your phone to link the session
See [docs/messaging.md](docs/messaging.md) for advanced WhatsApp configuration.
### Gateway Commands (inside chat)
| Command | Description |
|---------|-------------|
| `/new` or `/reset` | Start fresh conversation |
| `/model [name]` | Show or change the model |
| `/personality [name]` | Set a personality |
| `/retry` | Retry the last message |
| `/undo` | Remove the last exchange |
| `/status` | Show session info |
| `/stop` | Stop the running agent |
| `/sethome` | Set this chat as the home channel |
| `/help` | Show available commands |
### DM Pairing (Alternative to Allowlists)
Instead of manually configuring user IDs in allowlists, you can use the pairing system. When an unknown user DMs your bot, they receive a one-time pairing code:
```bash
# The user sees: "Pairing code: XKGH5N7P"
# You approve them with:
hermes pairing approve telegram XKGH5N7P
# Other pairing commands:
hermes pairing list # View pending + approved users
hermes pairing revoke telegram 123456789 # Remove access
```
Pairing codes expire after 1 hour, are rate-limited, and use cryptographic randomness.
### Security
**By default, the gateway denies all users who are not in an allowlist or paired via DM.** This is the safe default for a bot with terminal access.
```bash
# Restrict to specific users (recommended):
TELEGRAM_ALLOWED_USERS=123456789,987654321
DISCORD_ALLOWED_USERS=123456789012345678
# Or explicitly allow all users (NOT recommended for bots with terminal access):
GATEWAY_ALLOW_ALL_USERS=true
```
### Working Directory
| Context | Default |
|---------|---------|
| **CLI (`hermes`)** | Current directory where you run the command |
| **Messaging gateway** | Home directory `~` (override with `MESSAGING_CWD`) |
| **Docker / Singularity / Modal / SSH** | User's home directory (`~`) inside the container or remote machine |
Override the terminal working directory for any backend:
```bash
# In ~/.hermes/.env or ~/.hermes/config.yaml:
MESSAGING_CWD=/home/myuser/projects # Gateway sessions
TERMINAL_CWD=/workspace # All terminal sessions (local or container)
```
### Tool Progress Notifications
Get real-time updates as the agent works:
```bash
# Enable in ~/.hermes/.env
HERMES_TOOL_PROGRESS=true
HERMES_TOOL_PROGRESS_MODE=all # or "new" for only when tool changes
```
---
## Commands
```bash
# Chat
hermes # Interactive chat (default)
hermes chat -q "Hello" # Single query mode
# Provider & model management
hermes model # Switch provider and model interactively
hermes login # Authenticate with Nous Portal (OAuth)
hermes logout # Clear stored OAuth credentials
# Configuration
hermes setup # Full setup wizard (provider, terminal, messaging, etc.)
hermes config # View/edit configuration
hermes config check # Check for missing config (useful after updates)
hermes config migrate # Interactively add missing options
hermes status # Show configuration status (incl. auth)
hermes doctor # Diagnose issues
# Maintenance
hermes update # Update to latest version
hermes uninstall # Uninstall (can keep configs for later reinstall)
# Gateway (messaging + cron scheduler)
hermes gateway # Run gateway in foreground
hermes gateway install # Install as system service (messaging + cron)
hermes gateway status # Check service status
# Skills, cron, misc
hermes skills search k8s # Search skill registries
hermes skills install ... # Install a skill (with security scan)
hermes skills list # List installed skills
hermes cron list # View scheduled jobs
hermes cron status # Check if cron scheduler is running
hermes pairing list # View/manage DM pairing codes
hermes version # Show version info
```
### CLI Commands (inside chat)
Type `/` to see an autocomplete dropdown of all commands.
| Command | Description |
|---------|-------------|
| `/help` | Show available commands |
| `/tools` | List available tools |
| `/toolsets` | List available toolsets |
| `/model [name]` | Show or change model |
| `/prompt` | View/set custom system prompt |
| `/personality [name]` | Set personality (kawaii, pirate, etc.) |
| `/clear` | Clear screen and reset conversation |
| `/history` | Show conversation history |
| `/reset` | Reset conversation only (keep screen) |
| `/retry` | Retry the last message |
| `/undo` | Remove the last exchange |
| `/save` | Save the current conversation |
| `/config` | Show current configuration |
| `/cron` | Manage scheduled tasks |
| `/skills` | Search, install, inspect, or manage skills from registries |
| `/platforms` | Show gateway/messaging platform status |
| `/quit` | Exit (also: `/exit`, `/q`) |
**Keybindings:**
- `Enter` — send message
- `Alt+Enter` or `Ctrl+J` — new line (multi-line input)
- `Ctrl+C` — interrupt agent (double-press to force exit)
- `Ctrl+D` — exit
### Interrupting the Agent
**CLI:**
- Type a message + Enter while the agent is working to interrupt and send new instructions
- `Ctrl+C` to interrupt (press twice within 2s to force exit)
- In-progress terminal commands are killed immediately (SIGTERM, then SIGKILL after 1s if the process resists)
- Multiple messages typed during interrupt are combined into one prompt
**Messaging Platforms (Telegram, Discord, Slack):**
- Send any message while the agent is working to interrupt
- Use `/stop` to interrupt without queuing a follow-up message
- Multiple messages sent during interrupt are combined into one prompt
- Interrupt signals are processed with highest priority (before command parsing)
---
## Features
### 🛠️ Tools & Toolsets
Tools are organized into logical **toolsets**:
```bash
# Use specific toolsets
hermes --toolsets "web,terminal"
# List all toolsets
hermes --list-tools
```
**Available toolsets:** `web`, `terminal`, `file`, `browser`, `vision`, `image_gen`, `moa`, `skills`, `tts`, `todo`, `memory`, `session_search`, `cronjob`, `code_execution`, `delegation`, `clarify`, and more.
### 🖥️ Terminal & Process Management
The terminal tool can execute commands in different environments, with full background process management via the `process` tool:
**Background processes:** Start with `terminal(command="...", background=true)`, then use `process(action="poll/wait/log/kill/write")` to monitor, wait for completion, read output, terminate, or send input. The `wait` action blocks until the process finishes -- no polling loops needed. PTY mode (`pty=true`) enables interactive CLI tools like Codex and Claude Code.
**Execution environments:**
| Backend | Description | Use Case |
|---------|-------------|----------|
| `local` | Run on your machine (default) | Development, trusted tasks |
| `docker` | Isolated containers | Security, reproducibility |
| `ssh` | Remote server | Sandboxing, keep agent away from its own code |
| `singularity` | HPC containers | Cluster computing, rootless |
| `modal` | Cloud execution | Serverless, scale |
**Configure in `~/.hermes/config.yaml`:**
```yaml
terminal:
backend: local # or: docker, ssh, singularity, modal
cwd: "." # Working directory ("." = current dir)
timeout: 180 # Command timeout in seconds
```
**Docker Backend:**
```yaml
terminal:
backend: docker
docker_image: python:3.11-slim
```
**SSH Backend** (recommended for security - agent can't modify its own code):
```yaml
terminal:
backend: ssh
```
```bash
# Set credentials in ~/.hermes/.env
TERMINAL_SSH_HOST=my-server.example.com
TERMINAL_SSH_USER=myuser
TERMINAL_SSH_KEY=~/.ssh/id_rsa
```
**Singularity/Apptainer** (for HPC clusters):
```bash
# Pre-build SIF for parallel workers
apptainer build ~/python.sif docker://python:3.11-slim
# Configure
hermes config set terminal.backend singularity
hermes config set terminal.singularity_image ~/python.sif
```
**Modal** (serverless cloud):
```bash
uv pip install "swe-rex[modal]" # Installs swe-rex + modal + boto3
modal setup # Authenticate with Modal
hermes config set terminal.backend modal
```
**Sudo Support:** If a command needs sudo, you'll be prompted for your password (cached for the session). Or set `SUDO_PASSWORD` in `~/.hermes/.env`.
**Container Security (Docker, Singularity, Modal):**
All container backends run with security hardening by default:
- Read-only root filesystem (Docker)
- All Linux capabilities dropped
- No privilege escalation (`--security-opt no-new-privileges`)
- PID limits (256 processes)
- Full namespace isolation (`--containall` for Singularity)
- Persistent workspace via volumes, not writable root layer
**Container Resources:**
Configure CPU, memory, disk, and persistence for all container backends:
```yaml
# In ~/.hermes/config.yaml under terminal:
terminal:
backend: docker # or singularity, modal
container_cpu: 1 # CPU cores (default: 1)
container_memory: 5120 # Memory in MB (default: 5GB)
container_disk: 51200 # Disk in MB (default: 50GB)
container_persistent: true # Persist filesystem across sessions (default: true)
```
When `container_persistent: true`, the sandbox state (installed packages, files, config) survives across sessions. Docker uses bind mounts, Singularity uses persistent overlays, and Modal uses filesystem snapshots. All persistent data is stored under `TERMINAL_SANDBOX_DIR` (default: `~/.hermes/sandboxes/`):
```bash
# Override where Docker workspaces and Singularity overlays/SIF cache are stored
TERMINAL_SANDBOX_DIR=/mnt/fast-ssd/hermes-sandboxes
```
### 🧠 Persistent Memory
Bounded curated memory that persists across sessions:
- **MEMORY.md** — agent's personal notes (environment facts, conventions, things learned). ~800 token budget.
- **USER.md** — user profile (preferences, communication style, expectations). ~500 token budget.
Both are injected into the system prompt as a frozen snapshot at session start. The agent manages its own memory via the `memory` tool (add/replace/remove/read). Character limits keep memory focused — when full, the agent consolidates or replaces entries.
Configure in `~/.hermes/config.yaml`:
```yaml
memory:
memory_enabled: true
user_profile_enabled: true
memory_char_limit: 2200 # ~800 tokens
user_char_limit: 1375 # ~500 tokens
```
### 📄 Context Files (SOUL.md, AGENTS.md, .cursorrules)
Drop these files in your project directory and the agent automatically picks them up:
| File | Purpose |
|------|---------|
| `AGENTS.md` | Project-specific instructions, coding conventions, tool usage guidelines |
| `SOUL.md` | Persona definition -- the agent embodies this personality and tone |
| `.cursorrules` | Cursor IDE rules (also detected) |
| `.cursor/rules/*.mdc` | Cursor rule files (also detected) |
- **AGENTS.md** is hierarchical: if subdirectories also have `AGENTS.md`, all are combined (like Codex/Cline).
- **SOUL.md** checks cwd first, then `~/.hermes/SOUL.md` as a global fallback.
- All context files are capped at 20,000 characters with smart truncation.
### 🗜️ Context Compression
Long conversations are automatically summarized when approaching context limits:
```yaml
# In ~/.hermes/config.yaml
compression:
enabled: true
threshold: 0.85 # Compress at 85% of limit
```
### 🗄️ Session Store
All CLI and messaging sessions are stored in a SQLite database (`~/.hermes/state.db`) with full-text search:
- **Full message history** stored per-session with model config and system prompt snapshots
- **FTS5 search** via the `session_search` tool -- search past conversations with Gemini Flash summarization
- **Compression-triggered session splitting** -- when context is compressed, a new session is created linked to the parent, giving clean trajectories
- **Source tagging** -- each session is tagged with its origin (cli, telegram, discord, etc.)
- Batch runner and RL trajectories are NOT stored here (separate systems)
### 📝 Session Logging
Every conversation is logged to `~/.hermes/sessions/` for debugging:
```
sessions/
├── session_20260201_143052_a1b2c3.json
└── ...
```
### ⏰ Scheduled Tasks (Cron)
Schedule tasks to run automatically:
```bash
# In the CLI (/cron slash commands)
/cron add 30m "Remind me to check the build"
/cron add "every 2h" "Check server status"
/cron add "0 9 * * *" "Morning briefing"
/cron list
/cron remove