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()
Feature Request: on_status_bar_render plugin hook
Summary
Add an
on_status_bar_renderplugin hook that lets plugins contributeextra fragments to the Hermes TUI status bar, without requiring patches
to
cli.pythat break on every update.Motivation
The current status bar in
_get_status_bar_fragments()is hardcoded: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 onhermes update.The existing plugin system already supports session boundary hooks
(
on_session_finalize,on_session_reset— added in bdc72ec). Astatus bar hook follows the same pattern.
Proposed API
In
hermes_cli/plugins.py, define the hook:In
cli.py,_get_status_bar_fragments():The
snapshotdict 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:
[mega_setup]after model name👁 gemini-2.5-flashat end⏰ 2 jobsfor users with active crons*when working tree has changesBackwards Compatibility
No breaking changes. Plugins that don't register this hook see no
difference. The hook is purely additive.
Related
on_session_finalizehook: bdc72econ_session_resethook: bdc72eccli.py:_get_status_bar_fragments()cli.py:_get_status_bar_snapshot()