hermes-agent/hermes_cli
teknium1 603599e982 feat: isolated profiles — multiple Hermes instances with independent config, gateway, and data
Add profile management so users can run multiple fully isolated Hermes
instances on the same machine. Each profile gets its own HERMES_HOME
with independent config.yaml, .env, memory, sessions, skills, gateway,
cron, and logs.

New files:
- hermes_cli/profiles.py: profile CRUD (create, list, clone, delete)
- tests/hermes_cli/test_profiles.py: 40 tests covering profiles
- tests/hermes_cli/test_gateway_pid_scoping.py: 3 gateway isolation tests

Key changes:
- hermes_cli/main.py: --profile/-p flag pre-parsed before any module
  imports (critical: 30+ modules cache HERMES_HOME at import time).
  New 'profile' subcommand with create/list/delete/show actions.
- hermes_cli/gateway.py: find_gateway_pids() now uses the HERMES_HOME-
  scoped PID file instead of a greedy ps aux scan. This prevents
  'hermes gateway stop' for one profile from killing another profile's
  gateway.
- hermes_cli/banner.py: shows active profile name in CLI banner when
  not using the default profile.

Usage:
  hermes profile create work                 # new empty profile
  hermes profile create work --clone default # clone config+keys
  hermes -p work setup                       # configure the profile
  hermes -p work                             # chat in work profile
  hermes -p work gateway start               # isolated gateway
  hermes profile list                        # see all profiles

Design:
- Profiles live at ~/.hermes/profiles/<name>/ (separate from default)
- Default profile is ~/.hermes (backward compatible, zero migration)
- --profile sets HERMES_HOME before any imports, so all downstream
  code (config, memory, sessions, gateway PID, systemd service names,
  cron, etc.) naturally scopes to the profile
- Systemd service names are already hash-scoped per HERMES_HOME
- Token-scoped locks prevent two profiles from binding the same bot

Full suite: 5278 passed, 0 new failures.
2026-03-17 05:38:19 -07:00
..
__init__.py chore: release v0.3.0 (v2026.3.17) 2026-03-17 00:38:48 -07:00
auth.py fix: remove ANTHROPIC_BASE_URL env var to avoid collisions (#1675) 2026-03-17 02:51:49 -07:00
banner.py feat: isolated profiles — multiple Hermes instances with independent config, gateway, and data 2026-03-17 05:38:19 -07:00
callbacks.py refactor(cli): implement approval locking mechanism to serialize concurrent requests 2026-03-13 23:59:18 -07:00
checklist.py fix: skip hanging tests + add global test timeout 2026-03-12 01:23:28 -07:00
claw.py fix(claw): warn when API keys are skipped during OpenClaw migration (#1580) 2026-03-17 02:10:36 -07:00
clipboard.py fix: clean up empty file after failed wl-paste clipboard extraction 2026-03-11 02:56:19 -07:00
codex_models.py fix: add codex forward-compat model listing 2026-03-13 21:34:01 -07:00
colors.py feat(cli): skin-aware light/dark theme mode with terminal auto-detection 2026-03-17 02:51:40 -07:00
commands.py feat: add /tools disable/enable/list slash commands with session reset (#1652) 2026-03-17 02:05:26 -07:00
config.py Merge pull request #1733 from NousResearch/fix/defensive-hardening 2026-03-17 04:46:20 -07:00
cron.py docs: clarify gateway service scopes (#1378) 2026-03-14 21:17:41 -07:00
curses_ui.py refactor: extract shared curses checklist, fix skill discovery perf 2026-03-11 03:06:15 -07:00
default_soul.py feat: seed a default global SOUL.md 2026-03-14 08:05:30 -07:00
doctor.py feat: add Kilo Code (kilocode) as first-class inference provider (#1666) 2026-03-17 02:40:34 -07:00
env_loader.py fix(config): reload .env over stale shell overrides 2026-03-15 06:46:28 -07:00
gateway.py feat: isolated profiles — multiple Hermes instances with independent config, gateway, and data 2026-03-17 05:38:19 -07:00
main.py feat: isolated profiles — multiple Hermes instances with independent config, gateway, and data 2026-03-17 05:38:19 -07:00
models.py fix(cli): use keyword args for fetch_nous_models (always TypeError) 2026-03-17 03:42:46 -07:00
pairing.py Cleanup time! 2026-02-20 23:23:32 -08:00
plugins.py feat: first-class plugin architecture (#1555) 2026-03-16 07:17:36 -07:00
profiles.py feat: isolated profiles — multiple Hermes instances with independent config, gateway, and data 2026-03-17 05:38:19 -07:00
runtime_provider.py fix: remove ANTHROPIC_BASE_URL env var to avoid collisions (#1675) 2026-03-17 02:51:49 -07:00
setup.py merge: resolve conflicts with origin/main 2026-03-17 04:30:37 -07:00
skills_config.py fix: wire email platform into toolset mappings + add documentation 2026-03-11 06:34:32 -07:00
skills_hub.py fix: add --yes flag to bypass confirmation in /skills install and uninstall (#1647) 2026-03-17 01:59:07 -07:00
skin_engine.py feat(cli): skin-aware light/dark theme mode with terminal auto-detection 2026-03-17 02:51:40 -07:00
status.py feat(web): add Tavily as web search/extract/crawl backend (#1731) 2026-03-17 04:28:03 -07:00
tools_config.py feat(web): add Tavily as web search/extract/crawl backend (#1731) 2026-03-17 04:28:03 -07:00
uninstall.py feat(gateway): scope systemd service name to HERMES_HOME 2026-03-16 04:42:46 -07:00