herdr-session-title-name
Live: https://herdr-session-title-name.uft1.com · https://herdr-session-title-name.pages.dev
Herdr plugin: persist terminal_title_stripped as tab label — so hermes --tui -c "hey what is 1 plus 1" shows as session_title on top and stays as tab name after the session closes.
- Sidebar
session_title alone on top — builtin herdr terminal_title_stripped (stripped OSC title, e.g. ⠋ hey… → hey…). No $session_name.
- Tab persistence — numeric tabs (
1, 2…) auto-rename to that stripped title. Manual names like DASH, HUB are respected and never overwritten.
Rep urposed from herdr-session-name (deprecated) → now herdr-session-title-name. No fork required — pure plugin for upstream herdr 0.8.2+.
Install
herdr plugin install jovylle/herdr-session-title-name --yes
herdr plugin list
# if you had the old id:
herdr plugin uninstall jovylle/herdr-session-name 2>/dev/null; herdr plugin unlink jovylle.session-name 2>/dev/null; true
herdr plugin log list --plugin jovylle.session-title-name
How it works
Herdr plugins can't hook terminal_title directly (PaneUpdated not in PLUGIN_HOOK_EVENT_KINDS), so this plugin uses two paths:
- Event hooks —
tab.created, pane.created, pane.focused, tab.focused, pane.exited → sync.sh fetches herdr api snapshot, finds each numeric tab's focused pane terminal_title_stripped, renames via herdr tab rename if needed.
- Startup poller —
watch.sh loops every 1.5s calling same sync, catching OSC title changes from hermes --tui -c "..." that don't fire an event.
Guard: only numeric labels ^[0-9]+$ are touched. Your DASH, github/jovylle stay.
Verify:
herdr api snapshot | python3 -c "import json,sys; d=json.loads(sys.stdin.read()); pans=d['result']['snapshot']['panes']; print([ (p['pane_id'], p.get('terminal_title_stripped')) for p in pans if p.get('terminal_title_stripped')][:5])"
herdr tab list | python3 -m json.tool | head -n 40
Herdr docs: https://herdr.dev/docs/configuration/ → Sidebar row layouts — tokens terminal_title / terminal_title_stripped.
Untouched config (no ~/.config/herdr/config.toml):
Add minimal title alone on top:
[ui.sidebar.agents]
rows = [["terminal_title_stripped"]]
If you want workspace/tab underneath:
[ui.sidebar.agents]
row_gap = 0
rows = [
["terminal_title_stripped"],
["state_icon", "workspace"],
[{ token = "tab", fg = "#101010" }]
]
Apply: herdr server reload-config
Modified config (you already have [ui.sidebar.agents]):
Prepend ["terminal_title_stripped"] as alone row on top — don't replace your other rows. Don't assume others have same config as yours.
Example your config before:
[ui.sidebar.agents]
rows = [
["agent", "$session_name"],
["terminal_title_stripped"],
["state_icon", "workspace"],
[{ token = "tab", fg = "#101010" }]
]
After (drop $session_name, title alone on top):
[ui.sidebar.agents]
rows = [
["terminal_title_stripped"],
["agent"],
["state_icon", "workspace"],
[{ token = "tab", fg = "#101010" }]
]
Fork users: session_title is alias for terminal_title_stripped at /lab/herdr-fork/src/config/sidebar.rs — both work, but plugin docs use upstream terminal_title_stripped.
Tab persistence demo
hermes --tui -c "hey what is 1 plus 1"
# sidebar top: hey what is 1 plus 1 (terminal_title_stripped)
# tab bar: 1 → hey what is 1 plus 1 (after ~1.5s)
# exit hermes — tab stays hey what is 1 plus 1
Files
herdr-plugin.toml — 0.3.0, hooks + startup poller
sync.sh — sync numeric tabs to stripped titles via herdr api snapshot
watch.sh — startup loop calling sync.sh every 1.5s
rename.sh — legacy shim (calls sync.sh)
site/index.html — landing page
Uninstall
herdr plugin uninstall jovylle/herdr-session-title-name
# if linked locally:
herdr plugin unlink jovylle.session-title-name
Redeploy landing: npx wrangler pages deploy site --project-name herdr-session-title-name --branch main