Skip to content

feat(plugins): add on_status_bar_render hook for plugin-contributed TUI status bar fragments #8642

@charleneleong-ai

Description

@charleneleong-ai

Feature Request: on_status_bar_render plugin hook

Summary

Add an on_status_bar_render plugin hook that lets plugins contribute
extra fragments to the Hermes TUI status bar, without requiring patches
to cli.py that break on every update.

Motivation

The current status bar in _get_status_bar_fragments() is hardcoded:

⚕ model │ ctx used/total │ [bar] pct% │ duration

There is no way for a plugin to append or prepend items (e.g. session
title, active vision model, cron job count, git dirty state) without
directly patching cli.py. This means any customization breaks on
hermes update.

The existing plugin system already supports session boundary hooks
(on_session_finalize, on_session_reset — added in bdc72ec). A
status bar hook follows the same pattern.

Proposed API

In hermes_cli/plugins.py, define the hook:

# Hook: on_status_bar_render
# Called every time the TUI status bar is rebuilt.
# Plugins return a list of prompt_toolkit (style, text) fragment tuples
# to append to the right side of the status bar.
# Return [] to contribute nothing.
#
# Example plugin usage:
# def setup(ctx):
#     ctx.register_hook("on_status_bar_render", my_status_fragments)
#
# def my_status_fragments(snapshot: dict) -> list[tuple[str, str]]:
#     return [("class:status-bar-dim", " │ "), ("class:status-bar", "my text")]

In cli.py, _get_status_bar_fragments():

# After building core frags, invoke plugin hook
from hermes_cli.plugins import invoke_hook
extra = invoke_hook("on_status_bar_render", snapshot=snapshot)
for frag_list in extra:
    if isinstance(frag_list, list):
        frags.extend(frag_list)

The snapshot dict passed to the hook should include at minimum:

{
    "model_short": str,       # e.g. "claude-sonnet-4-6"
    "model_full": str,        # full model id
    "context_percent": int,   # 0-100 or None
    "context_tokens": int,    # current tokens used
    "context_length": int,    # total context window
    "duration": str,          # human-readable session duration
    "session_id": str,        # current session id
    "session_title": str,     # current /title value or ""
}

Use Cases

With this hook, plugins could cleanly add:

  • Session title[mega_setup] after model name
  • Active vision model👁 gemini-2.5-flash at end
  • Cron job count⏰ 2 jobs for users with active crons
  • Git dirty indicator* when working tree has changes
  • Custom cost/usage — rate limit % from ccusage or similar

Backwards Compatibility

No breaking changes. Plugins that don't register this hook see no
difference. The hook is purely additive.

Related

  • on_session_finalize hook: bdc72ec
  • on_session_reset hook: bdc72ec
  • Status bar fragments: cli.py:_get_status_bar_fragments()
  • Status bar snapshot: cli.py:_get_status_bar_snapshot()

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3Low — cosmetic, nice to havecomp/pluginsPlugin system and bundled pluginscomp/tuiTerminal UI (ui-tui/ + tui_gateway/)type/featureNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions