# NousResearch/hermes-agent · Desktop UI zoom, font size, and scaling controls

## Open now

- 2 issues, 2 PRs open on GitHub.
- #38969: Desktop: Add text scaling and configurable text width / container margins
- #43417: \[Feature\]: 请问能增加调节字体大小功能？
- PR #51582: fix(desktop): app-level zoom that sticks, and session windows that inherit parent size
- PR #87172: fix(desktop): add Ctrl+R and F5 reload shortcut for Windows/Linux

These issues and pull requests collectively address the lack of zoom, font size, and UI scaling support in the desktop application, including keyboard shortcuts, appearance settings controls, and persistence of zoom state across sessions.

## TL;DR

- 24 member(s): 2 open issue(s), 16 closed issue(s), 2 open PR(s), 1 merged PR(s), 3 PR(s) closed without merging.
- A fix was merged to main in PR #60457. Verify it addresses your case.
- **Recommended:** read PR #60457 (and any competing PRs below) before filing. Confirm the merged change covers your symptom.

## Maintainer resolution verdict

- Internal-tracker verdict over this cluster's issue members: `unresolved`. This is distinct from the fix status above. Weigh it yourself.

## How this cluster was grouped

- Link evidence (`STRUCTURAL_PARTIAL`): some members are connected by structural evidence (shared changed files, or a closing/superseded reference); the rest are joined by an automated relevance judgement over their text.
- Members outside that structural core may belong to a different underlying problem.
- Pairwise link density `0.11`: the share of member pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36. `1.00` means every pair is linked.

## Open related issues

- #38969: Desktop: Add text scaling and configurable text width / container margins
- #43417: \[Feature\]: 请问能增加调节字体大小功能？

## Closed / duplicate issues

- #37619: Windows desktop app: add zoom / UI scaling support
- #37917: Desktop (Windows): Ctrl +/- zoom (text size) does nothing — application menu is null on non-mac with no fallback
- #40166: \[Desktop app\]: add font size / zoom control
- #40768: \[Desktop\]\[Windows\] Supplement to #40399: font size, chat text size, and density controls in Appearance
- #41879: Feature: Add font size scaling option for Hermes Desktop UI
- #45736: Feature: adjustable font size in Hermes desktop GUI (or CLI / config flag)
- #46097: Feature request: Desktop font size setting
- #47499: Feature request: UI zoom/scale controls
- #48336: Hermes Desktop: No UI zoom / font scaling support (Ctrl+/- ineffective, no config option)
- #48474: \[Feature\]: Default font size in settings
- #51918: \[Feature\]:  Font size / zoom setting in Desktop UI
- #53010: \[Feature Request\] Add font size settings for conversation area (accessibility & health)
- #53411: \[Feature\]: Can the UI font in the Desktop version be adjusted?
- #58161: \[Feature\]: I hope the desktop app adds a feature to adjust the interface font size.
- #60039: feat(desktop): increase default font size in chat interface (reference Codex Desktop)
- #64790: \[Feature\]: Add a font selector (family, size, color) to Desktop Appearance settings

## Prior & competing PRs

- **#41936: feat(desktop): add font size scaling option in Appearance settings**. closed without merge · fix tier `suggested`
  - maintainer direction: category `implemented_elsewhere`; implication `superseded`; refs `8ce3c2f99152e20be26abe604c57929fb8496dc7`, `#41879`
  - _suggested-tier fix detail withheld; re-request with `?tier=all` to include it._
- **#60457: feat(desktop): add UI scale setting to appearance settings (salvage #60249)**. merged to main · fix tier `verified`
  - maintainer direction: category `merged`; implication `superseded`
  - files: `apps/desktop/electron/main.cjs`, `apps/desktop/electron/preload.cjs`, `apps/desktop/electron/zoom.cjs`, `apps/desktop/electron/zoom.test.cjs`, `apps/desktop/package.json`, `apps/desktop/src/app/settings/appearance-settings.tsx`, `apps/desktop/src/global.d.ts`, `apps/desktop/src/i18n/en.ts`, `apps/desktop/src/i18n/ja.ts`, `apps/desktop/src/i18n/types.ts`, `apps/desktop/src/i18n/zh-hant.ts`, `apps/desktop/src/i18n/zh.ts`, `apps/desktop/src/store/zoom.ts`
  - fix hunks:
  - `apps/desktop/electron/main.cjs`

    ```diff
    @@ -4167,17 +4167,15 @@ function installPreviewShortcut(window) {
     // survives reloads/restarts) rather than a main-process JSON file. The main
     // process owns setZoomLevel, so we mirror each change into localStorage and
     // read it back on did-finish-load to re-apply after reloads or crash recovery.
    -const ZOOM_STORAGE_KEY = 'hermes:desktop:zoomLevel'
    -
    -function clampZoomLevel(value) {
    -  if (!Number.isFinite(value)) return 0
    -  return Math.min(Math.max(value, -9), 9)
    -}
    +const { ZOOM_STORAGE_KEY, clampZoomLevel, percentToZoomLevel, zoomLevelToPercent } = require('./zoom.cjs')
     
     function setAndPersistZoomLevel(window, zoomLevel) {
       if (!window || window.isDestroyed()) return
       const next = clampZoomLevel(zoomLevel)
       window.webContents.setZoomLevel(next)
    +  // Keep any open settings UI in sync, including changes made via the
    +  // keyboard shortcuts or the View menu.
    +  window.webContents.send('hermes:zoom:changed', { level: next, percent: zoomLevelToPercent(next) })
       window.webContents
         .executeJavaScript(
           `try { localStorage.setItem(${JSON.stringify(ZOOM_STORAGE_KEY)}, ${JSON.stringify(String(next))}) } catch {}`
    ```

    ```diff
    @@ -6158,6 +6156,21 @@ ipcMain.handle('hermes:window:openNewSession', async () => {
       return { ok: true }
     })
     
    +// --- Text size (zoom) -------------------------------------------------------
    +// The settings UI drives the same clamped zoom scale as the Ctrl/Cmd
    +// shortcuts and the View menu. Reads and writes target the asking window.
    +ipcMain.handle('hermes:zoom:get', event => {
    +  const window = BrowserWindow.fromWebContents(event.sender)
    +  const level = window && !window.isDestroyed() ? window.webContents.getZoomLevel() : 0
    +
    +  return { level, percent: zoomLevelToPercent(level) }
    +})
    +ipcMain.on('hermes:zoom:set-percent', (event, percent) => {
    +  const window = BrowserWindow.fromWebContents(event.sender)
    +  if (!window || window.isDestroyed()) return
    +  setAndPersistZoomLevel(window, percentToZoomLevel(Number(percent)))
    +})
    +
     // --- Pet overlay (pop-out mascot) -----------------------------------------
     // `request` is `{ bounds, screen }`. A fresh pop-out passes viewport-space
     // bounds (screen=false): convert to screen space by adding the main window's
    ```
  - `apps/desktop/electron/preload.cjs`

    ```diff
    @@ -78,6 +78,18 @@ contextBridge.exposeInMainWorld('hermesDesktop', {
         setDefaultProjectDir: dir => ipcRenderer.invoke('hermes:setting:defaultProjectDir:set', dir),
         pickDefaultProjectDir: () => ipcRenderer.invoke('hermes:setting:defaultProjectDir:pick')
       },
    +  zoom: {
    +    // Current zoom of this window, as { level, percent }.
    +    get: () => ipcRenderer.invoke('hermes:zoom:get'),
    +    setPercent: percent => ipcRenderer.send('hermes:zoom:set-percent', percent),
    +    // Fires on every zoom change, including the Ctrl/Cmd +/-/0 shortcuts,
    +    // so the settings UI can stay in sync with the keyboard.
    +    onChanged: callback => {
    +      const listener = (_event, payload) => callback(payload)
    +      ipcRenderer.on('hermes:zoom:changed', listener)
    +      return () => ipcRenderer.removeListener('hermes:zoom:changed', listener)
    +    }
    +  },
       revealLogs: () => ipcRenderer.invoke('hermes:logs:reveal'),
       getRecentLogs: () => ipcRenderer.invoke('hermes:logs:recent'),
       readDir: dirPath => ipcRenderer.invoke('hermes:fs:readDir', dirPath),
    ```
  - `apps/desktop/electron/zoom.cjs`

    ```diff
    @@ -0,0 +1,34 @@
    +/**
    + * Pure helpers for window zoom. The main process owns webContents.setZoomLevel,
    + * so the menu items, the Ctrl/Cmd shortcuts, and the settings UI all funnel
    + * through this one clamped scale. Percent is the user-facing unit (100 = the
    + * default size); Chromium's internal unit is the zoom level, where
    + * factor = 1.2 ^ level.
    + */
    +
    +const ZOOM_STORAGE_KEY = 'hermes:desktop:zoomLevel'
    +
    +const ZOOM_FACTOR_BASE = 1.2
    +const MIN_ZOOM_LEVEL = -9
    +const MAX_ZOOM_LEVEL = 9
    +
    +function clampZoomLevel(value) {
    +  if (!Number.isFinite(value)) return 0
    +  return Math.min(Math.max(value, MIN_ZOOM_LEVEL), MAX_ZOOM_LEVEL)
    +}
    +
    +function zoomLevelToPercent(level) {
    +  return Math.round(Math.pow(ZOOM_FACTOR_BASE, clampZoomLevel(level)) * 100)
    +}
    +
    +function percentToZoomLevel(percent) {
    +  if (!Number.isFinite(percent) || percent <= 0) return 0
    +  return clampZoomLevel(Math.log(percent / 100) / Math.log(ZOOM_FACTOR_BASE))
    +}
    +
    +module.exports = {
    +  ZOOM_STORAGE_KEY,
    +  clampZoomLevel,
    +  percentToZoomLevel,
    +  zoomLevelToPercent
    +}
    ```
  - `apps/desktop/electron/zoom.test.cjs`

    ```diff
    @@ -0,0 +1,54 @@
    +/**
    + * Unit tests for the pure zoom helpers: clamping garbage input, the
    + * percent <-> zoom-level conversion the settings UI relies on, and the
    + * roundtrip stability of the preset percentages.
    + */
    +
    +const test = require('node:test')
    +const assert = require('node:assert/strict')
    +
    +const { ZOOM_STORAGE_KEY, clampZoomLevel, percentToZoomLevel, zoomLevelToPercent } = require('./zoom.cjs')
    +
    +test('storage key stays stable so persisted zoom survives upgrades', () => {
    +  assert.equal(ZOOM_STORAGE_KEY, 'hermes:desktop:zoomLevel')
    +})
    +
    +test('clampZoomLevel rejects garbage and enforces bounds', () => {
    +  assert.equal(clampZoomLevel(NaN), 0)
    +  assert.equal(clampZoomLevel(Infinity), 0)
    +  assert.equal(clampZoomLevel(undefined), 0)
    +  assert.equal(clampZoomLevel('2'), 0)
    +  assert.equal(clampZoomLevel(0.3), 0.3)
    +  assert.equal(clampZoomLevel(-42), -9)
    +  assert.equal(clampZoomLevel(42), 9)
    +})
    +
    +test('level 0 is exactly 100 percent', () => {
    +  assert.equal(zoomLevelToPercent(0), 100)
    +  assert.equal(percentToZoomLevel(100), 0)
    +})
    +
    +test('percentToZoomLevel rejects garbage', () => {
    +  assert.equal(percentToZoomLevel(NaN), 0)
    +  assert.equal(percentToZoomLevel(0), 0)
    +  assert.equal(percentToZoomLevel(-50), 0)
    +  assert.equal(percentToZoomLevel(undefined), 0)
    +})
    +
    +test('preset percentages roundtrip within rounding', () => {
    +  for (const percent of [90, 100, 110, 125, 150, 175]) {
    +    assert.equal(zoomLevelToPercent(percentToZoomLevel(percent)), percent)
    +  }
    +})
    +
    +test('conversion is monotonic across the preset range', () => {
    +  const levels = [90, 100, 110, 125, 150, 175].map(percentToZoomLevel)
    +  for (let i = 1; i < levels.length; i++) {
    +    assert.ok(levels[i] > levels[i - 1])
    +  }
    +})
    +
    +test('extreme percentages clamp to the level bounds', () => {
    +  assert.equal(percentToZoomLevel(1), -9)
    +  assert.equal(percentToZoomLevel(1_000_000), 9)
    +})
    ```
  - `apps/desktop/package.json`

    ```diff
    @@ -37,7 +37,7 @@
         "test:desktop:nsis": "node scripts/test-desktop.mjs nsis",
         "test:desktop:existing": "node scripts/test-desktop.mjs existing",
         "test:desktop:fresh": "node scripts/test-desktop.mjs fresh",
    -    "test:desktop:platforms": "node --test electron/bootstrap-platform.test.cjs electron/hardening.test.cjs electron/backend-env.test.cjs electron/backend-probes.test.cjs electron/backend-ready.test.cjs electron/bootstrap-runner.test.cjs electron/connection-config.test.cjs electron/dashboard-token.test.cjs electron/gateway-ws-probe.test.cjs electron/oauth-net-request.test.cjs electron/desktop-uninstall.test.cjs electron/session-windows.test.cjs electron/link-title-window.test.cjs electron/workspace-cwd.test.cjs electron/fs-read-dir.test.cjs electron/git-root.test.cjs electron/git-worktree-ops.test.cjs electron/windows-child-process.test.cjs electron/update-remote.test.cjs electron/update-count.test.cjs electron/update-rebuild.test.cjs electron/update-marker.test.cjs electron/update-relaunch.test.cjs electron/windows-user-env.test.cjs electron/wsl-clipboard-image.test.cjs electron/titlebar-overlay-width.test.cjs electron/window-state.test.cjs electron/windows-hermes-resolution.test.cjs electron/oauth-session-request.test.cjs",
    +    "test:desktop:platforms": "node --test electron/bootstrap-platform.test.cjs electron/hardening.test.cjs electron/backend-env.test.cjs electron/backend-probes.test.cjs electron/backend-ready.test.cjs electron/bootstrap-runner.test.cjs electron/connection-config.test.cjs electron/dashboard-token.test.cjs electron/gateway-ws-probe.test.cjs electron/oauth-net-request.test.cjs electron/desktop-uninstall.test.cjs electron/session-windows.test.cjs electron/link-title-window.test.cjs electron/workspace-cwd.test.cjs electron/fs-read-dir.test.cjs electron/git-root.test.cjs electron/git-worktree-ops.test.cjs electron/windows-child-process.test.cjs electron/update-remote.test.cjs electron/update-count.test.cjs electron/update-rebuild.test.cjs electron/update-marker.test.cjs electron/update-relaunch.test.cjs electron/windows-user-env.test.cjs electron/wsl-clipboard-image.test.cjs electron/titlebar-overlay-width.test.cjs electron/window-state.test.cjs electron/zoom.test.cjs electron/windows-hermes-resolution.test.cjs electron/oauth-session-request.test.cjs",
         "typecheck": "tsc -p . --noEmit",
         "lint": "eslint src/ electron/",
         "lint:fix": "eslint src/ electron/ --fix",
    ```
  - `apps/desktop/src/app/settings/appearance-settings.tsx`

    ```diff
    @@ -16,6 +16,7 @@ import { $embedAllowed, $embedMode, clearEmbedAllowed, type EmbedMode, setEmbedM
     import { $activeGatewayProfile, $profiles, normalizeProfileKey } from '@/store/profile'
     import { $toolViewMode, setToolViewMode } from '@/store/tool-view'
     import { $translucency, setTranslucency } from '@/store/translucency'
    +import { $zoomPercent, setZoomPercent } from '@/store/zoom'
     import { getBaseColors, useTheme } from '@/themes/context'
     import { installVscodeThemeFromMarketplace } from '@/themes/install'
     import type { DesktopTheme } from '@/themes/types'
    ```

    ```diff
    @@ -62,6 +63,18 @@ function ThemePreview({ name, mode }: { name: string; mode: 'light' | 'dark' })
       )
     }
     
    +// UI scale presets, as zoom percentages. 100 is the browser-default size;
    +// the ids double as the percent values sent to the main process. A Cmd/Ctrl
    +// +/- step landing between presets highlights nothing, and the row
    +// description keeps showing the exact current percent.
    +const UI_SCALE_PRESETS = ['90', '100', '110', '125', '150', '175'] as const
    +
    +type UiScalePreset = (typeof UI_SCALE_PRESETS)[number]
    +
    +function matchUiScalePreset(percent: number): UiScalePreset | null {
    +  return UI_SCALE_PRESETS.find(preset => Number(preset) === percent) ?? null
    +}
    +
     function useDebounced<T>(value: T, delayMs: number): T {
       const [debounced, setDebounced] = useState(value)
     
    ```

    ```diff
    @@ -231,6 +244,7 @@ export function AppearanceSettings() {
       const { t, isSavingLocale } = useI18n()
       const { themeName, mode, resolvedMode, availableThemes, setTheme, setMode } = useTheme()
       const toolViewMode = useStore($toolViewMode)
    +  const zoomPercent = useStore($zoomPercent)
       const embedMode = useStore($embedMode)
       const embedAllowed = useStore($embedAllowed)
       const translucency = useStore($translucency)
    ```

    ```diff
    @@ -277,6 +291,10 @@ export function AppearanceSettings() {
         { id: 'off', label: a.embedsOff }
       ] as const satisfies readonly { id: EmbedMode; label: string }[]
     
    +  const uiScaleOptions = UI_SCALE_PRESETS.map(preset => ({ id: preset, label: `${preset}%` }))
    +
    +  const matchedScalePreset = matchUiScalePreset(zoomPercent)
    +
       return (
         <SettingsContent>
           <div>
    ```

    ```diff
    @@ -392,6 +410,21 @@ export function AppearanceSettings() {
                 wide
               />
     
    +          <ListRow
    +            action={
    +              <SegmentedControl
    +                onChange={id => {
    +                  triggerHaptic('selection')
    +                  setZoomPercent(Number(id))
    +                }}
    +                options={uiScaleOptions}
    +                value={matchedScalePreset ?? ('' as UiScalePreset)}
    +              />
    +            }
    +            description={a.uiScaleDesc(zoomPercent)}
    +            title={a.uiScaleTitle}
    +          />
    +
               <ListRow
                 action={
                   <div className="flex items-center gap-3">
    ```
  - `apps/desktop/src/global.d.ts`

    ```diff
    @@ -89,6 +89,11 @@ declare global {
             pickDefaultProjectDir: () => Promise<{ canceled: boolean; dir: null | string }>
             setDefaultProjectDir: (dir: null | string) => Promise<{ dir: null | string }>
           }
    +      zoom?: {
    +        get: () => Promise<{ level: number; percent: number }>
    +        setPercent: (percent: number) => void
    +        onChanged: (callback: (payload: { level: number; percent: number }) => void) => () => void
    +      }
           revealLogs: () => Promise<{ ok: boolean; path: string; error?: string }>
           getRecentLogs: () => Promise<{ path: string; lines: string[] }>
           readDir: (path: string) => Promise<HermesReadDirResult>
    ```
  - `apps/desktop/src/i18n/en.ts`

    ```diff
    @@ -381,6 +381,9 @@ export const en: Translations = {
           colorModeDesc: 'Pick a fixed mode or let Hermes follow your system setting.',
           toolViewTitle: 'Tool Call Display',
           toolViewDesc: 'Product hides raw tool payloads; Technical shows full input/output.',
    +      uiScaleTitle: 'UI Scale',
    +      uiScaleDesc: (percent: number) =>
    +        `Scales text and controls across the whole app. Cmd/Ctrl with +, - and 0 also works. Current: ${percent}%.`,
           translucencyTitle: 'Window Translucency',
           translucencyDesc: 'See your desktop through the whole window. macOS and Windows only.',
           embedsTitle: 'Inline Embeds',
    ```
  - `apps/desktop/src/i18n/ja.ts`

    ```diff
    @@ -287,6 +287,9 @@ export const ja = defineLocale({
           colorModeDesc: '固定モードを選ぶか、Hermes をシステム設定に合わせます。',
           toolViewTitle: 'ツール呼び出しの表示',
           toolViewDesc: 'プロダクト表示は生のツールペイロードを隠し、テクニカル表示は入出力をすべて表示します。',
    +      uiScaleTitle: 'UI スケール',
    +      uiScaleDesc: (percent: number) =>
    +        `アプリ全体の文字と UI を拡大縮小します。Cmd/Ctrl と +、-、0 でも変更できます。現在: ${percent}%`,
           translucencyTitle: 'ウィンドウの透過',
           translucencyDesc: 'ウィンドウ全体を透過させてデスクトップを表示します。macOS と Windows のみ。',
           embedsTitle: 'インライン埋め込み',
    ```
  - `apps/desktop/src/i18n/types.ts`

    ```diff
    @@ -302,6 +302,8 @@ export interface Translations {
           colorModeDesc: string
           toolViewTitle: string
           toolViewDesc: string
    +      uiScaleTitle: string
    +      uiScaleDesc: (percent: number) => string
           translucencyTitle: string
           translucencyDesc: string
           embedsTitle: string
    ```
  - `apps/desktop/src/i18n/zh-hant.ts`

    ```diff
    @@ -279,6 +279,8 @@ export const zhHant = defineLocale({
           colorModeDesc: '選擇固定模式，或讓 Hermes 跟隨系統設定。',
           toolViewTitle: '工具呼叫顯示',
           toolViewDesc: '產品模式會隱藏原始工具 payload；技術模式會顯示完整輸入/輸出。',
    +      uiScaleTitle: '介面縮放',
    +      uiScaleDesc: (percent: number) => `縮放整個應用程式的文字與介面。也可使用 Cmd/Ctrl 加 +、- 或 0 調整。目前：${percent}%`,
           translucencyTitle: '視窗透明',
           translucencyDesc: '讓整個視窗透出桌面。僅支援 macOS 與 Windows。',
           embedsTitle: '內嵌預覽',
    ```
  - `apps/desktop/src/i18n/zh.ts`

    ```diff
    @@ -370,6 +370,8 @@ export const zh: Translations = {
           colorModeDesc: '选择固定模式，或让 Hermes 跟随系统设置。',
           toolViewTitle: '工具调用显示',
           toolViewDesc: '产品模式隐藏原始工具数据；技术模式显示完整输入/输出。',
    +      uiScaleTitle: '界面缩放',
    +      uiScaleDesc: (percent: number) => `缩放整个应用的文字和界面。也可使用 Cmd/Ctrl 加 +、- 或 0 调整。当前：${percent}%`,
           translucencyTitle: '窗口透明',
           translucencyDesc: '让整个窗口透出桌面。仅支持 macOS 和 Windows。',
           embedsTitle: '内嵌预览',
    ```
  - `apps/desktop/src/store/zoom.ts`

    ```diff
    @@ -0,0 +1,22 @@
    +/**
    + * Window text size (zoom).
    + *
    + * The main process owns the zoom level and persists it (see electron/zoom.cjs
    + * for the scale). The renderer only mirrors the current percent for the
    + * settings UI: preset clicks go to the main process over IPC, and every
    + * change comes back through onChanged, including ones made with the
    + * Ctrl/Cmd +/-/0 shortcuts or the View menu, so the UI never drifts.
    + */
    +
    +import { atom } from 'nanostores'
    +
    +export const $zoomPercent = atom<number>(100)
    +
    +export function setZoomPercent(percent: number): void {
    +  window.hermesDesktop?.zoom?.setPercent(percent)
    +}
    +
    +if (typeof window !== 'undefined' && window.hermesDesktop?.zoom) {
    +  void window.hermesDesktop.zoom.get().then(({ percent }) => $zoomPercent.set(percent))
    +  window.hermesDesktop.zoom.onChanged(({ percent }) => $zoomPercent.set(percent))
    +}
    ```
- **#51582: fix(desktop): app-level zoom that sticks, and session windows that inherit parent size**. open
  - maintainer direction: category `uncategorized`; implication `needs_llm`
  - files: `apps/desktop/electron/main.cjs`, `apps/desktop/electron/session-windows.cjs`, `apps/desktop/electron/session-windows.test.cjs`, `apps/desktop/electron/zoom.cjs`, `apps/desktop/electron/zoom.test.cjs`, `apps/desktop/package.json`
- **#60249: feat(desktop): add UI scale setting to appearance settings**. closed without merge
  - maintainer direction: category `merged_via`; implication `superseded`; refs `#60457`
- **#87172: fix(desktop): add Ctrl+R and F5 reload shortcut for Windows/Linux**. open
  - maintainer direction: category `duplicate_of`; implication `duplicate`; refs `#79870`
  - files: `apps/desktop/electron/main.ts`, `apps/desktop/electron/reload-shortcut.test.ts`
- **#116606: feat(desktop): add configurable chat reading width**. closed without merge
  - maintainer direction: category `uncategorized`; implication `needs_llm`

## Fix status

- Merged to main in PR #60457 (cited above). No release data is tracked. Verify downstream.
- Fix last verified (merged) `2026-07-07`.
- Subsystem: `apps/desktop`
