feat(nix): container-aware CLI — auto-route into managed container - #7543
Conversation
|
|
fixes #7380 |
|
@BugBot review |
PR SummaryMedium Risk Overview Extends the NixOS module with Adds comprehensive unit tests for container detection/metadata parsing/exec retry logic and updates Nix setup docs to describe routing behavior, Reviewed by Cursor Bugbot for commit 38277a6. Configure here. |
|
this branch currently does not seem to work for me. error: Cannot build '/nix/store/07q2i2awg59mdhjdshj5533g0s6m8fsg-atomicwrites-1.4.1.drv'.
Reason: builder failed with exit code 2.
Output paths:
/nix/store/v766f9izcyprbrmqj0hrc558s0wc16lq-atomicwrites-1.4.1
Last 25 log lines:
> DEBUG Proceeding without build isolation
> DEBUG Locking the source tree for setuptools
> DEBUG Acquired exclusive lock for `/build/atomicwrites-1.4.1`
> DEBUG Calling `setuptools.build_meta:__legacy__.build_wheel("/build/atomicwrites-1.4.1/dist/", {}, None)`
> Traceback (most recent call last):
> File "<string>", line 8, in <module>
> ModuleNotFoundError: No module named 'setuptools'
> DEBUG Released lock at `/build/uv-setuptools-91b6cf3c668b19dd.lock`
> x Failed to build `/build/atomicwrites-1.4.1`
> |-> The build backend returned an error
> `-> Call to `setuptools.build_meta:__legacy__.build_wheel` failed (exit
> status: 1)
>
> hint: This error likely indicates that `atomicwrites-1.4.1` depends
> on `setuptools`, but doesn't declare it as a build dependency.
> If `atomicwrites-1.4.1` is a first-party package, consider adding
> `setuptools` to its `build-system.requires`. Otherwise, either add it to
> your `pyproject.toml` under:
>
> [tool.uv.extra-build-dependencies]
> "atomicwrites-1.4.1" = ["setuptools"]
>
> or `uv pip install setuptools` into the environment and re-run with
> `--no-build-isolation`.
> DEBUG Released lock at `/build/.tmpGVjimy/.lock`If I cherry-pick #7513, the build completes without this failure. After that, Error: no container with name or ID "hermes-agent" found: no such containerMy container = {
enable = true;
image = "localhost/hermes-research:2026-04-09-v1";
backend = "podman";
extraVolumes = [ "/srv/projects:/projects:rw" ];
};From my user account, Podman shows no running containers: [xxx@xxx]$ podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMESBut the container does exist under [xxx@xxx]$ sudo podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1b6816c1671a localhost/hermes-research:2026-04-09-v1 /data/current-pac... 11 hours ago Up 11 minutes hermes-agentSo the managed container is running as root, not under my user. If I start a separate container under my own user with: podman run -d --name hermes-agent --replace localhost/hermes-research:2026-04-09-v1 sleep infinitythen Error: unable to find user hermes: no matching entries in passwd filei'll wait to hear thoughts before going further -- can do some more tests if helpful |
|
rebased off main to include #7518 -- still got the Error: no container with name or ID "hermes-agent" found: no such container |
40dc41c to
ac809a7
Compare
|
78783f0 to
2816de8
Compare
|
…ged container When container.enable = true, the host `hermes` CLI transparently execs every subcommand into the managed Docker/Podman container. A symlink bridge (~/.hermes -> /var/lib/hermes/.hermes) unifies state between host and container so sessions, config, and memories are shared. CLI changes: - Global routing before subcommand dispatch (all commands forwarded) - docker exec with -u exec_user, env passthrough (TERM, COLORTERM, LANG, LC_ALL), TTY-aware flags - Retry with spinner on failure (TTY: 5s, non-TTY: 10s silent) - Hard fail instead of silent fallback - HERMES_DEV=1 env var bypasses routing for development - No routing messages (invisible to user) NixOS module changes: - container.hostUsers option: lists users who get ~/.hermes symlink and automatic hermes group membership - Activation script creates symlink bridge (with backup of existing ~/.hermes dirs), writes exec_user to .container-mode - Cleanup on disable: removes symlinks + .container-mode + stops service - Warning when hostUsers set without addToSystemPackages
2816de8 to
79e8cd1
Compare
|
|
@nousr thanks for testing! Both issues are now addressed in the latest push ( 1. atomicwrites build failure — This was because the branch predated #7488 (mautrix migration). Now rebased on main which includes that fix, so 2. Podman "no container with name or ID" error — This is a Podman rootful vs rootless namespace issue. The NixOS systemd service runs the container as root, but The CLI now probes whether the runtime can see the container. If it can't, it tries Add this to your NixOS config and rebuild: security.sudo.extraRules = [{
users = [ "nousr" ];
commands = [{
command = "/run/current-system/sw/bin/podman";
options = [ "NOPASSWD" ];
}];
}];After that, 3. "unable to find user hermes" — Also fixed. The exec function now uses |
|
@BugBot review |
- hermes_cli/main.py: reuse the existing `sudo` variable instead of
redundant `shutil.which("sudo")` call that could return None
- nix/nixosModules.nix: add missing `chown -h` when updating an
existing symlink target so ownership stays consistent with the
fresh-create and backup-replace branches
|
|
@BugBot review |
- hermes_cli/main.py: move container routing BEFORE parse_args() so
--help, unrecognised flags, and all subcommands are forwarded
transparently into the container instead of being intercepted by
argparse on the host (high severity)
- nix/nixosModules.nix: resolve home dirs via
config.users.users.${user}.home instead of hardcoding /home/${user},
supporting users with custom home directories (medium severity)
- nix/nixosModules.nix: gate hostUsers group membership on
container.enable so setting hostUsers without container mode doesn't
silently add users to the hermes group (low severity)
|
- Replace subprocess.run retry loop with os.execvp (no idle parent process) - Extract _probe_container helper for sudo detection with 15s timeout - Narrow exception handling: FileNotFoundError only in get_container_exec_info, catch TimeoutExpired specifically, remove silent except Exception: pass - Collapse needs_sudo + sudo into single sudo_path variable - Simplify NixOS symlink creation from 4 branches to 2 - Gate NixOS sudoers hint with "On NixOS:" prefix - Full test rewrite: 18 tests covering execvp, sudo probe, timeout, permissions
|
|
@BugBot review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit e793c70. Configure here.
…ousResearch#7543) * feat(nix): container-aware CLI — auto-route all subcommands into managed container When container.enable = true, the host `hermes` CLI transparently execs every subcommand into the managed Docker/Podman container. A symlink bridge (~/.hermes -> /var/lib/hermes/.hermes) unifies state between host and container so sessions, config, and memories are shared. CLI changes: - Global routing before subcommand dispatch (all commands forwarded) - docker exec with -u exec_user, env passthrough (TERM, COLORTERM, LANG, LC_ALL), TTY-aware flags - Retry with spinner on failure (TTY: 5s, non-TTY: 10s silent) - Hard fail instead of silent fallback - HERMES_DEV=1 env var bypasses routing for development - No routing messages (invisible to user) NixOS module changes: - container.hostUsers option: lists users who get ~/.hermes symlink and automatic hermes group membership - Activation script creates symlink bridge (with backup of existing ~/.hermes dirs), writes exec_user to .container-mode - Cleanup on disable: removes symlinks + .container-mode + stops service - Warning when hostUsers set without addToSystemPackages * fix: address review — reuse sudo var, add chown -h on symlink update - hermes_cli/main.py: reuse the existing `sudo` variable instead of redundant `shutil.which("sudo")` call that could return None - nix/nixosModules.nix: add missing `chown -h` when updating an existing symlink target so ownership stays consistent with the fresh-create and backup-replace branches * fix: address remaining review items from cursor bugbot - hermes_cli/main.py: move container routing BEFORE parse_args() so --help, unrecognised flags, and all subcommands are forwarded transparently into the container instead of being intercepted by argparse on the host (high severity) - nix/nixosModules.nix: resolve home dirs via config.users.users.${user}.home instead of hardcoding /home/${user}, supporting users with custom home directories (medium severity) - nix/nixosModules.nix: gate hostUsers group membership on container.enable so setting hostUsers without container mode doesn't silently add users to the hermes group (low severity) * fix: simplify container routing — execvp, no retries, let it crash - Replace subprocess.run retry loop with os.execvp (no idle parent process) - Extract _probe_container helper for sudo detection with 15s timeout - Narrow exception handling: FileNotFoundError only in get_container_exec_info, catch TimeoutExpired specifically, remove silent except Exception: pass - Collapse needs_sudo + sudo into single sudo_path variable - Simplify NixOS symlink creation from 4 branches to 2 - Gate NixOS sudoers hint with "On NixOS:" prefix - Full test rewrite: 18 tests covering execvp, sudo probe, timeout, permissions --------- Co-authored-by: Hermes Agent <hermes@nousresearch.com>
…ousResearch#7543) * feat(nix): container-aware CLI — auto-route all subcommands into managed container When container.enable = true, the host `hermes` CLI transparently execs every subcommand into the managed Docker/Podman container. A symlink bridge (~/.hermes -> /var/lib/hermes/.hermes) unifies state between host and container so sessions, config, and memories are shared. CLI changes: - Global routing before subcommand dispatch (all commands forwarded) - docker exec with -u exec_user, env passthrough (TERM, COLORTERM, LANG, LC_ALL), TTY-aware flags - Retry with spinner on failure (TTY: 5s, non-TTY: 10s silent) - Hard fail instead of silent fallback - HERMES_DEV=1 env var bypasses routing for development - No routing messages (invisible to user) NixOS module changes: - container.hostUsers option: lists users who get ~/.hermes symlink and automatic hermes group membership - Activation script creates symlink bridge (with backup of existing ~/.hermes dirs), writes exec_user to .container-mode - Cleanup on disable: removes symlinks + .container-mode + stops service - Warning when hostUsers set without addToSystemPackages * fix: address review — reuse sudo var, add chown -h on symlink update - hermes_cli/main.py: reuse the existing `sudo` variable instead of redundant `shutil.which("sudo")` call that could return None - nix/nixosModules.nix: add missing `chown -h` when updating an existing symlink target so ownership stays consistent with the fresh-create and backup-replace branches * fix: address remaining review items from cursor bugbot - hermes_cli/main.py: move container routing BEFORE parse_args() so --help, unrecognised flags, and all subcommands are forwarded transparently into the container instead of being intercepted by argparse on the host (high severity) - nix/nixosModules.nix: resolve home dirs via config.users.users.${user}.home instead of hardcoding /home/${user}, supporting users with custom home directories (medium severity) - nix/nixosModules.nix: gate hostUsers group membership on container.enable so setting hostUsers without container mode doesn't silently add users to the hermes group (low severity) * fix: simplify container routing — execvp, no retries, let it crash - Replace subprocess.run retry loop with os.execvp (no idle parent process) - Extract _probe_container helper for sudo detection with 15s timeout - Narrow exception handling: FileNotFoundError only in get_container_exec_info, catch TimeoutExpired specifically, remove silent except Exception: pass - Collapse needs_sudo + sudo into single sudo_path variable - Simplify NixOS symlink creation from 4 branches to 2 - Gate NixOS sudoers hint with "On NixOS:" prefix - Full test rewrite: 18 tests covering execvp, sudo probe, timeout, permissions --------- Co-authored-by: Hermes Agent <hermes@nousresearch.com>
…ousResearch#7543) * feat(nix): container-aware CLI — auto-route all subcommands into managed container When container.enable = true, the host `hermes` CLI transparently execs every subcommand into the managed Docker/Podman container. A symlink bridge (~/.hermes -> /var/lib/hermes/.hermes) unifies state between host and container so sessions, config, and memories are shared. CLI changes: - Global routing before subcommand dispatch (all commands forwarded) - docker exec with -u exec_user, env passthrough (TERM, COLORTERM, LANG, LC_ALL), TTY-aware flags - Retry with spinner on failure (TTY: 5s, non-TTY: 10s silent) - Hard fail instead of silent fallback - HERMES_DEV=1 env var bypasses routing for development - No routing messages (invisible to user) NixOS module changes: - container.hostUsers option: lists users who get ~/.hermes symlink and automatic hermes group membership - Activation script creates symlink bridge (with backup of existing ~/.hermes dirs), writes exec_user to .container-mode - Cleanup on disable: removes symlinks + .container-mode + stops service - Warning when hostUsers set without addToSystemPackages * fix: address review — reuse sudo var, add chown -h on symlink update - hermes_cli/main.py: reuse the existing `sudo` variable instead of redundant `shutil.which("sudo")` call that could return None - nix/nixosModules.nix: add missing `chown -h` when updating an existing symlink target so ownership stays consistent with the fresh-create and backup-replace branches * fix: address remaining review items from cursor bugbot - hermes_cli/main.py: move container routing BEFORE parse_args() so --help, unrecognised flags, and all subcommands are forwarded transparently into the container instead of being intercepted by argparse on the host (high severity) - nix/nixosModules.nix: resolve home dirs via config.users.users.${user}.home instead of hardcoding /home/${user}, supporting users with custom home directories (medium severity) - nix/nixosModules.nix: gate hostUsers group membership on container.enable so setting hostUsers without container mode doesn't silently add users to the hermes group (low severity) * fix: simplify container routing — execvp, no retries, let it crash - Replace subprocess.run retry loop with os.execvp (no idle parent process) - Extract _probe_container helper for sudo detection with 15s timeout - Narrow exception handling: FileNotFoundError only in get_container_exec_info, catch TimeoutExpired specifically, remove silent except Exception: pass - Collapse needs_sudo + sudo into single sudo_path variable - Simplify NixOS symlink creation from 4 branches to 2 - Gate NixOS sudoers hint with "On NixOS:" prefix - Full test rewrite: 18 tests covering execvp, sudo probe, timeout, permissions --------- Co-authored-by: Hermes Agent <hermes@nousresearch.com>
…ousResearch#7543) * feat(nix): container-aware CLI — auto-route all subcommands into managed container When container.enable = true, the host `hermes` CLI transparently execs every subcommand into the managed Docker/Podman container. A symlink bridge (~/.hermes -> /var/lib/hermes/.hermes) unifies state between host and container so sessions, config, and memories are shared. CLI changes: - Global routing before subcommand dispatch (all commands forwarded) - docker exec with -u exec_user, env passthrough (TERM, COLORTERM, LANG, LC_ALL), TTY-aware flags - Retry with spinner on failure (TTY: 5s, non-TTY: 10s silent) - Hard fail instead of silent fallback - HERMES_DEV=1 env var bypasses routing for development - No routing messages (invisible to user) NixOS module changes: - container.hostUsers option: lists users who get ~/.hermes symlink and automatic hermes group membership - Activation script creates symlink bridge (with backup of existing ~/.hermes dirs), writes exec_user to .container-mode - Cleanup on disable: removes symlinks + .container-mode + stops service - Warning when hostUsers set without addToSystemPackages * fix: address review — reuse sudo var, add chown -h on symlink update - hermes_cli/main.py: reuse the existing `sudo` variable instead of redundant `shutil.which("sudo")` call that could return None - nix/nixosModules.nix: add missing `chown -h` when updating an existing symlink target so ownership stays consistent with the fresh-create and backup-replace branches * fix: address remaining review items from cursor bugbot - hermes_cli/main.py: move container routing BEFORE parse_args() so --help, unrecognised flags, and all subcommands are forwarded transparently into the container instead of being intercepted by argparse on the host (high severity) - nix/nixosModules.nix: resolve home dirs via config.users.users.${user}.home instead of hardcoding /home/${user}, supporting users with custom home directories (medium severity) - nix/nixosModules.nix: gate hostUsers group membership on container.enable so setting hostUsers without container mode doesn't silently add users to the hermes group (low severity) * fix: simplify container routing — execvp, no retries, let it crash - Replace subprocess.run retry loop with os.execvp (no idle parent process) - Extract _probe_container helper for sudo detection with 15s timeout - Narrow exception handling: FileNotFoundError only in get_container_exec_info, catch TimeoutExpired specifically, remove silent except Exception: pass - Collapse needs_sudo + sudo into single sudo_path variable - Simplify NixOS symlink creation from 4 branches to 2 - Gate NixOS sudoers hint with "On NixOS:" prefix - Full test rewrite: 18 tests covering execvp, sudo probe, timeout, permissions --------- Co-authored-by: Hermes Agent <hermes@nousresearch.com>
Summary
container.enable = true, the hosthermesCLI transparently routes all subcommands into the managed Docker/Podman container viadocker execcontainer.hostUsersoption creates a~/.hermessymlink bridge to the service stateDir, unifying sessions/config/memories between host and containerhostUsersare auto-added to thehermesgroupHERMES_DEV=1env var bypasses routing for development.container-mode, stops serviceDepends on #7488 (mautrix migration) for a clean
nix build— theatomicwritessdist failure frommatrix-nio[e2e]is resolved there.Test plan
nix-instantiate --parse)hermes version,hermes config,hermes sessions list,hermes chat -q, tool calling, session persistenceHERMES_DEV=1bypass verified (host Python 3.12 vs container Python 3.11)