hermes - ✅(Solved) Fix Bug: Terminal approval prompt freezes input area, preventing user interaction [2 pull requests, 5 comments, 5 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
NousResearch/hermes-agent#13617Fetched 2026-04-22 08:05:21
View on GitHub
Comments
5
Participants
5
Timeline
12
Reactions
1
Author
Timeline (top)
commented ×5labeled ×3cross-referenced ×2closed ×1

When Hermes encounters a command that triggers the terminal safety filter (e.g. sudo tee to system dirs), it displays an approval prompt ([o]nce | [s]ession | [a]lways | [d]eny). The prompt freezes the CLI input area, making it impossible for the user to type a response.

Root Cause

When Hermes encounters a command that triggers the terminal safety filter (e.g. sudo tee to system dirs), it displays an approval prompt ([o]nce | [s]ession | [a]lways | [d]eny). The prompt freezes the CLI input area, making it impossible for the user to type a response.

Fix Action

Workaround

  • Set approvals.mode: auto in ~/.hermes/config.yaml
  • Use direct .deb downloads instead of sudo tee for apt repos

PR fix notes

PR #13697: fix: approval prompt freeze — CLI thread-local + TUI blind-keystroke

Description (problem / solution / changelog)

Restores dangerous-command approval in both CLI and TUI — approval prompts now accept keystrokes instead of freezing the terminal for 60s.

Salvage of #13634 by @Societus (rebase-merged for authorship preservation) + regression-guard tests.

Root cause

62348cff (#13525) moved _approval_callback / _sudo_password_callback to threading.local() to fix GHSA-qg5c-hvr5-hjgr (ACP race). CLI registers callbacks in the main thread but the agent runs in a daemon thread spawned by chat()threading.local doesn't propagate, so _get_approval_callback() returned None in the agent thread and fell back to input(), which deadlocks inside prompt_toolkit.

TUI had an adjacent bug: useInputHandlers consumed keystrokes via return when isBlocked, but Ink's EventEmitter still delivered them to ApprovalPrompt — user saw a frozen overlay while blind keystrokes could silently approve dangerous commands session-wide or write to the permanent allowlist.

Changes

FileChange
cli.pyRegister approval/sudo/secret callbacks inside run_agent() thread target; clear in finally
ui-tui/src/app/useInputHandlers.tsWhen approval/clarify/confirm overlay active, only intercept Ctrl+C — let arrow/number/Enter fall through
tests/cli/test_cli_approval_ui.pyTwo regression guards pinning the thread-local contract

Validation

  • tests/cli/test_cli_approval_ui.py tests/acp/test_approval_isolation.py tests/tools/test_command_guards.py — 35 passed
  • E2E: confirmed main-thread registration is invisible to child thread on current main, and child-thread registration is visible + cleared on finally
  • TUI: tsc --noEmit clean

Closes #13617, closes #13618.

Changed files

  • cli.py (modified, +20/-0)
  • tests/cli/test_cli_approval_ui.py (modified, +85/-0)
  • ui-tui/src/app/useInputHandlers.ts (modified, +11/-0)

PR #13734: fix(agent): propagate approval callbacks to concurrent tool worker threads

Description (problem / solution / changelog)

Bug #13617 Regression: Concurrent tool execution deadlocks on dangerous-command approval

Summary

When the agent executes a batch of tools concurrently (e.g. read_file + terminal in the same turn), any dangerous-command approval prompt deadlocks. The user can type a selection but pressing Return has no effect; the prompt times out after 60 seconds and denies the command.

Root Cause

_execute_tool_calls_concurrent() in run_agent.py dispatches tool calls to a ThreadPoolExecutor. The dangerous-command approval callback (and sudo password callback) are stored in threading.local() inside tools/terminal_tool.py. Worker threads spawned by the executor cannot see callbacks registered in the parent agent thread, so _get_approval_callback() returns None.

When the callback is None, tools/approval.py falls back to plain input() in a background daemon thread. However, the Hermes CLI uses prompt_toolkit, which puts the terminal in raw mode. The background thread's input() competes with prompt_toolkit for stdin. The user can type characters (they may echo), but the Enter key is captured by prompt_toolkit and never reaches input(), causing a deadlock until the timeout fires.

Affected Code Paths

  • run_agent.pyAIAgent._execute_tool_calls_concurrent()_run_tool() worker function
  • Any concurrent batch containing terminal, execute_code, or other tools that trigger dangerous-command detection

Fix

Capture the parent thread's approval/sudo callbacks before launching the thread pool, then register them locally inside each worker thread (and clear them on exit). This mirrors the existing fix pattern used in cli.py for the main agent worker thread.

Files Changed

  • run_agent.py

Key Diff Points

  1. Import callback getters/setters from tools.terminal_tool
  2. Before defining _run_tool, snapshot _get_approval_callback() and _get_sudo_password_callback()
  3. Inside _run_tool, after set_activity_callback(), register the callbacks:
    if _parent_approval_cb is not None:
        _set_approval_callback(_parent_approval_cb)
    if _parent_sudo_cb is not None:
        _set_sudo_password_callback(_parent_sudo_cb)
  4. At the end of _run_tool, clear them:
    _set_approval_callback(None)
    _set_sudo_password_callback(None)

Regression Tests

  • tests/cli/test_cli_approval_ui.py::TestApprovalCallbackThreadLocalWiring
    • test_main_thread_registration_is_invisible_to_child_thread
    • test_child_thread_registration_is_visible_and_cleared_in_finally

All 10 approval UI tests pass after the fix.

Related

  • Original fix: GHSA-qg5c-hvr5-hjgr / #13617 (made callbacks thread-local)
  • The original fix registered callbacks inside the main agent worker thread (cli.py ~8378) but missed the concurrent execution path (run_agent.py ~7876).

Changed files

  • run_agent.py (modified, +33/-0)
RAW_BUFFERClick to expand / collapse

Description

When Hermes encounters a command that triggers the terminal safety filter (e.g. sudo tee to system dirs), it displays an approval prompt ([o]nce | [s]ession | [a]lways | [d]eny). The prompt freezes the CLI input area, making it impossible for the user to type a response.

Steps to Reproduce

  1. Run a command triggering the danger classifier, e.g. sudo tee /etc/apt/keyrings/githubcli-archive-keyring.gpg
  2. Approval prompt appears
  3. Input area is frozen — cannot type [a], [o], [s], or [d]
  4. Times out after 60s: BLOCKED: User denied. Do NOT retry.

Environment

  • Platform: WSL (Windows Subsystem for Linux)
  • Hermes CLI interface
  • approvals.mode: manual

Workaround

  • Set approvals.mode: auto in ~/.hermes/config.yaml
  • Use direct .deb downloads instead of sudo tee for apt repos

Expected Behavior

Approval prompt should accept keyboard input.

Actual Behavior

Input area freezes completely. User cannot respond, resulting in timeout and blocked command.

extent analysis

TL;DR

Setting approvals.mode to auto in the Hermes configuration file may resolve the issue by bypassing the manual approval prompt.

Guidance

  • Verify that the issue is specific to the manual approval mode by testing with approvals.mode set to auto in ~/.hermes/config.yaml.
  • Check if using direct .deb downloads instead of sudo tee for apt repositories can serve as a temporary workaround.
  • Investigate potential conflicts or limitations of the Hermes CLI interface within the WSL environment that might be contributing to the input freeze.
  • Consider testing the same commands and approval prompts in a native Linux environment to isolate if the issue is WSL-specific.

Example

No code snippet is provided as the issue seems to be related to configuration and environment rather than code.

Notes

The provided workaround suggests a potential solution but does not address the root cause of the input freeze. Further investigation into the Hermes CLI and WSL interaction may be necessary for a permanent fix.

Recommendation

Apply the workaround by setting approvals.mode to auto as it provides a functional, though potentially less secure, alternative to the manual approval process. This allows for continued use of Hermes while the root cause of the input freeze is further investigated.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

hermes - ✅(Solved) Fix Bug: Terminal approval prompt freezes input area, preventing user interaction [2 pull requests, 5 comments, 5 participants]