Skip to content

feat(nix): container-aware CLI — auto-route hermes chat into managed container - #7470

Closed
alt-glitch wants to merge 1 commit into
mainfrom
feat/container-aware-cli
Closed

feat(nix): container-aware CLI — auto-route hermes chat into managed container#7470
alt-glitch wants to merge 1 commit into
mainfrom
feat/container-aware-cli

Conversation

@alt-glitch

Copy link
Copy Markdown
Collaborator

Summary

When container.enable = true in the NixOS module, running hermes chat on the host now automatically execs into the managed container via docker/podman exec. The interactive CLI runs in the same environment as the gateway service — with access to all container-installed packages and tools.

Previously, users had to manually run:

sudo podman exec -it hermes-agent sh -lc '/data/current-package/bin/hermes chat'

Now they just run:

hermes chat

How it works

  1. NixOS activation script writes a .container-mode metadata file to HERMES_HOME containing backend, container_name, and hermes_bin. File is removed when container mode is disabled.

  2. Host CLI detection (hermes_cli/config.py):

    • _is_inside_container() — detects /.dockerenv, /run/.containerenv, and cgroup markers to prevent infinite exec loops
    • get_container_exec_info() — reads .container-mode, returns None if already inside a container or file doesn't exist
  3. Container exec (hermes_cli/main.py):

    • _exec_in_container() validates the container runtime exists and is running, then os.execvp() replaces the process
    • cmd_chat intercepts before normal flow to check for container routing

Safety & fallback

  • --host flag bypasses container routing
  • Falls back to host CLI if: container runtime not found, container not running, inspect fails, or any detection error
  • Already-inside-container detection prevents infinite exec loops
  • --host is stripped from forwarded args (not meaningful inside container)

Files changed

File Change
hermes_cli/config.py _is_inside_container(), get_container_exec_info()
hermes_cli/main.py _exec_in_container(), --host flag, cmd_chat intercept
nix/nixosModules.nix Write/remove .container-mode in activation script
tests/hermes_cli/test_container_aware_cli.py 14 tests
website/docs/getting-started/nix-setup.md Container-aware CLI docs

Test plan

  • 14 unit tests pass (detection, metadata parsing, exec building, fallbacks)
  • Manual test on NixOS with container.enable = true + addToSystemPackages = true
  • Verify --host bypasses container routing
  • Verify fallback when container is stopped

Closes #7380

…container

When container.enable = true in the NixOS module, running 'hermes chat'
on the host now automatically execs into the managed container via
docker/podman exec. This means the interactive CLI runs in the same
environment as the gateway service, with access to all container-installed
packages and tools.

Implementation:
- NixOS activation script writes .container-mode metadata file to
  HERMES_HOME with backend, container_name, and hermes_bin path
- File is removed when container mode is disabled (nixos-rebuild switch)
- hermes_cli/config.py: _is_inside_container() detects Docker/Podman
  indicators (/.dockerenv, /run/.containerenv, cgroup)
- hermes_cli/config.py: get_container_exec_info() reads .container-mode
  metadata, returns None when already inside a container
- hermes_cli/main.py: _exec_in_container() validates the container is
  running, then os.execvp() replaces the process with the container exec
- cmd_chat intercepts before normal flow, checks container info, execs

Safety:
- --host flag bypasses container routing (run on host regardless)
- Falls back to host CLI if: container runtime not found, container not
  running, inspect fails, or any detection error
- Strips --host from forwarded args (not meaningful inside container)
- Already-inside-container detection prevents infinite exec loops

Closes #7380
@alt-glitch alt-glitch added the type/feature New feature or request label Apr 11, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator Author

@BugBot review

@cursor

cursor Bot commented Apr 11, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Changes CLI execution flow to exec into a Docker/Podman container based on host-side metadata, which can alter interactive behavior and failure modes if detection or container state is wrong.

Overview
When NixOS container.enable is active, running hermes chat on the host now detects container mode via a new HERMES_HOME/.container-mode marker and transparently docker/podman execs into the managed container to run the chat CLI.

Adds host-side container detection to prevent infinite re-exec, validates runtime availability and container running state with graceful fallback to host execution, and introduces hermes chat --host to bypass routing. Includes new unit tests for detection/metadata parsing/exec behavior and updates NixOS activation + docs to write/remove the .container-mode file.

Reviewed by Cursor Bugbot for commit 611b89c. Configure here.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 611b89c. Configure here.

Comment thread hermes_cli/main.py
_exec_in_container(container_info, sys.argv[1:])
# _exec_in_container calls os.execvp which replaces the process.
# If we get here, the exec failed.
sys.exit(1)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fallback to host CLI broken by unconditional sys.exit(1)

High Severity

_exec_in_container returns normally in all fallback scenarios (runtime not found, container not running, inspect timeout), but cmd_chat unconditionally calls sys.exit(1) after it returns. This means the graceful "fall back to host CLI" behavior never actually works — the process just exits with an error. The warning messages even say "falling back to host CLI" but the host CLI path is never reached. Only when os.execvp raises an exception does the except Exception: pass block allow fallthrough.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 611b89c. Configure here.

@alt-glitch

Copy link
Copy Markdown
Collaborator Author

Superseded by #7543 (clean rebase on main with subprocess.run fix and Podman sudo support).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Add a container-aware interactive CLI for NixOS managed container mode

1 participant