Skip to content

feat: global font magnification setting (50–200%) for terminals + chrome #3147

Description

@the-gigi

Summary

cmux currently has per-pane font zoom for terminals (Cmd+=/-/0 → Ghostty's increase_font_size / decrease_font_size / reset_font_size) and a parallel per-pane page zoom for browser panels (browserZoomIn/Out/Reset). It does not have a way to scale all fonts in the app at once — terminal glyphs, tab bar titles, sidebar workspace rows, workspace headers, notifications, settings, command palette — without manually zooming each pane and leaving the chrome untouched.

This issue tracks adding a global font magnification setting that scales every font in cmux uniformly via a single percentage, with per-pane zoom continuing to layer on top for the focused pane.

Why this matters

  • Low-vision users: the only existing affordance is per-pane terminal zoom. Workspace names, tab titles, sidebar branch names, status pills, and command palette text all stay at their design size — hard to read for users with poor vision.
  • Per-pane zoom doesn't compose: a workspace with 6 panes requires 6 separate Cmd+= sequences, and re-zooming on every new split is friction. Even after that, the chrome around them is still small.
  • macOS Accessibility → Zoom is too coarse: it scales the entire screen pixel-for-pixel, blurring text. cmux can render at the larger size natively for crisper text.
  • No config-file equivalent: font-size in the cmux/Ghostty config controls only the terminal default; there's no knob for tab bar / sidebar / workspace title sizing without per-element overrides.

Proposed shape

Single app.globalFontMagnification setting (integer percent), 50–200% in 10% steps, default 100%.

  • Terminals: scale Ghostty's parsed font-size by the percent (read via ghostty_config_get, multiply, re-inject before ghostty_config_finalize).
  • Tab bar: scale surface-tab-bar-font-size proportionally.
  • SwiftUI chrome: a .cmuxFont(size:) / .cmuxFont(.caption) view modifier reading @AppStorage(GlobalFontMagnification.percentKey) so every site re-renders live when the user changes the value. All hardcoded .font(.system(size:)) / .font(.caption) / .font(.headline) etc. call sites in Sources/ go through it (~270 sites).
  • Per-pane zoom is unchanged: Cmd+=/-/0 still hits Ghostty's per-surface zoom for terminals and the browser-panel page zoom for browsers, layering on top of whatever the global value resolved to.
  • Settings UI: a row in App settings with a stepper + Reset button. Live updates.
  • cmux.json: app.globalFontMagnification key in ~/.config/cmux/settings.json, schema in web/data/cmux-settings.schema.json.
  • Reset All Settings: returns magnification to 100% along with everything else.

Why cap at 200%?

cmux has fixed-size budgets in places (titlebar height, command palette / help-menu rows, browser button hit areas, badge frames). At ≤200% these absorb the scaled labels without clipping; above that, chrome starts to break. Users who need larger zoom can use macOS Accessibility → Zoom for system-wide scaling instead.

Implementation

Implemented in #3145.

Environment

  • cmux on macOS 15+ (no version-specific dependencies — works as far back as the current minimum).

Filed by

Filed retroactively to track the feature alongside PR #3145.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions