feat(web): configurable fonts and sizes under Settings → Appearance - #5103
Conversation
Adds a Fonts section to Appearance with four client-persisted preferences — interface (sans), composer, code, and terminal font families. Family only; sizing is deliberately left for a follow-up. - contracts: four FontFamilyPreference client settings (empty string means default), patchable per key - the font theme tokens move out of the inline Tailwind theme so utilities reference the variables, and a FontAppearanceSync applies custom families as CSS variable overrides with the default stacks kept as fallbacks - the composer gets its own --font-composer variable (defaults to the sans stack) applied on the editor surface, so prompt writers can use a mono face without changing the rest of the app - the terminal preference feeds the Ghostty surface's font option and live setFont from pingdotgg#4860's groundwork; the bundled Nerd Font symbols fallback keeps prompt glyphs on any custom face - each settings row shows a live preview rendered in the resolved stack, with per-row reset; custom names are normalized and quoted through tested pure helpers Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…views Replaces the free-text family inputs with dropdowns of curated faces filtered through document.fonts.check so only fonts that will actually render are offered (bundled webfonts always appear); a Custom… option keeps arbitrary families possible. Each option renders in its own face, and every row gains a preview card styled like the real surface — chat text, a mini composer, a highlighted code snippet, and a dark terminal prompt — rendered in the resolved stack, matching mobile's Appearance screen style. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The pre and code elements in the preview cards carried the preflight mono font-family, overriding the card's resolved stack, so those two previews never changed with the dropdown. They inherit now; also brace the comment-looking literal flagged by lint. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…views document.fonts.check() answers true for families that are not installed (nothing needs loading), so the dropdowns offered fonts that silently fell back to the default stack and the sans-side previews appeared not to update. Availability now comes from canvas metric probing: a family counts as available when substituting it before a generic changes the measured advance. The terminal preview card also follows the app theme now — the real terminal renders on the app background in light mode, so a hardcoded dark card was inconsistent theming. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The base styles hardcoded literal font stacks on body and pre/code, so the runtime --font-sans/--font-mono overrides from Settings -> Appearance only reached the preview cards. Reference the theme tokens instead; the literal stacks stay single-sourced in the @theme block. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ApprovabilityVerdict: Needs human review This PR introduces a new user-facing feature (configurable fonts and sizes in Settings → Appearance) with substantial new components, font picker UI with Local Font Access API integration, and changes to how fonts render across all app surfaces. New features of this scope warrant human review. You can customize Macroscope's approvability policy. Learn more. |
Client settings hydrate after mount, which dropped two things on reload: the terminal font (setFont fired while the surface was still loading, so the preference never reached the created terminal) and the custom-font input (customMode initialized from the pre-hydration empty value, leaving the field hidden behind a "Custom" trigger). The terminal re-applies the current preference once the surface exists, and the input visibility now derives from the value itself. Also groups mixed dropdowns (composer) into labeled Sans serif / Monospace sections and removes the composer's redundant default entry - the reset affordance already returns it to following the interface font. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…om names Every font dropdown now offers the full catalog split into bold Sans serif / Monospace sections, so any surface can point at any face. The custom input edits a draft that only commits once the typed name probes as an installed font - the current font holds (and the field flags invalid) while a partial or unknown name is typed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… tokens The @pierre/diffs surfaces (file previews, chat diffs, annotatable code, search lines) render inside shadow roots with their own literal font stack as fallback, so the code font preference never reached them. The library consults --diffs-font-family/--diffs-header-font-family as override hooks and custom properties inherit across the shadow boundary, so defining the hooks once at :root covers every consumer. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…r preview Restore defaults now lists and resets the four font-family preferences (the General page's restore is intentionally global), and the composer preview falls back to the resolved interface stack so it matches the runtime var(--font-composer) chain instead of the bare default sans stack. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Per review direction the interface and code fonts stay on the theme defaults; only the prompt textarea (people who prefer writing prompts in a mono face) and the terminal remain configurable. The textarea setting is retitled to make its scope explicit - the rest of the composer follows the interface font. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
An emptied custom font field now resets the preference to the default instead of silently keeping the previous font behind an empty-looking input; partial or unknown names still hold the current font while typing. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The final split keeps every surface configurable: interface (labels, controls, messages, composer chrome), prompt (textarea and placeholder only), code (code blocks, diffs, file previews), and terminal. Every dropdown now offers the same Default entry, fixing the prompt/terminal inconsistency. The custom input no longer commits on every keystroke: it edits a local draft and commits 400ms after typing pauses (or on Enter/blur), so the app does not reflow mid-word and the unknown-name flag waits for the pause. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Quote custom terminal families before they reach the canvas font string:
a non-ident name ("3270 Nerd Font", "M+ 1m") made the whole string
invalid CSS, so the assignment silently kept the previous font.
- Point the DM Sans catalog entry at the registered "DM Sans Variable"
family; the bundled webfont never registers plain "DM Sans", so the
option rendered in the serif fallback and only applied by coincidence.
- Cap the custom input at the schema's 200-character limit.
- Cover fontOptionCategories and non-ident quoting with tests.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The custom input now replaces the dropdown instead of stacking beneath it, so entering custom mode no longer grows the row and pushes the rest of the page down; it autofocuses, and Escape discards uncommitted typing without closing the settings page. Typefaces differ in x-height at the same pixel size (DM Sans 0.51 vs JetBrains Mono 0.55), so switching family also changed apparent text size. Each surface now carries a font-size-adjust measured from its own default stack: the platform default renders unchanged, and any chosen font is scaled to match it. Measurements are re-taken once webfonts finish loading, since an early probe describes the fallback face rather than the default. The sidebar PR number follows the interface font (tabular digits keep it from reflowing) instead of the code font. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The section defaults to two rows - one sans, one monospace - with the demos showing every surface each choice reaches. An Advanced switch in the section header reveals the per-surface rows (prompt, terminal, anti-aliasing); the state persists locally, and a settings-search jump to a hidden row flips the switch for the session so the target exists. The cascade behind the simple view is real: the terminal now inherits the monospace preference unless overridden. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Keyboard selection commits: the combobox commits through onValueChange instead of per-item clicks, so Enter on a highlighted font works, and keyboard highlights scroll the virtualized list into view the way the branch selector does. - The picker popup opens after mount instead of mounting open, so the exit transition has a style baseline and close cannot wedge. - Preview sessions no longer grant local-fonts: untrusted preview content must not read the user's installed-font fingerprint. The app's own picker runs in the main window session. - The simple-mode Monospace row keeps the code-font search anchor under its custom title. - A settings-search jump to font smoothing on non-macOS no longer pins Advanced on: the target set is platform-gated and each jump expands at most once. - The Advanced preference persists through the shared useLocalStorage hook instead of hand-rolled helpers. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit deb9252. Configure here.
| if (lastExpandedTargetRef.current === searchTargetId) return; | ||
| lastExpandedTargetRef.current = searchTargetId; | ||
| setAdvanced(true); | ||
| }, [searchTargetId, setAdvanced]); |
There was a problem hiding this comment.
Repeat search skips Advanced expand
Medium Severity
The lastExpandedTargetRef isn't reset when the search target is cleared. This prevents the "Advanced" typography section from expanding on subsequent searches for the same advanced setting, making the target unscrollable.
Reviewed by Cursor Bugbot for commit deb9252. Configure here.
The input-until-focused flow exists only because raising the browser's local-fonts prompt needs a user gesture. When the permission is already granted - Electron approves silently with no prompt UI, and a browser that granted once reports granted on return visits - no gesture is needed, so the rows probe the Permissions API at mount and render the picker right away. "prompt" and "denied" keep the focus-driven flow. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The parse cache hands back shared mutable file objects, and a FileDiff instance keys its render and highlight bookkeeping on them - the same reason DiffPanel scopes its cache per theme. With the simple and advanced typography views both consuming one cached parse, a remounted preview could inherit stale already-highlighted state and render plain text. Each mount now parses under its own scope. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The interactive FileDiff's mount lifecycle can race the shared shiki singleton when the typography views remount it - its render cache is seeded highlighted-before-highlighting, so a lost race locks in an unhighlighted frame permanently. The preview needs no interactivity, so it now renders once per theme through the SSR pipeline (which always awaits the highlighter before emitting HTML) and injects the finished markup into a shadow root, the same way FileDiff hosts it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
@juliusmarminge the goat |
## What's Changed * fix(web): better right panel (new diffs styling) by @maria-rcks in pingdotgg/t3code#5260 * fix(server): keep regenerated titles on topic by @t3dotgg in pingdotgg/t3code#5365 * refactor(server): make title prompts plaintext by @t3dotgg in pingdotgg/t3code#5368 * feat(web): configurable fonts and sizes under Settings → Appearance by @StiensWout in pingdotgg/t3code#5103 * feat(sidebar-v2): bring back thread pinning by @t3dotgg in pingdotgg/t3code#5312 * feat(web): make pairing QR codes actually scannable, with endpoint choice by @t3dotgg in pingdotgg/t3code#5360 * fix(desktop,web): improve in-app browser shortcuts and URL behavior by @t3dotgg in pingdotgg/t3code#4703 * fix(web): prevent legacy model picker layout shift by @FllipEis in pingdotgg/t3code#5349 * fix(server): allow remote updates with database migrations by @t3dotgg in pingdotgg/t3code#5374 **Full Changelog**: pingdotgg/t3code@v0.0.32-nightly.20260804.1000...v0.0.32-nightly.20260805.1002 Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.32-nightly.20260805.1002
The merge resolution kept "DM Sans Variable"/"JetBrains Mono" in --font-sans and --font-mono on the assumption they were fork branding. They were not: those stacks are byte-identical to the merge base, and upstream's pingdotgg#5103 deliberately removed the bundled @fontsource packages, their imports, and the stacks together so Settings -> Appearance can supply the family instead. Keeping the names would have left the CSS asking for fonts the app no longer ships. Co-Authored-By: Claude <noreply@anthropic.com>
31 upstream commits (through 3c5bdb8). Three conflicts, all in fork contact files: - apps/server/src/http.ts: upstream replaced the hand-rolled compression middleware with HttpMiddleware.compression(). Dropped the stale middleware from our side, kept the fork's static cache-header block (HTML_SHELL_CACHE_HEADERS / IMMUTABLE_ASSET_CACHE_HEADERS / isFingerprintedAsset); its response-site usages auto-merged. - apps/web/src/components/SidebarV2.tsx: upstream expanded the useThreadActions destructure for thread pinning (pingdotgg#5312). Took theirs, re-appended the fork's `const forkThread = useForkThread()`. - apps/web/src/components/settings/SettingsPanels.tsx: upstream relocated the word-wrap row into the new typography area (pingdotgg#5103). Dropped the stale word-wrap block, kept the fork's <ExternalSessionsSettingRow /> at the end of the Appearance section. Tripwire reported zero dropped fork lines. pnpm-lock.yaml auto-merged and `corepack pnpm install --lockfile-only` confirmed it consistent. vp run typecheck and vp check both clean (0 errors, 0 warnings). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ingdotgg#5103) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Julius Marminge <julius0216@outlook.com>
…ingdotgg#5103) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Julius Marminge <julius0216@outlook.com>
…ingdotgg#5103) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Julius Marminge <julius0216@outlook.com>
…ingdotgg#5103) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Julius Marminge <julius0216@outlook.com>
…ingdotgg#5103) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Julius Marminge <julius0216@outlook.com>
…arance-features-63f7 sync: port upstream appearance fonts, sidebar pinning, scannable pairing QR, and update migrations (pingdotgg#5103–pingdotgg#5374)
Port the non-font hunks from upstream pingdotgg#5384. The FontFamilyPicker, SettingsFontPreviews, and SettingsPanels hunks remain omitted because configurable fonts pingdotgg#5103 was intentionally rejected. Partial upstream commit: 41ebf22
…ffect beta.103 67 upstream commits (through 6b73b3d): paginated thread loading with user-anchored turn windows (pingdotgg#5493), contract-backed fonts (pingdotgg#5103), subagent/workflow observability agents panel (pingdotgg#5219), sidebar-v2 thread pinning (pingdotgg#5312, migrations 036/037), scannable pairing QR (pingdotgg#5360), MCP tool-result trimming (pingdotgg#5482), renderer OOM containment (pingdotgg#5148), tunnel survives updates/stops, terminal polish batch, forward-compat ServerProviders decode (pingdotgg#5327), Effect beta.103, many fixes. Forma preserved: composer surface/footer, ComposerMetaBar, diff panel skin, RightPanelTabs Forma strip/icons with BOTH componentPreview and agents surfaces, sidebar tone map, forma:// CORS origins, ~/.forma, fork migrations 935-941 after upstream 036/037, fork contract fields alongside fonts/threadPinning. Fonts unification starts (terminal now settings-driven); fix-forward follows. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Fix-forward: - ChatView: dedupe RightPanelTabs import, onAddAgents wired at all three surface mounts alongside onAddComponentPreview - Sidebar.logic: Monitoring tone/pill entries; stale colorClass returns converted to toneClass/glyph shape - SidebarV2 duplicate destructure; DiffPanel Button/RefreshCwIcon imports; ConnectionsSettings TriangleAlertIcon; SettingsFontPreviews codeContexts - ClaudeAdapter: drop fork-era is_error early return so aborted_tools maps to interrupted (pingdotgg#5557 behavior + test) - fork thread.forked projection upsert gains pinnedAt Fonts unification (pingdotgg#5103 engine, Forma skin): - Interface panel Typography now reads/writes settings (fontSizeInterface, fontSizeCode, fontSmoothing) — synced across devices; link row to the full font-family pickers - Forma css utilities bridged to the engine: --app-code-font-size* derive from --font-size-code preserving the 12/11/13 default scale - terminal's old localStorage sizing removed (settings-driven via merge) - one-time migration of forma:interface-appearance sizes into settings, default-guarded so other-device choices are never clobbered typecheck exit 0; server 1966 passed; web suites green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
## What's Changed * fix(mobile): reduce thread feed scroll jank by @gabrielelpidio in pingdotgg/t3code#4874 * fix(web): restore sidebar v2 thread actions and terminal icon by @Noojuno in pingdotgg/t3code#4712 * fix(web): settle button now works on hover, not just right-click by @t3dotgg in pingdotgg/t3code#4905 * fix(clients): disable add project while disconnected by @StiensWout in pingdotgg/t3code#4834 * fix(composer): hide default Codex service tier by @maxktz in pingdotgg/t3code#4784 * docs: link iOS and Android app store downloads by @t3dotgg in pingdotgg/t3code#4902 * fix(web): align remote server update action by @StiensWout in pingdotgg/t3code#4731 * fix(connect): suggest a serve command that matches how you ran connect by @t3dotgg in pingdotgg/t3code#4897 * fix(mobile): stop shared content errors in Personal Team builds by @t3dotgg in pingdotgg/t3code#4943 * perf(mobile): sends respond instantly, thread opens stop freezing by @t3dotgg in pingdotgg/t3code#4882 * fix(web): show Codex fast mode as a bolt by @t3dotgg in pingdotgg/t3code#4947 * docs: seed worktrees with a copy of real userdata instead of banning it by @t3dotgg in pingdotgg/t3code#4949 * fix(mobile): support dragged images in the composer by @t3dotgg in pingdotgg/t3code#4953 * fix(mobile): stop long iOS threads from jumping while scrolling up by @t3dotgg in pingdotgg/t3code#4867 * fix(web): keep worktree default when switching a draft's machine by @t3dotgg in pingdotgg/t3code#4964 * perf(mobile): reconnect environments immediately on resume by @t3dotgg in pingdotgg/t3code#4878 * feat(web): pasting a huge screenshot now compresses it instead of erroring by @t3dotgg in pingdotgg/t3code#4967 * feat(web): regenerate thread titles from sidebar by @t3dotgg in pingdotgg/t3code#4810 * fix(web): show server update progress through reconnect by @t3dotgg in pingdotgg/t3code#4903 * feat(search): find threads by conversation content by @t3dotgg in pingdotgg/t3code#4959 * fix: marketing site Vercel builds no longer die after ~100 deploys by @t3dotgg in pingdotgg/t3code#4975 * docs: split user and maintainer docs, fix 100+ stale claims by @t3dotgg in pingdotgg/t3code#4807 * fix(web): server updates no longer look like warnings by @t3dotgg in pingdotgg/t3code#4992 * fix(connect): reboots no longer strand the relay link, 403s now say why by @t3dotgg in pingdotgg/t3code#4988 * Add project file picker (⌘P) and project content search (⇧⌘F) by @jakeleventhal in pingdotgg/t3code#4855 * Check for mobile app updates on launch by @juliusmarminge in pingdotgg/t3code#4958 * fix(mobile): support pre-Liquid-Glass iOS bottom toolbar by @gabrielelpidio in pingdotgg/t3code#4984 * fix(server): restore PR detection without HOME by @StiensWout in pingdotgg/t3code#4985 * fix(web): fill fast mode icon by @maria-rcks in pingdotgg/t3code#5004 * fix: cache project favicons across web and mobile by @gabrielelpidio in pingdotgg/t3code#4767 * perf(ci): cut stale runs and redundant setup by @t3dotgg in pingdotgg/t3code#4802 * style(web): make scroll-to-end pill translucent by @maria-rcks in pingdotgg/t3code#5036 * fix(desktop): bump Clerk Electron SDK to 0.0.24 and register t3code:// scheme on Linux by @juliusmarminge in pingdotgg/t3code#5015 * perf(server): cache default branch name and origin existence across status refreshes by @UtkarshUsername in pingdotgg/t3code#5008 * feat(shared): support shorthand (major-only) versions in the semver helpers by @arhxam in pingdotgg/t3code#5027 * fix(mobile): remove unnecessary photo library permission by @skjiisa in pingdotgg/t3code#4929 * fix(shared): lenient JSON parser deletes commas inside string values by @arhxam in pingdotgg/t3code#5025 * fix(mobile): default bare IP pairing to HTTP by @Lucenx9 in pingdotgg/t3code#4990 * fix(mobile): restore iOS Threads branding by @PixPMusic in pingdotgg/t3code#4862 * chore: add mobile issue template area by @MaxAnderson95 in pingdotgg/t3code#4895 * fix(desktop): link release notes from the update downloaded toast by @Sy-D in pingdotgg/t3code#4771 * fix(mobile): accept Android clipboard images in composer by @adityavardhansharma in pingdotgg/t3code#4836 * fix(mobile): show the correct build channel in Android's Threads page header by @PixPMusic in pingdotgg/t3code#4861 * fix(contracts): decode growing config unions forward-compatibly by @juliusmarminge in pingdotgg/t3code#5055 * fix(mobile): server model, worktree, and origin preferences now apply to new tasks by @t3dotgg in pingdotgg/t3code#5064 * fix(ci): repair the mobile showcase screenshots workflow by @juliusmarminge in pingdotgg/t3code#5057 * fix(ci): capture iPad App Store screenshots in landscape by @PixPMusic in pingdotgg/t3code#5065 * fix(oxlint-plugin): Resolve the oxlint bin without assuming a pnpm layout by @mwolson in pingdotgg/t3code#5066 * feat(cli): `npx t3 pair` - generate QR code from a running server by @t3dotgg in pingdotgg/t3code#4955 * fix(server): self-update no longer rolls itself back on restart by @t3dotgg in pingdotgg/t3code#5095 * fix(ci): rotate iPad showcase captures without Simulator UI scripting by @juliusmarminge in pingdotgg/t3code#5094 * feat(web): render terminals with libghostty-vt by @StiensWout in pingdotgg/t3code#4860 * refactor: move the canonical libghostty-vt vendor to the repository root by @StiensWout in pingdotgg/t3code#5102 * feat(mobile): add thread snoozing by @gabrielelpidio in pingdotgg/t3code#5053 * feat(mobile): make settled threads collapsible by @PixPMusic in pingdotgg/t3code#5056 * follow-up normalization after #4700. by @shivamhwp in pingdotgg/t3code#4498 * feat(web): search threads from the sidebar by @shivamhwp in pingdotgg/t3code#4769 * feat(web): add settings sidebar search by @shivamhwp in pingdotgg/t3code#4682 * fix: threads with open PRs no longer auto-settle by @t3dotgg in pingdotgg/t3code#5151 * fix(server): bound thread catch-up replay and stop full-DB snapshot hydration by @t3dotgg in pingdotgg/t3code#5147 * fix(server): follow branch drift in dedicated worktrees so PRs link to their thread by @t3dotgg in pingdotgg/t3code#5159 * fix(server): make remote updates rollback-safe by @t3dotgg in pingdotgg/t3code#5181 * fix(web): stop settle controls overlapping the status label by @ipanasenko in pingdotgg/t3code#4574 * fix: normalize app icon glyph sizing by @t3-code[bot] in pingdotgg/t3code#5202 * fix(server): surface cloudflared FTL/PNC relay logs as warnings, not debug by @arhxam in pingdotgg/t3code#5076 * fix(server): stop npx service updates from silently leaving the old server running by @t3dotgg in pingdotgg/t3code#5217 * feat: fold legacy models into separate menus by @t3dotgg in pingdotgg/t3code#5190 * fix(desktop): claim the t3code:// scheme default on Linux at startup by @juliusmarminge in pingdotgg/t3code#5054 * fix(web): polish interface spacing by @maria-rcks in pingdotgg/t3code#5252 * fix(desktop): Niri/Hyprland - Linux secret storage backend by @mwolson in pingdotgg/t3code#2916 * fix(web): match loading screen to dark theme by @t3-code[bot] in pingdotgg/t3code#5303 * fix(web): blink the terminal cursor again by @StiensWout in pingdotgg/t3code#5314 * fix(terminal): protect held Ctrl/Cmd+W close shortcut by @StiensWout in pingdotgg/t3code#5322 * fix(server): strip replayable terminal queries from history by @StiensWout in pingdotgg/t3code#5319 * fix(contracts): decode ServerProviders forward-compatibly by @Brechard in pingdotgg/t3code#5327 * fix(web): simplify chat code blocks by @t3-code[bot] in pingdotgg/t3code#5301 * fix(web): align multiline error alert controls by @t3-code[bot] in pingdotgg/t3code#5304 * Upgrade Effect to beta.103 by @juliusmarminge in pingdotgg/t3code#5331 * fix(web): increase tooltip z-index to overlay popovers and menus by @naMqe-h in pingdotgg/t3code#5326 * fix(server): use a Cursor todo's title when its content is blank by @arhxam in pingdotgg/t3code#5073 * fix(ssh): isolate managed tunnel processes by @nateEc in pingdotgg/t3code#4347 * fix(server): scrub AppImage XDG_DATA_DIRS and GSETTINGS_SCHEMA_DIR from terminals by @arhxam in pingdotgg/t3code#5075 * fix(mobile): show correct provider icons for Grok, Cursor, and OpenCode by @Wraient in pingdotgg/t3code#4586 * fix(web): stop the chat timeline reading through the provider status banner by @Bil0000 in pingdotgg/t3code#5353 * fix(desktop,web): contain renderer memory growth and recover from renderer OOM crashes by @t3dotgg in pingdotgg/t3code#5148 * fix(server): generate durable thread titles by @t3dotgg in pingdotgg/t3code#5357 * fix(web): better right panel (new diffs styling) by @maria-rcks in pingdotgg/t3code#5260 * fix(server): keep regenerated titles on topic by @t3dotgg in pingdotgg/t3code#5365 * refactor(server): make title prompts plaintext by @t3dotgg in pingdotgg/t3code#5368 * feat(web): configurable fonts and sizes under Settings → Appearance by @StiensWout in pingdotgg/t3code#5103 * feat(sidebar-v2): bring back thread pinning by @t3dotgg in pingdotgg/t3code#5312 * feat(web): make pairing QR codes actually scannable, with endpoint choice by @t3dotgg in pingdotgg/t3code#5360 * fix(desktop,web): improve in-app browser shortcuts and URL behavior by @t3dotgg in pingdotgg/t3code#4703 * fix(web): prevent legacy model picker layout shift by @FllipEis in pingdotgg/t3code#5349 * fix(server): allow remote updates with database migrations by @t3dotgg in pingdotgg/t3code#5374 * fix(mcp): unblock Kimi models in OpenCode with preview tools by @hwanseoc in pingdotgg/t3code#5128 * fix(web): clear main branch lint warnings by @t3dotgg in pingdotgg/t3code#5384 * fix(mobile): preserve grouped project workspaces by @shivamhwp in pingdotgg/t3code#4642 * fix(mobile): prevent Android thread search crash by @shivamhwp in pingdotgg/t3code#5386 * fix(web): truncate long project switcher names by @FllipEis in pingdotgg/t3code#5348 * fix(mobile): avoid double dividers between thread sections by @shivamhwp in pingdotgg/t3code#5391 * fix(web): keep the composer command menu anchored to the composer by @StiensWout in pingdotgg/t3code#5336 * fix(web): restore terminal link hover styles by @StiensWout in pingdotgg/t3code#5382 * fix(ci): isolate releases from shared API rate limits by @t3dotgg in pingdotgg/t3code#5394 * fix(web): keep model picker shortcuts in sync by @t3dotgg in pingdotgg/t3code#5400 * fix(web): keep terminal font settings reliable by @StiensWout in pingdotgg/t3code#5397 * Enrich terminal font previews by @juliusmarminge in pingdotgg/t3code#5428 * fix(web): preserve terminal font size when splitting by @t3-code[bot] in pingdotgg/t3code#5444 * Prevent terminal loading flash by @juliusmarminge in pingdotgg/t3code#5432 * fix: reconnect faster after remote server updates by @t3dotgg in pingdotgg/t3code#5404 * feat: native subagent & workflow observability by @t3dotgg in pingdotgg/t3code#5219 * perf(server): stop shipping full MCP tool results in thread payloads by @t3dotgg in pingdotgg/t3code#5482 * fix(web): closed plan sidebar stays closed when returning to a thread by @t3dotgg in pingdotgg/t3code#5484 * fix: respect time format for sidebar snooze by @huxcrux in pingdotgg/t3code#4438 * fix: smooth remote server updates by @t3dotgg in pingdotgg/t3code#5470 * fix(server): drop superseded tool updates from snapshots by @t3dotgg in pingdotgg/t3code#5483 * fix(web): clarify auto permission fallback by @t3-code[bot] in pingdotgg/t3code#5431 * fix(acp): keep unknown approvals actionable by @t3-code[bot] in pingdotgg/t3code#5430 * fix(mobile): stop thread messages reading through pending cards by @carlosricojr in pingdotgg/t3code#5450 * fix(web): align composer inline chips with prompt text by @StiensWout in pingdotgg/t3code#5495 * fix(web): clear woke state on explicit thread actions by @StiensWout in pingdotgg/t3code#5486 * fix(server): skip origin fetch when creating worktrees in repos without an origin remote by @t3dotgg in pingdotgg/t3code#5556 * fix(web): update tooltip no longer dismisses when scrolling release notes by @t3dotgg in pingdotgg/t3code#5547 * fix(server): stop showing commit/push/PR notices as errors in the work log by @t3dotgg in pingdotgg/t3code#5559 * fix(web): show remote environment for non-Git projects by @t3dotgg in pingdotgg/t3code#5555 * fix(server): stopping a Claude thread no longer shows an ede_diagnostic error by @t3dotgg in pingdotgg/t3code#5557 * fix(web): show one toast when snoozing threads in bulk by @t3dotgg in pingdotgg/t3code#5560 * fix(server): let stopped threads settle immediately by @t3dotgg in pingdotgg/t3code#5553 * feat: paginate thread loading with user-anchored turn windows by @t3dotgg in pingdotgg/t3code#5493 * fix: prevent reconnect loops during server stalls by @gfsaaser24 in pingdotgg/t3code#5561 * fix(server): settle stopped Claude subagents by @t3dotgg in pingdotgg/t3code#5568 * fix: scrolling up during a running thread no longer snaps back to the bottom by @t3dotgg in pingdotgg/t3code#5566 * fix(server): one disconnecting client no longer blocks every reconnect by @t3dotgg in pingdotgg/t3code#5572 * test(server): catch client transfer regressions in CI by @t3dotgg in pingdotgg/t3code#5350 * fix(web): stop the "requests are slow" warning from firing on every provider update by @t3dotgg in pingdotgg/t3code#5570 * fix(web): keep agent panel rows stable by @t3dotgg in pingdotgg/t3code#5569 * docs: ship production T3 Connect public config in .env.example by @t3dotgg in pingdotgg/t3code#5573 * fix(web): plans stop hijacking the UI, fold into chat instead by @t3dotgg in pingdotgg/t3code#5558 * feat(web): remove Build/Plan toggle from the composer by @t3dotgg in pingdotgg/t3code#5551 * feat(web): per-device provider settings by @t3dotgg in pingdotgg/t3code#4479 * fix(mobile): invisible T3 Connect devices can now be seen and removed by @t3dotgg in pingdotgg/t3code#5563 * fix: add missing space before 'GitHub releases page' link on download page by @Mateleo in pingdotgg/t3code#4511 * fix(web): stop the sidebar "Working" label from pulsing by @t3dotgg in pingdotgg/t3code#5580 * feat(web): add modular theme library by @StiensWout in pingdotgg/t3code#5226 * fix(web): reading a thread clears Done; Woke is dismissible by @t3dotgg in pingdotgg/t3code#5579 * perf(dev): faster cold-start for dev web serving by @t3dotgg in pingdotgg/t3code#5584 * fix(dev): agents get --share right on the first try by @t3dotgg in pingdotgg/t3code#5586 * fix(mobile): improve keyboard avoiding by @jmeistrich in pingdotgg/t3code#5451 * fix(web): live background-work banner no longer hides behind the update notice by @t3dotgg in pingdotgg/t3code#5595 * fix(web): stabilize chat timeline positioning by @jmeistrich in pingdotgg/t3code#5449 * feat(server): record runtime mode per turn and on mode changes by @t3dotgg in pingdotgg/t3code#5593 * feat(web): thread actions from the chat header title by @t3dotgg in pingdotgg/t3code#5592 * fix(mobile): avoid iOS terminal reset on clear by @justynleung in pingdotgg/t3code#5440 * fix(mobile): pad scroll views above Android nav bar by @StoneCotton in pingdotgg/t3code#5415 * fix(mobile): keep Android chat text from showing through the composer by @PollyGlot in pingdotgg/t3code#5582 * fix(mobile): repair Clerk auth navigation headers by @gabrielelpidio in pingdotgg/t3code#5140 * Bump mobile app version to 1.0.2 by @juliusmarminge in pingdotgg/t3code#5588 * feat(web): click the pin icon to unpin a thread by @UtkarshUsername in pingdotgg/t3code#5578 * fix(web): show the correctly matching shortcut in new thread button's tooltip by @UtkarshUsername in pingdotgg/t3code#5594 ## New Contributors * @gabrielelpidio made their first contribution in pingdotgg/t3code#4874 * @arhxam made their first contribution in pingdotgg/t3code#5027 * @skjiisa made their first contribution in pingdotgg/t3code#4929 * @Lucenx9 made their first contribution in pingdotgg/t3code#4990 * @MaxAnderson95 made their first contribution in pingdotgg/t3code#4895 * @t3-code[bot] made their first contribution in pingdotgg/t3code#5202 * @Brechard made their first contribution in pingdotgg/t3code#5327 * @naMqe-h made their first contribution in pingdotgg/t3code#5326 * @Bil0000 made their first contribution in pingdotgg/t3code#5353 * @gfsaaser24 made their first contribution in pingdotgg/t3code#5561 * @Mateleo made their first contribution in pingdotgg/t3code#4511 * @jmeistrich made their first contribution in pingdotgg/t3code#5451 * @justynleung made their first contribution in pingdotgg/t3code#5440 * @StoneCotton made their first contribution in pingdotgg/t3code#5415 * @PollyGlot made their first contribution in pingdotgg/t3code#5582 **Full Changelog**: pingdotgg/t3code@v0.0.31...v0.0.32 Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.32
* feat(web): add collapse-all toggle to diff panel (pingdotgg#4475) * feat(web): show fast mode as a bolt instead of a "Normal" label (pingdotgg#4488) Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> * feat(dev): keep worktree dev state isolated on T3 Code dev servers (pingdotgg#4555) Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> * feat(dev): Make t3 code dev instances shareable over Tailscale (pingdotgg#4556) Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(dev): skip browser-blocked ports (pingdotgg#4608) * fix: cut websocket throughput in half by pruning activity payloads (pingdotgg#4622) * perf(mobile): defer work-log detail serialization (pingdotgg#4607) * test: account for lazy thread feed details (pingdotgg#4628) * feat(relay): limit managed tunnels per user (pingdotgg#4530) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * Add managed tunnel limits migration (pingdotgg#4635) * Add background preview capture and picture-in-picture support (pingdotgg#4397) Co-authored-by: codex <codex@users.noreply.github.com> * feat(web): prompt stash — cmd+S saves the composer to a per-provider queue (pingdotgg#4453) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * Upgrade Effect and Alchemy betas (pingdotgg#4643) Prepare Relay production infrastructure for the PlanetScale PS_20 HA topology, upgrade Effect and Alchemy to compatible betas, reconcile migration state, and preserve patched MCP session termination behavior.\n\nCo-authored-by: codex <codex@users.noreply.github.com> * feat: allow new thread creation through project breadcrumbs (pingdotgg#4638) * fix(web): scope PR state to the thread branch (pingdotgg#4460) Co-authored-by: codex <codex@users.noreply.github.com> * Drop redundant Relay user indexes (pingdotgg#4648) Co-authored-by: codex <codex@users.noreply.github.com> * feat(connect): release the Cloudflare tunnel when the environment shuts down (pingdotgg#4531) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * Fix Relay Worker RuntimeContext wiring (pingdotgg#4653) Co-authored-by: codex <codex@users.noreply.github.com> * Fix live sidebar resize limits and defer Alchemy runtime context (pingdotgg#4655) * fix(web): constrain branch toolbar context (pingdotgg#4657) * Keep MCP credentials alive across provider turns (pingdotgg#4659) * fix: close actions dropdown when editing (pingdotgg#4660) * fix(preview): stabilize PiP viewport identity (pingdotgg#4661) Co-authored-by: codex <codex@users.noreply.github.com> * Add glass styling for thread tooltips and simplify preview tab handling (pingdotgg#4665) * Use tarball archiving for hosted web deploys (pingdotgg#4669) * fix(server): bound editor discovery during config loading (pingdotgg#4291) * Prevent draft thread detail polling before shell registration (pingdotgg#4670) Co-authored-by: codex <codex@users.noreply.github.com> * feat: add configurable source control writing settings (pingdotgg#4204) Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Julius Marminge <julius0216@outlook.com> Co-authored-by: codex <codex@users.noreply.github.com> * feat(diff-panel): show total line additions and deletions (pingdotgg#4674) * Clear provider update actions while updating (pingdotgg#4676) * Fix sidebar highlighting for draft threads (pingdotgg#4679) * Use glass surfaces for web toasts (pingdotgg#4681) * Show origin ref in branch trigger label (pingdotgg#4680) Co-authored-by: codex <codex@users.noreply.github.com> * fix(mobile): match react version to react-native 0.85.3 vendored renderer (19.2.3) (pingdotgg#4675) * chore(release): prepare v0.0.29 * Add OTA update checks to mobile settings (pingdotgg#4686) * fix(mobile): threads load snapped to bottom on iOS (pingdotgg#4689) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * feat: default sidebar v2 on for nightly and dev builds (pingdotgg#4491) Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(web): 33 web UI fixes (pingdotgg#4700) * Make mobile Thread List v2 the default (pingdotgg#4717) * Fix mobile showcase workflow without Clerk (pingdotgg#4718) * Fix relay credential lookup for unlinked environments (pingdotgg#4692) Co-authored-by: codex <codex@users.noreply.github.com> * Settle merged PR threads immediately (pingdotgg#4704) * feat(web): add maria's sidebar header artwork toggle (pingdotgg#4652) * feat(web): add appearance settings category (pingdotgg#4715) * fix(desktop): allow updater-controlled relaunch (pingdotgg#4721) * fix(web): prevent diff panel scroll jumping (pingdotgg#4724) * Link inline code file paths in chat markdown (pingdotgg#4726) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * Fix Android showcase capture and rebuild v2 queued rows (pingdotgg#4730) Co-authored-by: Claude <noreply@anthropic.com> * perf(server): negotiate permessage-deflate on the websocket (pingdotgg#4705) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * docs: overhaul agent guidance (pingdotgg#4782) * Prevent sidebar row labels from truncating (pingdotgg#4789) * perf(server): gzip large thread snapshots (pingdotgg#4788) * fix(web): stashed prompts now survive switching providers (pingdotgg#4787) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * Fix Git ref refresh resource storms (pingdotgg#4727) Co-authored-by: codex <codex@users.noreply.github.com> * perf(server): trim stale context-window rows and drop dead replay RPC (pingdotgg#4791) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * fix(web): defer command palette filesystem navigation (pingdotgg#2109) Co-authored-by: codex <codex@users.noreply.github.com> * fix(release): skip scripts during Vercel installs (pingdotgg#4796) * refactor(client): share filesystem browse navigation (pingdotgg#4797) Co-authored-by: codex <codex@users.noreply.github.com> * fix(mobile): defer filesystem navigation (pingdotgg#4799) Co-authored-by: codex <codex@users.noreply.github.com> * refactor(server): use native HTTP compression streams (pingdotgg#4798) Co-authored-by: codex <codex@users.noreply.github.com> * Remove Connect waitlist and add GA announcement tooling (pingdotgg#4691) * Fix Connect sign-in settings label (pingdotgg#4806) * chore(release): prepare v0.0.30 * fix(desktop): restore T3 Connect sign-in (pingdotgg#4809) Co-authored-by: Julius Marminge <julius0216@outlook.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * Simplify files panel header (pingdotgg#4828) * build(desktop): reduce installed app size by ~300MB (pingdotgg#4824) * Update model version from claude-opus-4-8 to claude-opus-5 (pingdotgg#4832) * Preserve the thread shell while detail loads (pingdotgg#4830) * Reduce idle work and disk churn with native resource diagnostics (pingdotgg#2679) Co-authored-by: codex <codex@users.noreply.github.com> * fix(server): detect repositories after initialization (pingdotgg#4848) * perf(server): merge separate staged/unstaged numstat calls into single diff HEAD --numstat (pingdotgg#4843) * fix(git): disable external diff for review diff previews (pingdotgg#4854) * Fix editable file focus and live syntax highlighting (pingdotgg#3979) * fix(web): remember the rendered-markdown choice across threads (pingdotgg#4853) Co-authored-by: Simon Doba <simon.doba@orbit.de> Co-authored-by: Claude Opus 5 <noreply@anthropic.com> * chore(release): prepare v0.0.31 * fix(mobile): reduce thread feed scroll jank (pingdotgg#4874) * fix(web): restore sidebar v2 thread actions and terminal icon (pingdotgg#4712) * fix(web): settle button now works on hover, not just right-click (pingdotgg#4905) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * fix(clients): disable add project while disconnected (pingdotgg#4834) * fix(composer): hide default Codex service tier (pingdotgg#4784) * docs: link iOS and Android app store downloads (pingdotgg#4902) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * fix(web): align remote server update action (pingdotgg#4731) * fix(connect): suggest a serve command that matches how you ran connect (pingdotgg#4897) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * fix(mobile): stop shared content errors in Personal Team builds (pingdotgg#4943) * perf(mobile): sends respond instantly, thread opens stop freezing (pingdotgg#4882) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * fix(web): show Codex fast mode as a bolt (pingdotgg#4947) * docs: seed worktrees with a copy of real userdata instead of banning it (pingdotgg#4949) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * fix(mobile): support dragged images in the composer (pingdotgg#4953) * fix(mobile): stop long iOS threads from jumping while scrolling up (pingdotgg#4867) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * fix(web): keep worktree default when switching a draft's machine (pingdotgg#4964) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * perf(mobile): reconnect environments immediately on resume (pingdotgg#4878) * feat(web): pasting a huge screenshot now compresses it instead of erroring (pingdotgg#4967) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * feat(web): regenerate thread titles from sidebar (pingdotgg#4810) * fix(web): show server update progress through reconnect (pingdotgg#4903) * feat(search): find threads by conversation content (pingdotgg#4959) * fix: marketing site Vercel builds no longer die after ~100 deploys (pingdotgg#4975) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * docs: split user and maintainer docs, fix 100+ stale claims (pingdotgg#4807) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * fix(web): server updates no longer look like warnings (pingdotgg#4992) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * fix(connect): reboots no longer strand the relay link, 403s now say why (pingdotgg#4988) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * Add project file picker (⌘P) and project content search (⇧⌘F) (pingdotgg#4855) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Julius Marminge <julius0216@outlook.com> * Check for mobile app updates on launch (pingdotgg#4958) Co-authored-by: codex <codex@users.noreply.github.com> * fix(mobile): support pre-Liquid-Glass iOS bottom toolbar (pingdotgg#4984) * fix(server): restore PR detection without HOME (pingdotgg#4985) * fix(web): fill fast mode icon (pingdotgg#5004) * fix: cache project favicons across web and mobile (pingdotgg#4767) * perf(ci): cut stale runs and redundant setup (pingdotgg#4802) * chore(mobile): bump app version to 1.0.1 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * style(web): make scroll-to-end pill translucent (pingdotgg#5036) * fix(ci): drop sparse-checkout from EAS workflows actions/checkout implements sparse-checkout with --filter=blob:none, so the runner repo is a partial clone missing the .repos/ blobs. eas-cli archives the project via `git clone --depth 1 file://<workspace>`, which upload-pack cannot serve from a partial clone and exits 128 (pingdotgg#4802 broke both EAS build workflows this way). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(desktop): bump Clerk Electron SDK to 0.0.24 and register t3code:// scheme on Linux (pingdotgg#5015) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * perf(server): cache default branch name and origin existence across status refreshes (pingdotgg#5008) * feat(shared): support shorthand (major-only) versions in the semver helpers (pingdotgg#5027) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(mobile): remove unnecessary photo library permission (pingdotgg#4929) * fix(shared): lenient JSON parser deletes commas inside string values (pingdotgg#5025) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(mobile): default bare IP pairing to HTTP (pingdotgg#4990) * fix(mobile): restore iOS Threads branding (pingdotgg#4862) * chore: add mobile issue template area (pingdotgg#4895) * fix(desktop): link release notes from the update downloaded toast (pingdotgg#4771) Co-authored-by: Claude Opus 5 <noreply@anthropic.com> * fix(mobile): accept Android clipboard images in composer (pingdotgg#4836) * fix(mobile): show the correct build channel in Android's Threads page header (pingdotgg#4861) * fix(contracts): decode growing config unions forward-compatibly (pingdotgg#5055) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * fix(mobile): server model, worktree, and origin preferences now apply to new tasks (pingdotgg#5064) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * fix(ci): repair the mobile showcase screenshots workflow (pingdotgg#5057) * fix(ci): capture iPad App Store screenshots in landscape (pingdotgg#5065) * fix(oxlint-plugin): Resolve the oxlint bin without assuming a pnpm layout (pingdotgg#5066) * feat(cli): `npx t3 pair` - generate QR code from a running server (pingdotgg#4955) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * fix(server): self-update no longer rolls itself back on restart (pingdotgg#5095) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * fix(ci): rotate iPad showcase captures without Simulator UI scripting (pingdotgg#5094) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * feat(web): render terminals with libghostty-vt (pingdotgg#4860) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * refactor: move the canonical libghostty-vt vendor to the repository root (pingdotgg#5102) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * feat(mobile): add thread snoozing (pingdotgg#5053) * feat(mobile): make settled threads collapsible (pingdotgg#5056) * follow-up normalization after pingdotgg#4700. (pingdotgg#4498) Co-authored-by: T3 Code Test <t3code-test@example.com> * feat(web): search threads from the sidebar (pingdotgg#4769) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * feat(web): add settings sidebar search (pingdotgg#4682) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * fix: threads with open PRs no longer auto-settle (pingdotgg#5151) * fix(server): bound thread catch-up replay and stop full-DB snapshot hydration (pingdotgg#5147) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * fix(server): follow branch drift in dedicated worktrees so PRs link to their thread (pingdotgg#5159) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * fix(server): make remote updates rollback-safe (pingdotgg#5181) * fix(web): stop settle controls overlapping the status label (pingdotgg#4574) * fix: normalize app icon glyph sizing (pingdotgg#5202) Co-authored-by: t3-code[bot] <269035359+t3-code[bot]@users.noreply.github.com> * fix(server): surface cloudflared FTL/PNC relay logs as warnings, not debug (pingdotgg#5076) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(server): stop npx service updates from silently leaving the old server running (pingdotgg#5217) Co-authored-by: Claude <noreply@anthropic.com> * feat: fold legacy models into separate menus (pingdotgg#5190) * fix(desktop): claim the t3code:// scheme default on Linux at startup (pingdotgg#5054) * fix(web): polish interface spacing (pingdotgg#5252) * fix(desktop): Niri/Hyprland - Linux secret storage backend (pingdotgg#2916) Co-authored-by: Julius Marminge <julius0216@outlook.com> * fix(web): match loading screen to dark theme (pingdotgg#5303) * fix(web): blink the terminal cursor again (pingdotgg#5314) Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(terminal): protect held Ctrl/Cmd+W close shortcut (pingdotgg#5322) * fix(server): strip replayable terminal queries from history (pingdotgg#5319) * fix(contracts): decode ServerProviders forward-compatibly (pingdotgg#5327) Co-authored-by: Rodrigo Brechard <rodrigo@clubtidy.fr> * fix(web): simplify chat code blocks (pingdotgg#5301) * fix(web): align multiline error alert controls (pingdotgg#5304) * Upgrade Effect to beta.103 (pingdotgg#5331) * fix(web): increase tooltip z-index to overlay popovers and menus (pingdotgg#5326) * fix(server): use a Cursor todo's title when its content is blank (pingdotgg#5073) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(ssh): isolate managed tunnel processes (pingdotgg#4347) * fix(server): scrub AppImage XDG_DATA_DIRS and GSETTINGS_SCHEMA_DIR from terminals (pingdotgg#5075) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(mobile): show correct provider icons for Grok, Cursor, and OpenCode (pingdotgg#4586) * fix(web): stop the chat timeline reading through the provider status banner (pingdotgg#5353) * fix(desktop,web): contain renderer memory growth and recover from renderer OOM crashes (pingdotgg#5148) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * fix(server): generate durable thread titles (pingdotgg#5357) * fix(web): better right panel (new diffs styling) (pingdotgg#5260) * fix(server): keep regenerated titles on topic (pingdotgg#5365) * refactor(server): make title prompts plaintext (pingdotgg#5368) * feat(web): configurable fonts and sizes under Settings → Appearance (pingdotgg#5103) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Julius Marminge <julius0216@outlook.com> * feat(sidebar-v2): thread pinning for sidebar v2 (pingdotgg#5312) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * feat(web): make pairing QR codes actually scannable, with endpoint choice (pingdotgg#5360) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * fix(desktop,web): improve in-app browser shortcuts and URL behavior (pingdotgg#4703) * fix(web): prevent legacy model picker layout shift (pingdotgg#5349) * fix(server): allow remote updates with database migrations (pingdotgg#5374) * fix(mcp): unblock Kimi models in OpenCode with preview tools (pingdotgg#5128) * fix(web): clear main branch lint warnings (pingdotgg#5384) * fix(mobile): preserve grouped project workspaces (pingdotgg#4642) Co-authored-by: T3 Code Test <t3code-test@example.com> * fix(mobile): prevent Android thread search crash (pingdotgg#5386) * fix(web): truncate long project switcher names (pingdotgg#5348) * fix(mobile): avoid double dividers between thread sections (pingdotgg#5391) Co-authored-by: T3 Code Test <t3code-test@example.com> * fix(web): keep the composer command menu anchored to the composer (pingdotgg#5336) * fix(web): restore terminal link hover styles (pingdotgg#5382) * fix(ci): isolate releases from shared API rate limits (pingdotgg#5394) * fix(web): keep model picker shortcuts in sync (pingdotgg#5400) * fix(web): keep terminal font settings reliable (pingdotgg#5397) * Enrich terminal font previews (pingdotgg#5428) * fix(web): preserve terminal font size when splitting (pingdotgg#5444) Co-authored-by: t3-code[bot] <269035359+t3-code[bot]@users.noreply.github.com> * Prevent terminal loading flash (pingdotgg#5432) * fix: reconnect faster after remote server updates (pingdotgg#5404) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * feat: native subagent & workflow observability (pingdotgg#5219) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * perf(server): stop shipping full MCP tool results in thread payloads (pingdotgg#5482) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * fix(web): closed plan sidebar stays closed when returning to a thread (pingdotgg#5484) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * fix: respect time format for sidebar snooze (pingdotgg#4438) * fix(web): calm one-row server update status and banner The version-skew banner is no longer an amber warning: it reads "Server update available" with the raw versions (unreadable for nightlies) moved to a tooltip. The in-flight rail (Download/Install/ Resume) becomes a single status row, "Downloading…" then "Restarting…", since the wire installing stage is a sub-second launcher handoff and "resuming" meant nothing to most people. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(server): keep the managed tunnel across remote update restarts Measured on a live update: the server was back in ~9s but stayed unreachable for ~96s, because releasing the tunnel on shutdown forces the replacement tunnel's hostname route through 1-2 minutes of edge propagation. An update handoff always brings a server right back (new version or rollback), so the tunnel is never orphaned; skip the release when the launcher state file records a pending update. The next boot respawns the connector from the stored config against the same tunnel and is reachable as soon as it connects. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(server): use the launcher state writer in release tests Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(server): release the tunnel when an explicit stop interrupts an update A pending update in the launcher state is not proof a replacement server is coming: `t3 service uninstall` or `systemctl stop` during the pending window also tears the server down, permanently. The launcher now writes a stop marker before signalling its child on an explicit stop and clears it on the next start; the shutdown tunnel release keeps the tunnel only for pending updates without the marker. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(server): clean up interrupted update trials * fix(server): order explicit service shutdown * fix(web): make update version tooltips accessible * fix(server): separate trial cleanup from handoff retention * fix(server): drop superseded tool updates from snapshots A tool.updated row is the in-flight snapshot of a call; once the call completes, the tool.completed row carries the final state and both clients fold every matching update into it. Shipping the updates buys nothing: 47k such rows exist in one real database, and a single thread carries 3,291 of them. Filter them out of thread snapshots, mirroring the existing context-window dedup. Matching is per turn and only against a LATER completion, so a revert that discards the completing turn cannot leave a call unrepresented, and a later update under the same identity (the next call, still in flight) survives. Live events are untouched. Rows are matched on the same identity the clients collapse by: an explicit data.toolCallId when the adapter emits one, otherwise the itemType/title/detail triple. No tool lifecycle row in the real db carries a toolCallId, so the fallback does the work. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(server): pin interleaved-collapse divergence as intentional with test Bugbot flagged that clients collapse only adjacent lifecycle rows, so dropping a superseded update separated by an interleaved parallel call diverges from full-history rendering. Measured on a real database: 1.5% of dropped rows (553/36,581), all pure in-flight state whose final result the retained completion still shows, and zero dropped rows carry a client-merged payload field their completion lacks (verified across all 49,515 update rows). Documents the tradeoff and adds a test pinning it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(web): clarify auto permission fallback (pingdotgg#5431) Co-authored-by: t3-code[bot] <269035359+t3-code[bot]@users.noreply.github.com> * fix(acp): keep unknown approvals actionable (pingdotgg#5430) Co-authored-by: t3-code[bot] <269035359+t3-code[bot]@users.noreply.github.com> * fix(mobile): stop thread messages reading through pending cards (pingdotgg#5450) Co-authored-by: Claude Opus 5 <noreply@anthropic.com> * fix(web): align composer inline chips with prompt text (pingdotgg#5495) * fix(web): clear woke state on explicit thread actions (pingdotgg#5486) * fix(server): skip origin fetch when creating worktrees in repos without an origin remote (pingdotgg#5556) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * fix(web): update tooltip no longer dismisses when scrolling release notes (pingdotgg#5547) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * fix(server): stop showing commit/push/PR notices as errors in the work log (pingdotgg#5559) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * fix(web): show remote environment for non-Git projects (pingdotgg#5555) * fix(server): stopping a Claude thread no longer shows an ede_diagnostic error (pingdotgg#5557) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * fix(web): show one toast when snoozing threads in bulk (pingdotgg#5560) * fix(server): let stopped threads settle immediately (pingdotgg#5553) * feat: paginate thread loading with user-anchored turn windows (pingdotgg#5493) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * fix: prevent reconnect loops during server stalls (pingdotgg#5561) Co-authored-by: t3-turbo-simulation <simulation@t3turbo.local> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Theo Browne <me@t3.gg> * fix(server): settle stopped Claude subagents (pingdotgg#5568) * fix: scrolling up during a running thread no longer snaps back to the bottom (pingdotgg#5566) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * fix(server): one disconnecting client no longer blocks every reconnect (pingdotgg#5572) Co-authored-by: Claude <noreply@anthropic.com> * test(server): catch client transfer regressions in CI (pingdotgg#5350) * fix(web): stop the "requests are slow" warning from firing on every provider update (pingdotgg#5570) Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(web): keep agent panel rows stable (pingdotgg#5569) * docs: ship production T3 Connect public config in .env.example (pingdotgg#5573) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * fix(web): plans stop hijacking the UI, fold into chat instead (pingdotgg#5558) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * feat(web): remove Build/Plan toggle from the composer (pingdotgg#5551) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * feat(web): per-device provider settings (pingdotgg#4479) Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(mobile): invisible T3 Connect devices can now be seen and removed (pingdotgg#5563) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * fix: add missing space before 'GitHub releases page' link on download page (pingdotgg#4511) * fix(web): stop the sidebar "Working" label from pulsing (pingdotgg#5580) Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> * feat(web): add modular theme library (pingdotgg#5226) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Julius Marminge <julius0216@outlook.com> Co-authored-by: maria-rcks <maria@kuuro.net> Co-authored-by: Julius Marminge <jmarminge@gmail.com> * fix(web): reading a thread clears Done; Woke is dismissible (pingdotgg#5579) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * perf(dev): faster cold-start for dev web serving (pingdotgg#5584) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * fix(dev): Improve instructions for --share (pingdotgg#5586) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * fix(mobile): improve keyboard avoiding (pingdotgg#5451) * fix(web): live background-work banner no longer hides behind the update notice (pingdotgg#5595) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * fix(web): stabilize chat timeline positioning (pingdotgg#5449) Co-authored-by: codex <codex@users.noreply.github.com> * feat(server): record runtime mode per turn and on mode changes (pingdotgg#5593) Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> * feat(web): thread actions from the chat header title (pingdotgg#5592) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * fix(mobile): avoid iOS terminal reset on clear (pingdotgg#5440) * fix(mobile): pad scroll views above Android nav bar (pingdotgg#5415) * fix(mobile): keep Android chat text from showing through the composer (pingdotgg#5582) * fix(mobile): repair Clerk auth navigation headers (pingdotgg#5140) Co-authored-by: codex <codex@users.noreply.github.com> * Bump mobile app version to 1.0.2 (pingdotgg#5588) * feat(web): click the pin icon to unpin a thread (pingdotgg#5578) * fix(web): show the correctly matching shortcut in new thread button's tooltip (pingdotgg#5594) * chore: advance public upstream baseline * chore: advance upstream baseline to v0.0.32 * fix: align react native patch lock hash --------- Co-authored-by: jan <hi@4bs3nt.com> Co-authored-by: Theo Browne <me@t3.gg> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Co-authored-by: Alex Southwell <saphid@gmail.com> Co-authored-by: Julius Marminge <julius0216@outlook.com> Co-authored-by: codex <codex@users.noreply.github.com> Co-authored-by: Max Katz <me@maxkatz.me> Co-authored-by: maria <maria@kuuro.net> Co-authored-by: Krzysztof Moch <krzysmoch.programs@gmail.com> Co-authored-by: t3-code[bot] <269035359+t3-code[bot]@users.noreply.github.com> Co-authored-by: Alex <me@pixp.cc> Co-authored-by: wukko <me@wukko.me> Co-authored-by: Wout Stiens <71498452+StiensWout@users.noreply.github.com> Co-authored-by: Utkarsh Patil <73941998+UtkarshUsername@users.noreply.github.com> Co-authored-by: ohbentos <72638975+ohbentos@users.noreply.github.com> Co-authored-by: Jake Leventhal <jakeleventhal@me.com> Co-authored-by: Simon Doba <simon.doba@hotmail.de> Co-authored-by: Simon Doba <simon.doba@orbit.de> Co-authored-by: Gabriel De Andrade <30420087+gabrielelpidio@users.noreply.github.com> Co-authored-by: Jono Kemball <Noojuno@users.noreply.github.com> Co-authored-by: Arham Amin <132888838+arhxam@users.noreply.github.com> Co-authored-by: Elaine Lyons <elaine@lyons.app> Co-authored-by: Simone <lucenz@proton.me> Co-authored-by: Max Anderson <max.a.anderson95@gmail.com> Co-authored-by: Aditya Vardhan Sharma <adityaradhika13@gmail.com> Co-authored-by: Mike Olson <mwolson@member.fsf.org> Co-authored-by: shivam <91240327+shivamhwp@users.noreply.github.com> Co-authored-by: T3 Code Test <t3code-test@example.com> Co-authored-by: Illia Panasenko <hello@ipanasenko.me> Co-authored-by: Rodrigo Brechard <rodrigobrechard@gmail.com> Co-authored-by: Rodrigo Brechard <rodrigo@clubtidy.fr> Co-authored-by: naMqe <naMqe07@gmail.com> Co-authored-by: Yukun Shan <92423096+nateEc@users.noreply.github.com> Co-authored-by: Rushikesh Gaikwad <81632222+Wraient@users.noreply.github.com> Co-authored-by: Bilal Bakr <62337003+Bil0000@users.noreply.github.com> Co-authored-by: Fllip <39161142+FllipEis@users.noreply.github.com> Co-authored-by: Hwanseo Choi <electricvoxel@gmail.com> Co-authored-by: Hugo Blom <6117705+huxcrux@users.noreply.github.com> Co-authored-by: Carlos Rico-Ospina <carlosricojr@gmail.com> Co-authored-by: Gabe Fletcher <gabe@editmypodcast.agency> Co-authored-by: t3-turbo-simulation <simulation@t3turbo.local> Co-authored-by: Mateleo <mateleo78@gmail.com> Co-authored-by: Julius Marminge <jmarminge@gmail.com> Co-authored-by: Jay Meistrich <github@jayz.us> Co-authored-by: Justyn Leung <justynleung2000@gmail.com> Co-authored-by: Tyler Saari <73684839+StoneCotton@users.noreply.github.com> Co-authored-by: Pavlo Trinko <paul.trinko95@gmail.com> Co-authored-by: atryan <atryan@users.noreply.github.com>


What changed
Settings → Appearance gains a Fonts section: four surfaces, each with a family picker and a size slider, a live preview rendered in the resolved family and size, and a per-row reset.
The family pickers are grouped by category (Sans serif / Monospace) and filtered to faces that are actually installed, probed with canvas metrics —
document.fonts.check()reportstruefor absent families, so it cannot filter anything. "Custom…" accepts any name: it edits a local draft that commits 400ms after typing pauses (or on Enter/blur) and only once the name resolves, so the applied font holds while a partial name is typed.Cell-grid surfaces stay monospace. The terminal draws on a fixed cell lattice, so a proportional face renders its text narrower than its own cells and strands the cursor to the right. The Code and Terminal pickers offer monospace faces only, and the renderer independently measures the requested family and falls back to the default when it is not monospace, so a previously stored value cannot leave the terminal in that state.
The terminal size adapts to its canvas. The preference is a ceiling: narrow panes (splits, the side panel) slide the rendered size down until a classic 80-column grid fits, down to an 8px legibility floor, and widening slides it back up. The measurement lives in
fit(), so drags, splits, and window resizes all pass through it.The composer context strip degrades instead of colliding. Its controls truncate, and once even truncated labels cannot fit they animate shut to icons (measured from laid-out content, with hysteresis, restoring as space returns).
Under the hood:
--font-sans/--font-monotheme tokens move out of@theme inlineso Tailwind utilities reference the variables;body,pre/code, and the@pierre/diffsshadow-root hooks route through themValidation
🤖 Generated with Claude Code
Note
Medium Risk
Interface font size drives root
remscaling app-wide, and typography touches terminal rendering and persisted client settings; previewlocal-fontsdenial is an intentional security guard.Overview
Adds Settings → Appearance → Typography so users can pick interface, prompt, code, and terminal font families and sizes (with optional Advanced per-surface overrides, macOS font smoothing, and live previews on real composer/diff/Ghostty surfaces).
Runtime wiring: new client settings flow through
FontAppearanceSyncinto CSS variables (--font-sans,--font-mono,--font-composer, size tokens); bundled DM Sans / JetBrains Mono are removed in favor of system stacks. Family pickers use the Local Font Access API where available, with canvas/DOM probing for installed and monospace faces.Terminal: Ghostty honors preferences, rejects proportional fonts, shrinks size to keep ~80 columns in narrow panes, and reapplies fonts after async hydration. Composer context strip collapses labels to icons when space is tight. Preview browser sessions deliberately omit
local-fontspermission so untrusted pages cannot fingerprint installed fonts.Reviewed by Cursor Bugbot for commit 284ea9f. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Add configurable font family and size controls to Settings → Appearance
FontFamilyPickercomponent that enumerates installed local fonts via the Local Font Access API with search and virtualized list rendering; falls back to a validated text input when the API is unavailable.--font-sans,--font-mono,--font-composer,--font-size-prompt,--font-size-code) applied todocument.documentElementat runtime via a newFontAppearanceSyncroot component..glass-opacity-sliderCSS class and--glass-slider-*custom properties are renamed to.settings-slider/--settings-slider-*; any external references will break.Macroscope summarized 284ea9f.
closes #4376