Skip to content

feat(cli): add busy_input_toggle_key to flip interrupt/queue mode at runtime - #4903

Open
hbmartin wants to merge 1 commit into
NousResearch:mainfrom
hbmartin:feat/busy-input-toggle-key
Open

feat(cli): add busy_input_toggle_key to flip interrupt/queue mode at runtime#4903
hbmartin wants to merge 1 commit into
NousResearch:mainfrom
hbmartin:feat/busy-input-toggle-key

Conversation

@hbmartin

@hbmartin hbmartin commented Apr 3, 2026

Copy link
Copy Markdown

Summary

Adds display.busy_input_toggle_key — a configurable keybinding that toggles busy_input_mode between interrupt and queue at runtime, without restarting the session.

Motivated by the UX friction of having to choose one mode statically via config. Users often want interrupt as the default but occasionally want to queue a follow-up thought while the agent is mid-task — without prepending /queue every time.

Changes

  • hermes_cli/config.py — adds busy_input_toggle_key: None to DEFAULT_CONFIG["display"]. Default is null so no behavior change for existing users.
  • cli.py — reads the key at startup; registers a kb.add() handler (only when a key is configured) that flips self.busy_input_mode and prints a brief inline status message; adds a dim [Q] indicator to all three status bar width variants when queue mode is active.
  • cli-config.yaml.example — documents the new option alongside busy_input_mode.

Usage

# ~/.hermes/config.yaml
display:
  busy_input_toggle_key: c-t   # Ctrl+T toggles interrupt/queue

Pressing the key at any time prints:

  Input mode: queue — Enter will queue messages for the next turn

or

  Input mode: interrupt — Enter will interrupt the running agent

The status bar shows [Q] next to the model name whenever queue mode is active.

Accepts any prompt_toolkit key name: c-t, f2, c-q, etc.

Notes

  • Ctrl+C always interrupts regardless of this setting (unchanged)
  • /queue <message> still works as a one-off escape hatch
  • The toggle works both while the agent is running and while idle
  • No tests added — behavior is a thin wrapper around the existing busy_input_mode branch in handle_enter

…runtime

Adds a configurable keybinding (display.busy_input_toggle_key in
config.yaml) that toggles busy_input_mode between 'interrupt' and
'queue' without restarting the session.

- Read busy_input_toggle_key from display config on startup
- Register a kb.add() handler when the key is set that flips
  self.busy_input_mode and prints a brief status line
- Show a dim [Q] indicator in the status bar when queue mode is active
  (all three width variants: <52, <76, full)
- Document the option in cli-config.yaml.example alongside busy_input_mode
- Default is null (no key bound) so existing behavior is unchanged

Example config:
  display:
    busy_input_toggle_key: c-t

Ctrl+C always interrupts regardless of this setting.
@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have comp/cli CLI entry point, hermes_cli/, setup wizard labels May 1, 2026

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the focused CLI UX improvement. The requested hotkey is not present on current main, but this implementation needs adaptation to current busy-input behavior.

Problems

  • Current main has a third steer mode (cli.py:3734-3743, dispatched at cli.py:13503-13531). The PR handler at cli.py:7563-7568 maps every non-interrupt mode to interrupt, so a user configured for steer loses steering on the first toggle.
  • The example lists c-q (cli-config.yaml.example:728), but current main binds Ctrl+Q to interrupt/exit behavior (cli.py:13889-13954).
  • The PR has no tests for registration, three-mode transitions, or binding collisions; current /busy mode coverage lives in tests/cli/test_busy_input_mode_command.py:44-95.

Suggested changes

  • Rework the toggle around the current three-mode contract, with explicit tested semantics for steer.
  • Reserve or reject existing bindings such as c-q, and add focused keybinding tests.
  • Document the finalized behavior in website/docs/user-guide/cli.md as well as the example config.

This is an automated hermes-sweeper review.

Comment thread cli.py
@kb.add(cli_ref.busy_input_toggle_key)
def handle_busy_input_toggle(event):
"""Toggle busy_input_mode between 'interrupt' and 'queue'."""
if cli_ref.busy_input_mode == "interrupt":

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Current main now has a third steer mode (cli.py:3737-3743) with a distinct agent.steer() dispatch path (cli.py:13503-13531). This else turns steer into interrupt; please define and test a three-mode-safe transition before salvaging.

Comment thread cli-config.yaml.example
# Keybinding to toggle between interrupt and queue mode at runtime (CLI only).
# When pressed while Hermes is running, flips busy_input_mode between
# "interrupt" and "queue" without restarting the session.
# Accepts prompt_toolkit key names: "c-t" (Ctrl+T), "f2", "c-q", etc.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

c-q is no longer a safe example: current main binds Ctrl+Q at cli.py:13889 as an interrupt/exit shortcut. Reserve or reject collisions with existing bindings instead of advertising them as usable.

@teknium1 teknium1 added sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/cli CLI entry point, hermes_cli/, setup wizard P3 Low — cosmetic, nice to have sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants