hermes-agent/hermes_cli
Siddharth Balyan 1789c2699a
feat(nix): shared-state permission model for interactive CLI users (#6796)
* feat(nix): shared-state permission model for interactive CLI users

Enable interactive CLI users in the hermes group to share full
read-write state (sessions, memories, logs, cron) with the gateway
service via a setgid + group-writable permission model.

Changes:

nix/nixosModules.nix:
- Directories use setgid 2770 (was 0750) so new files inherit the
  hermes group. home/ stays 0750 (no interactive write needed).
- Activation script creates HERMES_HOME subdirs (cron, sessions, logs,
  memories) — previously Python created them but managed mode now skips
  mkdir.
- Activation migrates existing runtime files to group-writable (chmod
  g+rw). Nix-managed files (config.yaml, .env, .managed) stay 0640/0644.
- Gateway systemd unit gets UMask=0007 so files it creates are 0660.

hermes_cli/config.py:
- ensure_hermes_home() splits into managed/unmanaged paths. Managed mode
  verifies dirs exist (raises RuntimeError if not) instead of creating
  them. Scoped umask(0o007) ensures SOUL.md is created as 0660.

hermes_logging.py:
- _ManagedRotatingFileHandler subclass applies chmod 0660 after log
  rotation in managed mode. RotatingFileHandler.doRollover() creates new
  files via open() which uses the process umask (0022 → 0644), not the
  scoped umask from ensure_hermes_home().

Verified with a 13-subtest NixOS VM integration test covering setgid,
interactive writes, file ownership, migration, and gateway coexistence.

Refs: #6044

* Fix managed log file mode on initial open

Co-authored-by: Siddharth Balyan <alt-glitch@users.noreply.github.com>

* refactor: simplify managed file handler and merge activation loops

- Cache is_managed() result in handler __init__ instead of lazy-importing
  on every _open()/_chmod_if_managed() call. Avoids repeated stat+env
  checks on log rotation.
- Merge two for-loops over the same subdir list in activation script
  into a single loop (mkdir + chown + chmod + find in one pass).

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Siddharth Balyan <alt-glitch@users.noreply.github.com>
2026-04-10 03:48:42 +05:30
..
__init__.py chore: release v0.8.0 (2026.4.8) (#6135) 2026-04-08 04:56:20 -07:00
auth.py fix(credential_pool): use _resolve_kimi_base_url when seeding kimi-coding pool 2026-04-09 11:11:25 -07:00
auth_commands.py feat(qwen): add Qwen OAuth provider with portal request support 2026-04-08 13:46:30 -07:00
banner.py fix: resolve opencode.ai context window to 1M and clean up display formatting 2026-04-09 01:43:22 -07:00
callbacks.py refactor: remove 24 confirmed dead functions — 432 lines of unused code 2026-04-07 11:41:26 -07:00
checklist.py fix: add TTY guard to interactive CLI commands to prevent CPU spin (#3933) 2026-03-30 08:10:23 -07:00
claw.py refactor: codebase-wide lint cleanup — unused imports, dead code, and inefficient patterns (#5821) 2026-04-07 10:25:31 -07:00
clipboard.py refactor: deduplicate PowerShell script constants between Windows and WSL paths 2026-04-07 12:49:39 -07:00
codex_models.py fix: add gpt-5.4-mini to Codex fallback catalog (#3855) 2026-03-29 20:10:00 -07:00
colors.py feat: respect NO_COLOR env var and TERM=dumb (#4079) 2026-03-30 17:07:21 -07:00
commands.py fix: normalize reasoning effort ordering in UI 2026-04-09 14:20:16 -07:00
config.py feat(nix): shared-state permission model for interactive CLI users (#6796) 2026-04-10 03:48:42 +05:30
copilot_auth.py chore: remove ~100 unused imports across 55 files (#3016) 2026-03-25 15:02:03 -07:00
cron.py feat(cron): track delivery failures in job status (#6042) 2026-04-07 22:49:01 -07:00
curses_ui.py fix: add TTY guard to interactive CLI commands to prevent CPU spin (#3933) 2026-03-30 08:10:23 -07:00
default_soul.py fix: reset default SOUL.md to baseline identity text (#3159) 2026-03-26 01:34:27 -07:00
doctor.py fix(doctor): only check the active memory provider, not all providers unconditionally (#6285) 2026-04-08 13:44:58 -07:00
dump.py feat: add 'hermes dump' command for copy-pasteable setup summary (#6550) 2026-04-09 04:00:41 -07:00
env_loader.py chore: remove ~100 unused imports across 55 files (#3016) 2026-03-25 15:02:03 -07:00
gateway.py feat(gateway): add BlueBubbles iMessage platform adapter (#6437) 2026-04-08 23:54:03 -07:00
logs.py refactor: codebase-wide lint cleanup — unused imports, dead code, and inefficient patterns (#5821) 2026-04-07 10:25:31 -07:00
main.py fix: normalize reasoning effort ordering in UI 2026-04-09 14:20:16 -07:00
mcp_config.py fix: add TTY guard to interactive CLI commands to prevent CPU spin (#3933) 2026-03-30 08:10:23 -07:00
memory_setup.py refactor: replace inline HERMES_HOME re-implementations with get_hermes_home() 2026-04-07 10:40:34 -07:00
model_normalize.py feat(qwen): add Qwen OAuth provider with portal request support 2026-04-08 13:46:30 -07:00
model_switch.py fix(cli): prefer auth.py env vars over models.dev in provider detection (#6755) 2026-04-09 11:13:11 -07:00
models.py fix(models): correct probed_url selection logic 2026-04-09 02:38:09 -07:00
nous_subscription.py feat: switch managed browser provider from Browserbase to Browser Use (#5750) 2026-04-07 08:40:22 -04:00
pairing.py chore: fix 154 f-strings, simplify getattr/URL patterns, remove dead code (#3119) 2026-03-25 19:47:58 -07:00
plugins.py feat(cli): add on_session_finalize and on_session_reset plugin hooks 2026-04-08 04:27:34 -07:00
plugins_cmd.py refactor: replace inline HERMES_HOME re-implementations with get_hermes_home() 2026-04-07 10:40:34 -07:00
profiles.py feat: add 'hermes dump' command for copy-pasteable setup summary (#6550) 2026-04-09 04:00:41 -07:00
providers.py feat(qwen): add Qwen OAuth provider with portal request support 2026-04-08 13:46:30 -07:00
runtime_provider.py feat(qwen): add Qwen OAuth provider with portal request support 2026-04-08 13:46:30 -07:00
setup.py fix: OpenClaw migration now shows dry-run preview before executing (#6769) 2026-04-09 12:15:06 -07:00
skills_config.py fix(bluebubbles): add missing integration points and documentation (#6460) 2026-04-09 00:19:05 -07:00
skills_hub.py fix(skills): validate hub bundle paths before install (#3986) 2026-03-30 08:37:19 -07:00
skin_engine.py refactor: codebase-wide lint cleanup — unused imports, dead code, and inefficient patterns (#5821) 2026-04-07 10:25:31 -07:00
status.py feat(gateway): add BlueBubbles iMessage platform adapter (#6437) 2026-04-08 23:54:03 -07:00
tools_config.py feat(gateway): add BlueBubbles iMessage platform adapter (#6437) 2026-04-08 23:54:03 -07:00
uninstall.py refactor: remove 24 confirmed dead functions — 432 lines of unused code 2026-04-07 11:41:26 -07:00
webhook.py refactor: replace inline HERMES_HOME re-implementations with get_hermes_home() 2026-04-07 10:40:34 -07:00