Problem
There is no declarative way to install third-party hermes plugins in a NixOS-managed deployment. The Nix package builds a sealed Python venv via uv2nix with all deps baked in at build time. The existing extraPackages option only adds to the systemd service PATH, not the Python environment.
This means:
- Pip-packaged plugins using
importlib.metadata entry points (group hermes_agent.plugins) can't be discovered — they're not on sys.path
- Directory-based plugins in
~/.hermes/plugins/ work for simple cases, but anything with Python dependencies fails because those deps aren't in the sealed venv
- Users are left with workarounds: imperative
hermes plugins install, manual PYTHONPATH hacks, or pip install inside a container
Proposed solution
Two-tier approach:
Tier 1: extraPythonPackages (pure Nix)
For plugin authors who ship Nix packaging. Uses overlay + callPackage to make the hermes package overridable:
services.hermes-agent.package = pkgs.hermes-agent.override {
extraPythonPackages = [
(pkgs.python312Packages.buildPythonPackage { ... })
];
};
The wrapper injects these onto PYTHONPATH via makeSearchPath. The base uv2nix venv stays sealed.
Prerequisites:
Tier 2: extraPlugins (uv-managed, impure)
For any pip/git plugin — the path that actually matters for the community. The NixOS activation script uses uv to install plugins into a sidecar venv:
services.hermes-agent = {
extraPlugins = [
"hermes-lcm"
"git+https://github.com/user/hermes-some-plugin"
];
};
At activation time:
uv venv creates a sidecar venv using the same Python as the base package
uv pip install resolves and installs each plugin's dependency tree
- The wrapper adds the sidecar venv's site-packages to PYTHONPATH
importlib.metadata.entry_points() discovers the plugins
This is impure (hits the network at activation time) but is the only realistic path for plugins that are just a GitHub repo with a pyproject.toml.
Prior art
Scope
Problem
There is no declarative way to install third-party hermes plugins in a NixOS-managed deployment. The Nix package builds a sealed Python venv via uv2nix with all deps baked in at build time. The existing
extraPackagesoption only adds to the systemd service PATH, not the Python environment.This means:
importlib.metadataentry points (grouphermes_agent.plugins) can't be discovered — they're not onsys.path~/.hermes/plugins/work for simple cases, but anything with Python dependencies fails because those deps aren't in the sealed venvhermes plugins install, manual PYTHONPATH hacks, orpip installinside a containerProposed solution
Two-tier approach:
Tier 1:
extraPythonPackages(pure Nix)For plugin authors who ship Nix packaging. Uses overlay +
callPackageto make the hermes package overridable:The wrapper injects these onto PYTHONPATH via
makeSearchPath. The base uv2nix venv stays sealed.Prerequisites:
callPackage-able derivation (see feat(nix): add overlay and make package overridable #7229 for prior art)nix/overlays.nixexposingpkgs.hermes-agentextraPythonPackagesparameter to the package derivationTier 2:
extraPlugins(uv-managed, impure)For any pip/git plugin — the path that actually matters for the community. The NixOS activation script uses
uvto install plugins into a sidecar venv:At activation time:
uv venvcreates a sidecar venv using the same Python as the base packageuv pip installresolves and installs each plugin's dependency treeimportlib.metadata.entry_points()discovers the pluginsThis is impure (hits the network at activation time) but is the only realistic path for plugins that are just a GitHub repo with a
pyproject.toml.Prior art
extraPython3Packages, qutebrowser'sextraPythonPackages— same PYTHONPATH injection patternScope
callPackage-ablenix/hermes-agent.nixnix/overlays.nix+ wire intoflake.nixextraPythonPackagesparameter (tier 1)extraPluginsNixOS module option + activation script (tier 2)