fix(desktop): keep composer usable during reconnect (#45488)
* feat(cli): add --safe-mode troubleshooting flag Inspired by Claude Code v2.1.169 (June 2026): run Hermes with all customizations disabled to isolate setup problems from product bugs. --safe-mode implies --ignore-user-config and --ignore-rules, and additionally skips plugin discovery (hermes_cli/plugins.py) and MCP server loading (tools/mcp_tool.py) via the internal HERMES_SAFE_MODE env bridge. * fix(desktop): keep composer usable during reconnect
This commit is contained in:
@@ -213,6 +213,13 @@ def build_top_level_parser():
|
||||
default=False,
|
||||
help="Skip auto-injection of AGENTS.md, SOUL.md, .cursorrules, memory, and preloaded skills",
|
||||
)
|
||||
_inherited_flag(
|
||||
parser,
|
||||
"--safe-mode",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help="Troubleshooting mode: disable ALL customizations — user config, AGENTS.md/memory injection, plugins, and MCP servers (implies --ignore-user-config and --ignore-rules)",
|
||||
)
|
||||
_inherited_flag(
|
||||
parser,
|
||||
"--tui",
|
||||
@@ -366,6 +373,13 @@ def build_top_level_parser():
|
||||
default=argparse.SUPPRESS,
|
||||
help="Skip auto-injection of AGENTS.md, SOUL.md, .cursorrules, memory, and preloaded skills. Combine with --ignore-user-config for a fully isolated run.",
|
||||
)
|
||||
_inherited_flag(
|
||||
chat_parser,
|
||||
"--safe-mode",
|
||||
action="store_true",
|
||||
default=argparse.SUPPRESS,
|
||||
help="Troubleshooting mode: disable ALL customizations — user config, AGENTS.md/memory injection, plugins, and MCP servers (implies --ignore-user-config and --ignore-rules). Use to isolate whether a problem comes from your setup or from Hermes itself.",
|
||||
)
|
||||
chat_parser.add_argument(
|
||||
"--source",
|
||||
default=None,
|
||||
|
||||
+14
-2
@@ -2199,6 +2199,18 @@ def cmd_chat(args):
|
||||
if getattr(args, "yolo", False):
|
||||
os.environ["HERMES_YOLO_MODE"] = "1"
|
||||
|
||||
# --safe-mode: troubleshooting mode that disables ALL customizations.
|
||||
# Inspired by Claude Code v2.1.169's --safe-mode (June 2026): run with a
|
||||
# pristine environment to isolate whether a problem comes from the user's
|
||||
# setup (config, rules files, plugins, MCP servers) or from Hermes itself.
|
||||
# Implemented as a superset of --ignore-user-config + --ignore-rules plus
|
||||
# plugin/MCP discovery suppression (HERMES_SAFE_MODE is checked by
|
||||
# hermes_cli/plugins.py and tools/mcp_tool.py).
|
||||
if getattr(args, "safe_mode", False):
|
||||
os.environ["HERMES_SAFE_MODE"] = "1"
|
||||
os.environ["HERMES_IGNORE_USER_CONFIG"] = "1"
|
||||
os.environ["HERMES_IGNORE_RULES"] = "1"
|
||||
|
||||
# --ignore-user-config: make load_cli_config() / load_config() skip the
|
||||
# user's ~/.hermes/config.yaml and return built-in defaults. Set BEFORE
|
||||
# importing cli (which runs `CLI_CONFIG = load_cli_config()` at module
|
||||
@@ -2256,8 +2268,8 @@ def cmd_chat(args):
|
||||
"checkpoints": getattr(args, "checkpoints", False),
|
||||
"pass_session_id": getattr(args, "pass_session_id", False),
|
||||
"max_turns": getattr(args, "max_turns", None),
|
||||
"ignore_rules": getattr(args, "ignore_rules", False),
|
||||
"ignore_user_config": getattr(args, "ignore_user_config", False),
|
||||
"ignore_rules": getattr(args, "ignore_rules", False) or getattr(args, "safe_mode", False),
|
||||
"ignore_user_config": getattr(args, "ignore_user_config", False) or getattr(args, "safe_mode", False),
|
||||
"compact": getattr(args, "compact", False),
|
||||
}
|
||||
# Filter out None values
|
||||
|
||||
@@ -1124,6 +1124,14 @@ class PluginManager:
|
||||
"""
|
||||
if self._discovered and not force:
|
||||
return
|
||||
# Safe mode (--safe-mode / HERMES_SAFE_MODE=1): troubleshooting run
|
||||
# with all customizations disabled. Skip plugin discovery entirely so
|
||||
# no third-party code (hooks, tools, platforms) loads. Mark as
|
||||
# discovered so callers see a clean empty registry, not a retry loop.
|
||||
if env_var_enabled("HERMES_SAFE_MODE"):
|
||||
logger.info("HERMES_SAFE_MODE=1 — plugin discovery skipped")
|
||||
self._discovered = True
|
||||
return
|
||||
if force:
|
||||
self._plugins.clear()
|
||||
self._hooks.clear()
|
||||
|
||||
Reference in New Issue
Block a user