0xrsydn/nix-hermes-agent
Nix package and NixOS module for Hermes Agent by Nous Research
nix-hermes-agent provides a Nix package and NixOS module for the declarative deployment of Hermes Agent. It allows users to manage the entire agent lifecycle—including configurations, workspace documents, and systemd services—through a single Nix configuration file. The module features a robust update policy that uses quarantined candidate pull requests to prevent broken upstream releases from affecting stable deployments. It also supports secure secrets management by keeping API keys and authentication tokens outside of the Nix store.
- Declarative configuration for cli-config.yaml and workspace documents
- Hybrid skill management supporting both Nix-managed and CLI-installed skills
- Secure secrets integration via systemd EnvironmentFiles and sops-nix
full readme from github
nix-hermes-agent
Declarative Nix package and NixOS module for Hermes Agent by Nous Research.
Everything is configured in Nix. Config, documents, secrets, service — one nixos-rebuild switch and it's live.
Upstream pins are promoted through quarantined candidate PRs so a broken Hermes release cannot replace the last-known-good package. See the upstream update policy.
Quick Start
1. Add to your flake
{
inputs.nix-hermes.url = "github:0xrsydn/nix-hermes-agent";
outputs = { self, nixpkgs, nix-hermes, ... }: {
nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
modules = [
nix-hermes.nixosModules.hermes-agent
./hermes.nix # your config (see below)
];
};
};
}
2. Configure declaratively
# hermes.nix
{ ... }:
{
services.hermes-agent = {
enable = true;
# ── Declarative config (renders to cli-config.yaml) ──
config = {
model = {
default = "anthropic/claude-opus-4.6";
provider = "openrouter";
};
terminal = {
backend = "local";
timeout = 180;
lifetime_seconds = 300;
};
agent = {
max_turns = 60;
reasoning_effort = "medium";
};
memory = {
memory_enabled = true;
user_profile_enabled = true;
memory_char_limit = 2200;
nudge_interval = 10;
};
compression = {
enabled = true;
threshold = 0.85;
summary_model = "google/gemini-3-flash-preview";
};
toolsets = [ "all" ];
};
# ── Secrets (not in Nix store) ──
environmentFiles = [
"/run/secrets/hermes-env" # ANTHROPIC_API_KEY, TELEGRAM_TOKEN, etc.
];
# ── Non-secret env vars ──
environment = {
LLM_MODEL = "anthropic/claude-opus-4.6";
};
# ── Workspace documents (inline or file paths) ──
documents = {
"SOUL.md" = ''
# SOUL.md
You are a sharp, pragmatic AI assistant.
'';
"AGENTS.md" = ''
# AGENTS.md
Read SOUL.md first. Then help the user.
'';
"USER.md" = ''
# USER.md
Name: Your Human
'';
# Or reference a file:
# "SOUL.md" = ./documents/SOUL.md;
};
# ── Declarative skills (phase 1) ──
skills = {
bundled.enable = true;
optional = [
"creative/blender-mcp"
];
custom = {
repo-watch = {
category = "research";
source = ./skills/repo-watch;
};
};
};
# ── MCP servers ──
mcpServers = {
context7 = {
command = "npx";
args = [ "-y" "@upstash/context7-mcp@latest" ];
};
};
# ── Extra tools on PATH ──
extraPackages = with pkgs; [ jq ripgrep curl ];
};
}
Secrets Management
Plain files approach
services.hermes-agent = {
environmentFiles = [ "/run/secrets/hermes-env" ];
authFile = "/run/secrets/hermes-auth.json"; # optional, for OAuth tokens
};
sops-nix approach
sops.secrets."hermes/env" = {
sopsFile = ./secrets/hermes.yaml;
owner = "hermes";
group = "hermes";
};
sops.secrets."hermes/auth" = {
sopsFile = ./secrets/hermes.yaml;
owner = "hermes";
group = "hermes";
};
services.hermes-agent = {
enable = true;
environmentFiles = [ config.sops.secrets."hermes/env".path ];
authFile = config.sops.secrets."hermes/auth".path;
config.model = {
default = "anthropic/claude-opus-4.6";
provider = "openrouter";
};
};
Example secrets file structure
hermes/env: |
OPENROUTER_API_KEY=sk-or-...
ANTHROPIC_API_KEY=sk-ant-...
TELEGRAM_TOKEN=123456:ABC...
GLM_API_KEY=...
hermes/auth: |
{"nous": {"token": "...", "refresh": "..."}, "codex": {"token": "..."}}
3. Create secrets file
# /run/secrets/hermes-env (or wherever you manage secrets)
OPENROUTER_API_KEY=sk-or-...
ANTHROPIC_API_KEY=sk-ant-...
TELEGRAM_TOKEN=123456:ABC...
TELEGRAM_ALLOWED_USERS=your_user_id
4. Deploy
nixos-rebuild switch
systemctl status hermes-agent
journalctl -u hermes-agent -f
Architecture
You (Telegram/Discord/WhatsApp/Slack) → Gateway → Tools → Machine does things
How it works
services.hermes-agent.configattrset is deep-merged and rendered tocli-config.yaml- Documents are installed into the workspace directory
- Secrets stay outside the Nix store via
environmentFiles - systemd service runs
hermes gatewaywith everything wired up
Directory layout
/var/lib/hermes/ # stateDir
├── .hermes/ # Hermes home (HERMES_HOME)
│ ├── cli-config.yaml # Generated from config option
│ ├── .env # Secrets (from environmentFiles)
│ ├── memory/ # Agent memory (runtime)
│ ├── skills/ # Skills (runtime)
│ └── logs/ # Session logs
├── workspace/ # workingDirectory
│ ├── SOUL.md # From documents option
│ ├── AGENTS.md
│ └── USER.md
└── logs/
└── gateway.log # Service log
Declarative Skills vs Native Hermes Skills
The skills option is designed to augment Hermes, not replace Hermes' native skill workflow.
Both approaches compose into the same runtime directory:
${stateDir}/.hermes/skills/
That means you can use both:
- declarative skills from Nix
- interactive/runtime skills from
hermes skills install
Ownership model
Nix-managed
Skills declared via:
services.hermes-agent.skills.bundledservices.hermes-agent.skills.optionalservices.hermes-agent.skills.custom
are reconciled by the module and tracked in:
.nix-managed-skills.json
These paths are considered owned by Nix.
Hermes-managed
Skills installed later via Hermes CLI, plus hub metadata under:
.hermes/skills/.hub/
are left alone by the module unless they collide with a Nix-managed path.
Collision rule
If a Hermes CLI install and a declarative Nix skill target the same installed path, the declarative Nix version wins on the next activation/rebuild.
Example:
- Nix declares
creative/blender-mcp - user later installs another
creative/blender-mcpvia Hermes CLI
On the next rebuild, the Nix-declared version is restored.
Recommended workflow
Use Hermes CLI for:
- experimentation
- hub/community skill discovery
- temporary installs
- trying before keeping
Use Nix declarative skills for:
- stable/reproducible deployments
- bundled upstream skills you always want
- selected optional skills you want pinned to the package revision
- local custom house skills stored in git
A good pattern is:
- install/try a skill interactively,
- decide it is worth keeping,
- promote it into Nix config if you want it reproducible.
This keeps nix-hermes-agent useful without interfering with the native Hermes experience.
Module Options
| Option | Type | Default | Description |
|---|---|---|---|
enable |
bool | false |
Enable Hermes Agent gateway |
config |
attrset | {} |
Declarative config (→ cli-config.yaml) |
configFile |
path | null |
Use existing config file (overrides config) |
documents |
attrset | {} |
Workspace files (string or path values) |
skills |
attrset | {} |
Declarative Hermes skills (bundled, optional, custom local) |
environmentFiles |
list | [] |
Secret env files (systemd EnvironmentFile) |
environment |
attrset | {} |
Non-secret env vars |
authFile |
path | null |
OAuth credentials file (auth.json) |
mcpServers |
attrset | {} |
MCP server configs (merged into config) |
user |
string | "hermes" |
Service user |
group |
string | "hermes" |
Service group |
stateDir |
path | /var/lib/hermes |
State directory |
workingDirectory |
path | ${stateDir}/workspace |
Working directory |
extraPackages |
list | [] |
Extra packages on PATH |
extraArgs |
list | [] |
Extra hermes gateway args |
logPath |
path | ${stateDir}/logs/gateway.log |
Log file |
restart |
string | "always" |
systemd Restart policy |
restartSec |
int | 5 |
Restart delay |
Config Reference
The config attrset maps directly to Hermes' cli-config.yaml. Key sections:
| Section | Purpose |
|---|---|
model |
Default model, provider, base_url |
terminal |
Backend (local/ssh/docker/modal), cwd, timeout |
agent |
max_turns, verbose, reasoning_effort, personalities |
memory |
memory_enabled, user_profile_enabled, char limits |
compression |
Context compression settings |
session_reset |
Auto-reset policy for messaging |
skills |
Skill creation nudge settings |
toolsets |
Which tool groups to enable |
mcp_servers |
MCP server connections |
delegation |
Subagent settings |
browser |
Browser tool settings |
stt |
Voice transcription config |
display |
UI/skin settings |
See the full config reference.
Just the Package
# Run directly
nix run github:0xrsydn/nix-hermes-agent -- --help
# In a dev shell
nix develop github:0xrsydn/nix-hermes-agent
# Use the overlay
nixpkgs.overlays = [ nix-hermes.overlays.default ];
License
MIT (same as upstream)