From 27833a05085442656eb54b945420edc2890e09ba Mon Sep 17 00:00:00 2001 From: EdderTalmor Date: Sun, 7 Jun 2026 14:42:00 -0400 Subject: [PATCH] fix: register shell hooks in TUI gateway and ACP adapter (issue #41457) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Shell hooks (the `hooks:` block in `config.yaml`) were not being registered in the desktop app (TUI gateway) or the ACP adapter (IDE integration) entry paths. This caused `pre_tool_call` block hooks to silently do nothing in those surfaces — a security-relevant gap where configured protections were enforced in CLI/gateway but ignored in desktop/IDE. Root cause: `agent.shell_hooks.register_from_config()` was called at startup in `cli.py`, `hermes_cli/main.py`, and `gateway/run.py`, but not in `tui_gateway/entry.py` or `acp_adapter/session.py`. Fix: Add `register_from_config(load_config(), accept_hooks=False)` calls in both entry points, wrapped in try/except to never block startup. The `accept_hooks=False` matches the gateway pattern since neither surface has a TTY — consent comes from `--accept-hooks`, `HERMES_ACCEPT_HOOKS`, or `hooks_auto_accept: true` in config. --- acp_adapter/session.py | 15 +++++++++++++++ tui_gateway/entry.py | 15 +++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/acp_adapter/session.py b/acp_adapter/session.py index c124229bec89a..2f80f2b56014f 100644 --- a/acp_adapter/session.py +++ b/acp_adapter/session.py @@ -617,6 +617,21 @@ def _make_agent( _register_task_cwd(session_id, cwd) agent = AIAgent(**kwargs) + + # Register declarative shell hooks from cli-config.yaml. ACP adapter + # has no TTY, so consent has to come from one of the three opt-in + # channels (--accept-hooks on launch, HERMES_ACCEPT_HOOKS env var, + # or hooks_auto_accept: true in config.yaml). Pass accept_hooks=False + # and let register_from_config resolve the effective value from env + + # config itself. Failures are logged but must not block session creation. + try: + from agent.shell_hooks import register_from_config + register_from_config(config, accept_hooks=False) + except Exception: + logger.debug( + "shell-hook registration failed for ACP session %s", session_id, exc_info=True + ) + # ACP stdio transport requires stdout to remain protocol-only JSON-RPC. # Route any incidental human-readable agent output to stderr instead. agent._print_fn = _acp_stderr_print diff --git a/tui_gateway/entry.py b/tui_gateway/entry.py index 7069ec97605fe..c028b465165ce 100644 --- a/tui_gateway/entry.py +++ b/tui_gateway/entry.py @@ -263,6 +263,21 @@ def _discover_mcp_background() -> None: global _mcp_discovery_thread _mcp_discovery_thread = _mcp_thread + # Register declarative shell hooks from cli-config.yaml. TUI gateway + # has no TTY, so consent has to come from one of the three opt-in + # channels (--accept-hooks on launch, HERMES_ACCEPT_HOOKS env var, + # or hooks_auto_accept: true in config.yaml). Pass accept_hooks=False + # and let register_from_config resolve the effective value from env + + # config itself. Failures are logged but must never block startup. + try: + from hermes_cli.config import load_config + from agent.shell_hooks import register_from_config + register_from_config(load_config(), accept_hooks=False) + except Exception: + logger.debug( + "shell-hook registration failed at TUI gateway startup", exc_info=True + ) + if not write_json({ "jsonrpc": "2.0", "method": "event",