hermes-bsd/hermes_cli
Teknium a175f39577
feat(nous): persist Nous OAuth across profiles via shared token store (#19712)
Mirrors the Codex auto-import UX. On successful Nous login (either
`hermes auth add nous --type oauth` or `hermes login nous`), tokens are
mirrored to `$HERMES_SHARED_AUTH_DIR/nous_auth.json` (default
`~/.hermes/shared/nous_auth.json`, outside any named profile's
HERMES_HOME). On next login in a new profile, the flow offers to import
those credentials ("Import these credentials? [Y/n]") and rehydrates via
a forced refresh+mint instead of running the full device-code flow.

Runtime refresh in any profile syncs the rotated refresh_token back to
the shared store so sibling profiles don't hit stale-token fallback
after rotation.

The volatile 24h agent_key is NOT persisted to the shared store —
only the long-lived OAuth tokens are cross-profile useful.

- `HERMES_SHARED_AUTH_DIR` env var for tests + custom layouts
- Pytest seat belt mirrors the existing `_auth_file_path` guard so
  forgetting to redirect the store in a test fails loudly
- File mode 0600 where platform supports it
- Runtime credential resolution is unchanged — shared store is only
  consulted during the login flow, so profile isolation at runtime is
  preserved
- Stale refresh_token + portal-down cases gracefully fall back to
  device-code

Addresses a user report from Mike Nguyen: running
`hermes --profile <name> auth add nous --type oauth` for every new
profile is unnecessary friction now that Codex has a shared-import
flow via `~/.codex/auth.json`.
2026-05-04 04:54:55 -07:00
..
__init__.py fix(windows): enforce UTF-8 stdout/stderr to prevent UnicodeEncodeError crash 2026-05-03 16:58:25 -07:00
_parser.py refactor(cli): derive relaunch flag table from argparse introspection 2026-04-29 20:33:29 -07:00
auth.py feat(nous): persist Nous OAuth across profiles via shared token store (#19712) 2026-05-04 04:54:55 -07:00
auth_commands.py feat(nous): persist Nous OAuth across profiles via shared token store (#19712) 2026-05-04 04:54:55 -07:00
azure_detect.py
backup.py fix(security): restore .env/auth.json/state.db with 0600 perms 2026-05-04 04:43:53 -07:00
banner.py fix(banner): show correct update status on nix-built hermes (#17550) 2026-04-30 07:03:00 +05:30
browser_connect.py
callbacks.py
claw.py
cli_output.py
clipboard.py
codex_models.py
colors.py
commands.py feat(cli,gateway): /new accepts optional session name argument 2026-05-04 03:14:50 -07:00
completion.py
config.py fix(cli): local backend CLI always uses launch directory, stops .env sync of TERMINAL_CWD (#19334) 2026-05-04 11:36:19 +05:30
copilot_auth.py
cron.py
curator.py fix(curator): authoritative absorbed_into on delete + restore cron skill links on rollback (#18671) (#18731) 2026-05-02 01:29:57 -07:00
curses_ui.py fix: treat ctrl-c as curses cancel 2026-05-04 01:36:44 -07:00
debug.py fix(debug): redact log content at upload time in hermes debug share 2026-05-03 11:42:20 -07:00
default_soul.py
dingtalk_auth.py
doctor.py fix(doctor): check global agent-browser when local install not found 2026-05-04 03:13:22 -07:00
dump.py
env_loader.py
fallback_cmd.py
gateway.py fix(gateway): show friendly error when service is not installed 2026-05-04 04:49:51 -07:00
goals.py feat: /goal — persistent cross-turn goals (Ralph loop) (#18262) 2026-04-30 23:10:20 -07:00
hooks.py
kanban.py feat(kanban): multi-project boards — one install, many kanbans (#19653) 2026-05-04 04:42:38 -07:00
kanban_db.py fix(profiles): normalize profile IDs for Kanban assignees and lookups 2026-05-04 04:44:37 -07:00
logs.py
main.py fix(cli): check updates against upstream/main for fork users 2026-05-04 04:42:44 -07:00
mcp_config.py refactor(config): migrate remaining 33 cfg_get call sites (#17311) 2026-04-29 04:03:03 -07:00
memory_setup.py fix(cli): decode .env as UTF-8 to avoid GBK crash on Windows 2026-05-02 01:40:31 -07:00
model_catalog.py
model_normalize.py feat(minimax-oauth): full integration with peer OAuth providers 2026-04-29 09:53:42 -07:00
model_switch.py fix(model-picker): exclude providers with empty credential pool entries 2026-05-04 03:12:12 -07:00
models.py fix(cli): allow custom:* provider slugs in model validation 2026-05-04 01:39:06 -07:00
nous_subscription.py
oneshot.py fix(tui): honor launch toolsets (#17623) 2026-04-29 16:55:27 -07:00
pairing.py
platforms.py feat: complete plugin platform parity — all 12 integration points 2026-04-29 21:56:51 -07:00
plugins.py fix(plugins): bound async plugin command await with 30s timeout 2026-04-30 19:56:18 -07:00
plugins_cmd.py feat(dashboard): add Plugins page with enable/disable, auth status, install/remove 2026-04-30 20:29:37 -04:00
profiles.py fix(profiles): keep validate_profile_name strict; callers normalize first 2026-05-04 04:44:37 -07:00
providers.py fix: prevent bare 'custom' slug in model.provider (#17478) 2026-04-30 04:32:11 -07:00
pty_bridge.py fix(pty): default TERM for resize probes 2026-05-04 02:38:54 -07:00
relaunch.py remove relaunch_chat 2026-04-29 20:33:29 -07:00
runtime_provider.py fix(fallback): let custom_providers shadow built-in aliases 2026-04-30 20:18:44 -07:00
setup.py fix(setup): skip AUXILIARY_VISION_MODEL write when input is blank 2026-05-04 02:41:47 -07:00
skills_config.py refactor(config): migrate remaining 33 cfg_get call sites (#17311) 2026-04-29 04:03:03 -07:00
skills_hub.py
skin_engine.py
slack_cli.py fix(paths): route achievements plugin + profile-tui through HERMES_HOME 2026-04-30 23:21:54 -07:00
status.py fix(status): show NVIDIA NIM api key status 2026-05-04 03:08:50 -07:00
timeouts.py
tips.py feat(tips): add cost-saving tips from April 30 tip-of-the-day (#17841) 2026-04-30 02:30:36 -07:00
tools_config.py fix(cli): sync use_gateway in _reconfigure_provider for tts, browser, and web 2026-05-04 02:33:55 -07:00
uninstall.py
vercel_auth.py feat: add Vercel Sandbox backend 2026-04-29 07:22:33 -07:00
voice.py
web_server.py feat(docker): launch dashboard as side-process via HERMES_DASHBOARD=1 2026-05-04 15:37:27 +10:00
webhook.py refactor(config): migrate remaining 33 cfg_get call sites (#17311) 2026-04-29 04:03:03 -07:00