Skip to content

feat(desktop): add configurable terminal font family (terminal.font_family in config.yaml) - #49592

Open
baoyu0 wants to merge 1 commit into
NousResearch:mainfrom
baoyu0:feat/terminal-font-family-config
Open

feat(desktop): add configurable terminal font family (terminal.font_family in config.yaml)#49592
baoyu0 wants to merge 1 commit into
NousResearch:mainfrom
baoyu0:feat/terminal-font-family-config

Conversation

@baoyu0

@baoyu0 baoyu0 commented Jun 20, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a new config option terminal.font_family that lets users customize the CSS font-family for the desktop app's embedded xterm.js terminal.

Problem

The embedded terminal font was hardcoded to:

JetBrains Mono, Cascadia Code, SF Mono, Menlo, Consolas, monospace

None of these are Nerd Fonts, so Nerd Font-only glyphs (like Starship prompt icons for the Windows logo) render as tofu/boxes. Users who have Nerd Fonts installed cannot configure the terminal to use them without patching the built desktop app JS.

Solution

Thread a new config value terminal.font_family from config.yaml through to the xterm.js Terminal constructor:

  1. Python backend (hermes_cli/config.py): added "font_family": "" to the terminal section of DEFAULT_CONFIG
  2. TypeScript types (types/hermes.ts): added font_family?: string to HermesConfig.terminal
  3. Config hook (use-hermes-config.ts): reads config.terminal?.font_family and exposes it as terminalFontFamily
  4. Component chain (desktop-controller.tsx -> persistent.tsx -> index.tsx -> use-terminal-session.ts): passes the value down to the Terminal constructor
  5. Fallback: when the field is empty or unset, the original hardcoded default is preserved (backward compatible)

Usage

# config.yaml
terminal:
  font_family: "'CaskaydiaCoveNerdFont', 'JetBrains Mono', monospace"

After restarting the desktop app, Nerd Font icons in the embedded terminal will render correctly.

Files changed

  • hermes_cli/config.py - added font_family default + documentation
  • apps/desktop/src/types/hermes.ts - added type
  • apps/desktop/src/app/session/hooks/use-hermes-config.ts - reads config value
  • apps/desktop/src/app/desktop-controller.tsx - wires value to terminal
  • apps/desktop/src/app/right-sidebar/terminal/persistent.tsx - passes through
  • apps/desktop/src/app/right-sidebar/terminal/index.tsx - passes through
  • apps/desktop/src/app/right-sidebar/terminal/use-terminal-session.ts - uses config value with fallback
  • apps/desktop/src/app/settings/constants.ts - field label + description for Settings UI

Testing

  • Verified config parsing: empty value falls back to built-in default
  • Settings UI displays "Terminal Font" field with description
  • The field supports arbitrary CSS font-family syntax (single font, font stacks, Nerd Font names)
  • Non-empty value overrides the xterm fontFamily in the Terminal constructor
  • No regressions: when font_family is unset or empty, behavior is identical to before
  • Pre-existing TypeScript lint errors untouched (all are path-alias resolution issues in test/build context)

…amily in config.yaml)

Adds a new config option terminal.font_family that lets users customize the
CSS font-family for the desktop app's embedded xterm.js terminal.

Previously the font was hardcoded in use-terminal-session.ts:
  'JetBrains Mono', 'Cascadia Code', 'SF Mono', Menlo, Consolas, monospace

Now the value from config.yaml (terminal.font_family) is threaded through:
  useHermesConfig → PersistentTerminal → TerminalTab → useTerminalSession

When font_family is empty or unset (default), the built-in fallback is used,
preserving backward compatibility. Users with Nerd Fonts installed (e.g.
CaskaydiaCoveNerdFont) can now set:

  terminal:
    font_family: 'CaskaydiaCoveNerdFont', 'JetBrains Mono', monospace

Closes: #terminal-font-config
@alt-glitch alt-glitch added type/feature New feature or request comp/tui Terminal UI (ui-tui/ + tui_gateway/) comp/cli CLI entry point, hermes_cli/, setup wizard P3 Low — cosmetic, nice to have comp/desktop Electron desktop app (apps/desktop/*) and removed comp/tui Terminal UI (ui-tui/ + tui_gateway/) labels Jun 20, 2026

@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 focused configuration contribution. The need still exists: current main hardcodes the interactive xterm font at apps/desktop/src/app/right-sidebar/terminal/use-terminal-session.ts:504.

Problems

  • The PR targets the old TerminalTab tree. Current main instead mounts TerminalWorkspace from persistent.tsx:136, which renders TerminalInstance in workspace.tsx:53-61; the changed terminal/index.tsx no longer exists. GitHub reports this PR as DIRTY.
  • At commit 98191306, use-hermes-config.ts:31,69 initializes the font as '' and fills it asynchronously, but use-terminal-session.ts:658 does not depend on fontFamily. If xterm is created first, it keeps the fallback font.
  • Current startup intentionally warms fonts before fitting and starting the PTY (use-terminal-session.ts:884-892); a custom family needs to participate in that path.

Suggested changes

  • Adapt the plumbing to the current PersistentTerminal → TerminalWorkspace → TerminalInstance → useTerminalSession path.
  • Add an update path that applies the resolved font, warms it, refits, and refreshes WebGL without restarting persistent terminals; cover delayed config resolution.
  • Decide whether the same setting should apply to the agent-background xterm at use-agent-terminal.ts:44.

Automated hermes-sweeper review.

convertEol: true,
cursorBlink: true,
fontFamily: "'JetBrains Mono', 'Cascadia Code', 'SF Mono', Menlo, Consolas, monospace",
fontFamily: fontFamily || "'JetBrains Mono', 'Cascadia Code', 'SF Mono', Menlo, Consolas, monospace",

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.

terminalFontFamily starts as '' and is set only after the asynchronous config request resolves, while this xterm-construction effect does not depend on fontFamily (line 658). If the terminal mounts first, it remains on the fallback for the session. Add a dedicated font-update path that also refits and clears the WebGL atlas; simply recreating the persistent terminal on every config response would discard shell state.

@teknium1 teknium1 added sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 14, 2026

@GottZ GottZ left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was generated by AI during triage.

Summary

Three PRs address the hardcoded Desktop terminal font: #49592 adds the initial config plumbing, #70925 expands it into a profile-scoped picker with lifecycle handling and tests, and #76395 carries that broader implementation onto current main.

Related pull requests

  • #49592 related — (+25/-8) — superseded by #76395: #49592 introduces terminal.font_family but targets the removed TerminalTab path and does not update an xterm instance when the asynchronously loaded font changes. Despite the keep_open review on #49592, #76395 implements the salvage path requested there through the current terminal hooks, including font warming and live updates.
  • #70925 [closed] related — (+1078/-30) — superseded by #76395: #70925 provides the comprehensive picker, profile persistence, both interactive and agent-terminal integration, font warming, live repaint, documentation, and tests. Despite the keep_open review on #70925, the #76395 diff contains the same core implementation while resolving the review's duplicate-import and nullable-observer cleanup blockers; #70925 remains relevant as the source branch identified as salvaged in the #76395 PR body and as superseded by #76395 in the contributor discussion on #70925.
  • #76395 [merged] related — (+1009/-30) — implemented reference: #76395 is the current-main implementation of configurable terminal fonts, covering both terminal surfaces, profile-scoped settings, safe fallback resolution, asynchronous warming, live repaint, config round-trip coverage, locales, and documentation. Its merged state makes it the reference that supersedes the two earlier proposals.

Duplicates

#70925 and #76395 are substantially the same end-to-end change, with #76395 carrying the implementation onto current main and resolving the documented review blockers. #49592 is the narrower configuration foundation whose intended behavior is subsumed by #76395.

Suggested consolidation

Close #49592 as duplicate of #76395: the chain is #49592#70925#76395, and the #76395 diff contains the current-tree implementation requested by the keep_open review on #49592. Keep #70925 closed as superseded by #76395; its keep_open review was appropriate before the duplicate imports and nullable-observer cleanup issue were addressed, but those fixes and the pending-font-preparation unmount test are present in #76395.

Cross-PR triage: Reviewed 3 pull requests and 0 issues in this complex. Each diff was read against this issue; Assessment working set: 116 kB of PR diffs, 8 kB of issue/PR text, 5 kB of discussion (10 comments), 0 verify verdicts. verdicts reflect diff content, not PR titles. Part of an automated triage batch.

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 comp/desktop Electron desktop app (apps/desktop/*) 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 type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants