nix-hermes-agent

July 14, 2026 · View on GitHub

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

  1. services.hermes-agent.config attrset is deep-merged and rendered to cli-config.yaml
  2. Documents are installed into the workspace directory
  3. Secrets stay outside the Nix store via environmentFiles
  4. systemd service runs hermes gateway with 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.bundled
  • services.hermes-agent.skills.optional
  • services.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-mcp via Hermes CLI

On the next rebuild, the Nix-declared version is restored.

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:

  1. install/try a skill interactively,
  2. decide it is worth keeping,
  3. 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

OptionTypeDefaultDescription
enableboolfalseEnable Hermes Agent gateway
configattrset{}Declarative config (→ cli-config.yaml)
configFilepathnullUse existing config file (overrides config)
documentsattrset{}Workspace files (string or path values)
skillsattrset{}Declarative Hermes skills (bundled, optional, custom local)
environmentFileslist[]Secret env files (systemd EnvironmentFile)
environmentattrset{}Non-secret env vars
authFilepathnullOAuth credentials file (auth.json)
mcpServersattrset{}MCP server configs (merged into config)
userstring"hermes"Service user
groupstring"hermes"Service group
stateDirpath/var/lib/hermesState directory
workingDirectorypath${stateDir}/workspaceWorking directory
extraPackageslist[]Extra packages on PATH
extraArgslist[]Extra hermes gateway args
logPathpath${stateDir}/logs/gateway.logLog file
restartstring"always"systemd Restart policy
restartSecint5Restart delay

Config Reference

The config attrset maps directly to Hermes' cli-config.yaml. Key sections:

SectionPurpose
modelDefault model, provider, base_url
terminalBackend (local/ssh/docker/modal), cwd, timeout
agentmax_turns, verbose, reasoning_effort, personalities
memorymemory_enabled, user_profile_enabled, char limits
compressionContext compression settings
session_resetAuto-reset policy for messaging
skillsSkill creation nudge settings
toolsetsWhich tool groups to enable
mcp_serversMCP server connections
delegationSubagent settings
browserBrowser tool settings
sttVoice transcription config
displayUI/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)