Skip to content

feat(cli): terminal tab titles + desktop notifications for agent state - #24632

Closed
Jpalmer95 wants to merge 1 commit into
NousResearch:mainfrom
Jpalmer95:feat/terminal-tab-notifications
Closed

feat(cli): terminal tab titles + desktop notifications for agent state#24632
Jpalmer95 wants to merge 1 commit into
NousResearch:mainfrom
Jpalmer95:feat/terminal-tab-notifications

Conversation

@Jpalmer95

Copy link
Copy Markdown
Contributor

Summary

Add terminal tab title updates and optional OS-level desktop notifications so users with multiple terminal tabs can see at a glance which Hermes session needs attention.

The Problem

When running multiple Hermes instances in different terminal tabs/instances, users have no way to tell which session needs their input without tab-switching. The agent may be waiting for command approval, a clarify answer, or may have hit an error — but the user can't see this without focusing the right tab.

The Solution

Two complementary notification mechanisms, both off by default:

1. Terminal Tab Titles (lightweight, recommended first step)

Updates the terminal emulator's window/tab title bar using standard OSC escape sequences, reflecting the agent's current state:

  • Hermes - Ready — waiting for input
  • Hermes - Thinking... — calling the LLM
  • Hermes - Using tool: terminal — executing a tool
  • Hermes - Waiting for approval — command approval needed
  • Hermes - Has a question for you — agent clarified
  • Hermes - Error — API/tool failure

Works in GNOME Terminal, iTerm2, Alacritty, Kitty, Windows Terminal, WezTerm, and tmux (with set-titles on).

2. Desktop Notifications (optional)

Native OS notifications appearing in the system notification tray:

  • Linux: notify-send (freedesktop.org)
  • macOS: osascript
  • Windows: PowerShell WinRT toast

Usage

Config (permanent):

display:
  notifications:
    enabled: true       # Master switch — enables tab titles
    tab_title: true     # Update terminal tab title on state changes
    desktop: false      # Send OS notification tray popups
    events:
      approval: true
      clarify: true
      error: true
      turn_complete: false

In-session (/notif command):

/notif                  # Show current status
/notif on               # Enable all notifications
/notif off              # Disable all notifications
/notif tab [on|off]     # Toggle tab title updates
/notif desktop [on|off] # Toggle OS notifications

Files Changed

File What
agent/notification.py New — cross-platform desktop notification helpers
agent/display.py Notification config globals, init_notifications(), set_tab_title(), KawaiiSpinner start/stop hooks
cli.py Init at startup, wire into approval/clarify/turn-complete, _handle_notif_command()
hermes_cli/config.py display.notifications config section with defaults
hermes_cli/commands.py /notif slash command registration
tests/agent/test_notification.py 25 tests covering all modules

Cross-Platform

  • Windows-safe: platform.system() guards, shutil.which() checks, PowerShell escaping
  • Headless-safe: skips notifications when no DISPLAY/Wayland session is present
  • Non-TTY-safe: tab titles only emit when stdout is a real terminal
  • Best-effort: no exceptions propagate into the agent loop

Tests

25 new tests, all passing:

  • Desktop notification (build commands per platform, helpers, enabled/disabled)
  • Display notification config (init, tab title output)
  • KawaiiSpinner integration (start/stop title updates)
  • Config defaults (structure, disabled by default)
  • Command registration (/notif in registry)

python -m pytest tests/agent/test_notification.py -v — 25/25 passed.

Add tab title updates and optional OS-level desktop notifications so users
with multiple terminal tabs can see at a glance which Hermes session needs
attention.

Changes:

agent/notification.py
  - Cross-platform desktop notification helpers (notify-send on Linux,
    osascript on macOS, PowerShell on Windows)
  - Convenience wrappers: notify_approval_needed, notify_question,
    notify_error, notify_turn_complete

agent/display.py
  - Notification config globals (_notif_enabled, _notif_tab_title,
    _notif_desktop) and init_notifications() for CLI startup
  - get_notification_config() for /notif query
  - set_tab_title() and _reset_tab_title() for terminal tab title control
  - KawaiiSpinner.start() updates tab title to "Thinking..."
  - KawaiiSpinner.update_text() extracts tool name for tab title
  - KawaiiSpinner.stop() resets tab title to default

hermes_cli/config.py
  - display.notifications config section: enabled, tab_title, desktop,
    events (approval, clarify, error, turn_complete)
  - All notifications OFF by default

cli.py
  - Initialize notifications at CLI startup from config
  - _approval_callback: sets tab title + desktop notify on command approval
  - _clarify_callback: sets tab title + desktop notify on agent questions
  - Turn complete: resets tab title + optional desktop notification
  - _handle_notif_command: full /notif CLI command with on/off/status/tab/desktop

hermes_cli/commands.py
  - Register /notif slash command

tests/agent/test_notification.py
  - 25 comprehensive tests covering all modules

Config examples:
  display.notifications.enabled: true        # enable tab titles
  display.notifications.desktop: true        # enable OS notifications
@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 duplicate This issue or pull request already exists labels May 13, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Duplicate of #5318 — earliest open PR implementing terminal tab title updates (#5505). This adds desktop notifications on top but the core OSC title feature is the same.

@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 cross-platform implementation. The underlying classic-CLI need remains: current main's automatic title path is TUI-only (ui-tui/src/app/useMainApp.ts:576-586), so this is not redundant.

Problems

  • hermes_cli/config.py:978 adds display.notifications.events, but the diff's init_notifications() only accepts enabled, tab_title, and desktop; no production path consumes the four event flags. In particular, agent/notification.py defines notify_error() but the changed cli.py paths do not call it.
  • agent/display.py clears the title on spinner stop, while the PR documents a Hermes - Ready idle title.
  • hermes_cli/commands.py drops cli_only=True from the existing /indicator entry without implementing or testing gateway behavior for it.

Suggested changes

  • Make each configured event gate its corresponding emission, including an actual classic-CLI error path, and cover suppression behavior in tests.
  • Restore the documented ready title at turn completion.
  • Restore /indicator as CLI-only unless its broader availability is intentional and covered.

Automated hermes-sweeper review.

Comment thread hermes_cli/config.py
# or PowerShell (Windows).
"notifications": {
"enabled": False, # Master switch for all notification features
"tab_title": True, # Update terminal tab title on state changes

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.

These event flags are not consumed by the added runtime: init_notifications() only receives enabled/tab_title/desktop, and the changed CLI paths do not read approval, clarify, error, or turn_complete. Please thread these controls into each notification emission or remove them.

@teknium1 teknium1 added sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-platform-windows Sweeper risk: may break or behave differently on native Windows sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 13, 2026
@OutThisLife

Copy link
Copy Markdown
Collaborator

Superseded by #74654 (classic CLI) and #74683 (TUI). The core OSC tab title feature is covered by #74654; the desktop notifications this PR adds on top are out of scope for the title feature. Closing to consolidate.

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 duplicate This issue or pull request already exists 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-platform-windows Sweeper risk: may break or behave differently on native Windows sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants