Skip to content

feat(tui): include session name in the terminal titlebar#43188

Merged
benbarclay merged 1 commit into
mainfrom
feat/tui-titlebar-session-name
Jun 10, 2026
Merged

feat(tui): include session name in the terminal titlebar#43188
benbarclay merged 1 commit into
mainfrom
feat/tui-titlebar-session-name

Conversation

@benbarclay

Copy link
Copy Markdown
Collaborator

Summary

The TUI sets the terminal/console titlebar via OSC 0 (useTerminalTitle), but until now it was composed from status marker + model + cwd only — the session's name never appeared, even though the TUI already knows it (you set it with /title, or auto-title generation produces one after the first response).

This changes the format to:

<marker> <session name> · <model> · <cwd>
  • marker (waiting on approval/sudo/secret/clarify), (busy), (idle)
  • session name — the current session's live (auto-)title; omitted when empty
  • model — short model name
  • cwd — truncated working dir; omitted when absent

When there's no session name yet (e.g. a brand-new session before auto-title lands), the titlebar is exactly the old <marker> <model> · <cwd>, so behavior is unchanged in that case.

How it works

The current session's title is read from the existing session.active_list poll that useMainApp already runs every 1.5s — each item already carries a current flag and its live title (server-side _session_live_item_session_live_title → DB lookup, so auto-titles are included). No new RPC / round-trip. UiState gains a sessionTitle field, patched only when it actually changes, preserving the existing idle-flicker guard.

The string-composition logic is extracted into a pure composeTabTitle() helper in domain/paths.ts (alongside shortCwd/fmtCwdBranch) so it's unit-testable.

Impact

Small UX nicety: when you run several Hermes sessions in different terminal tabs/windows, the OS tab/window title now disambiguates them by their session name instead of showing the same model · cwd for every tab. No effect on functionality.

Test plan

  • npm run type-check — clean
  • eslint on touched files — 0 errors (remaining warnings are pre-existing, in unrelated hooks)
  • composeTabTitle covered in paths.test.ts: ordering, name-omitted (== old format), whitespace-only name, cwd-omitted, marker-only fallback, truncation, boundary length — 8 new cases, all green
  • Full vitest run — green except one pre-existing failure in virtualHeights.test.ts ("compound user prompt width"), confirmed to fail identically on clean origin/main (verified by stash) and unrelated to this change

The terminal/console titlebar was composed from status marker + model +
cwd only; the session's (auto-)title never appeared, even though the TUI
already knows it.

Change the format to `<marker> <session name> · <model> · <cwd>`, with the
session name and cwd each omitted when absent so single-segment titles stay
clean. The current session's live title is pulled from the existing
session.active_list poll (which already carries each session's current flag
and title), so there's no extra round-trip; UiState gains a sessionTitle
field updated only when it actually changes, preserving the existing
idle-flicker guard.

Extract the join logic into a pure composeTabTitle() helper in domain/paths
and cover its edge cases (name omitted, cwd omitted, whitespace-only name,
marker-only fallback, truncation, boundary length) in paths.test.ts.
@github-actions

Copy link
Copy Markdown
Contributor

🔎 Lint report: feat/tui-titlebar-session-name vs origin/main

ruff

Total: 0 on HEAD, 0 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 0 pre-existing issues carried over.

ty (type checker)

Total: 10620 on HEAD, 10620 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 5564 pre-existing issues carried over.

Diagnostics are surfaced as warnings — this check never fails the build.

@benbarclay benbarclay merged commit d339653 into main Jun 10, 2026
20 checks passed
@benbarclay benbarclay deleted the feat/tui-titlebar-session-name branch June 10, 2026 01:24
wachoo pushed a commit to wachoo/hermes-agent that referenced this pull request Jun 10, 2026
…h#43188)

The terminal/console titlebar was composed from status marker + model +
cwd only; the session's (auto-)title never appeared, even though the TUI
already knows it.

Change the format to `<marker> <session name> · <model> · <cwd>`, with the
session name and cwd each omitted when absent so single-segment titles stay
clean. The current session's live title is pulled from the existing
session.active_list poll (which already carries each session's current flag
and title), so there's no extra round-trip; UiState gains a sessionTitle
field updated only when it actually changes, preserving the existing
idle-flicker guard.

Extract the join logic into a pure composeTabTitle() helper in domain/paths
and cover its edge cases (name omitted, cwd omitted, whitespace-only name,
marker-only fallback, truncation, boundary length) in paths.test.ts.
changman pushed a commit to changman/hermes-agent that referenced this pull request Jun 10, 2026
…h#43188)

The terminal/console titlebar was composed from status marker + model +
cwd only; the session's (auto-)title never appeared, even though the TUI
already knows it.

Change the format to `<marker> <session name> · <model> · <cwd>`, with the
session name and cwd each omitted when absent so single-segment titles stay
clean. The current session's live title is pulled from the existing
session.active_list poll (which already carries each session's current flag
and title), so there's no extra round-trip; UiState gains a sessionTitle
field updated only when it actually changes, preserving the existing
idle-flicker guard.

Extract the join logic into a pure composeTabTitle() helper in domain/paths
and cover its edge cases (name omitted, cwd omitted, whitespace-only name,
marker-only fallback, truncation, boundary length) in paths.test.ts.
alt-glitch pushed a commit that referenced this pull request Jun 14, 2026
The terminal/console titlebar was composed from status marker + model +
cwd only; the session's (auto-)title never appeared, even though the TUI
already knows it.

Change the format to `<marker> <session name> · <model> · <cwd>`, with the
session name and cwd each omitted when absent so single-segment titles stay
clean. The current session's live title is pulled from the existing
session.active_list poll (which already carries each session's current flag
and title), so there's no extra round-trip; UiState gains a sessionTitle
field updated only when it actually changes, preserving the existing
idle-flicker guard.

Extract the join logic into a pure composeTabTitle() helper in domain/paths
and cover its edge cases (name omitted, cwd omitted, whitespace-only name,
marker-only fallback, truncation, boundary length) in paths.test.ts.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant