Features, with evidence.

69 features across 8 categories. Every entry links to the commits that shipped it.

69 features

Search every setting, ranked, and jump straight to it

Quick look

A search box at the top of the settings nav, on Ctrl+F, finds pages, section headings and individual settings by title and description. Exact matches beat prefixes, which beat word starts, which beat matches inside a word; a page beats a setting at the same kind of match, and loose letter-by-letter matches only appear when nothing else does. Matches are highlighted without moving any text, long descriptions are cut around the match with an ellipsis on each cut side, and Enter opens the page, the inner tab and the collapsed group the setting is in, then scrolls to it and flashes it. The index is read from each page as it renders, so a plugin's own settings page is searchable without the plugin doing anything. The hotkey list and each integration's detail view are not indexed.

UI & theming

Ctrl+V pastes an image into Claude Code

Quick look

A terminal can only paste text, so Claude Code pastes an image by reading the clipboard itself when it sees Ctrl+V. With Ctrl+V bound to paste, one keystroke sent two things, an empty paste and a raw Ctrl+V, and Claude Code's two clipboard reads raced each other for the Windows clipboard. Paste with an image and no text now sends one Ctrl+V and nothing else, and text paste is unchanged. It can be switched off. The double delivery behind it was general to every hotkey and is fixed for all of them; see the next entry.

Claude Code

A hotkey's key is sent once, not twice

Quick look

A key bound to a hotkey that the terminal could also type reached the session twice: once from the hotkey, once from the terminal. It happened from launch until the first ordinary keystroke, and after every multi-chord hotkey, so the first Ctrl+C in a freshly opened Claude Code session sent two interrupts, the second of which can exit it, and Ctrl+C with text selected copied it and interrupted as well. Every hotkey now keeps its key, whatever was typed before. A handler that chooses not to act gives the key back, so copy bound to Ctrl+C with nothing selected still sends one Ctrl+C.

Terminal

Another running app that wants the same port, hotkey or Claude events is named

Quick look

Running Torbie beside Tabby made three collisions silent: the MCP plugin's port, the global hotkey, and the consume-and-delete Claude hook spool. Torbie now checks when its window gains focus, names the other app and its PID, says what goes wrong in one sentence, and offers what this app can do: move its own MCP server to a free port and show the Claude Code command to match, stop starting it, or clear its own hotkey. It never touches the other app.

Builds

Text reads on every surface, and accordions are outlines

Quick look

An audit of every settings surface found 94 runs of text below WCAG AA in a light scheme and 98 in a dark one. None remain. Secondary text is a measured colour instead of half opacity, badges and buttons take text measured against their own fill, alerts are tints with measured text, and a dark scheme no longer shows a white stripe beside the vertical tab bar. Accordions are outlined cards rather than grey slabs, and profile selector rows show a pointer.

UI & theming

A contrast audit of every settings surface

Quick look

A script that attaches to a hidden build and measures every visible run of text on every settings page, the tab bar, the settings nav and the profile selector, in both schemes, against WCAG AA. Text is measured as the browser composites it, and a self-test plants cases with known ratios so a change to how anything is measured cannot pass unnoticed.

Robustness

Build cards sit in a grid laid out by container queries

Quick look

In cards view each card stretched across the whole pane. Cards now fill as many columns of at least 460px as the pane allows, each capped at 720px, and the page and every card answer to their own width rather than the window's. A build's kind is a chip with its icon, because colour could not tell five kinds apart, and every run of text on the page reads at AA in both schemes.

Builds

Every dark and light pair, one search, and tabs that keep their own tone

Quick look

The Pair tab found six designs and now finds fourteen, in twenty-one rows: names are split where words run together, a plain name counts as a half, and a family with more variants keeps its lead pair. The colours decide which half is which, never the name alone. Pair is the first tab, one search above the tabs serves all three, and each mode tab opens on its own tone.

UI & theming

Plugin search filters, and the list sorts

Quick look

Typing into the Plugins search reordered the list and never shortened it, because the npm registry ignores a search term sent beside a keyword qualifier. The catalogue is fetched once and searched locally, with four sorts for available plugins and three for installed ones, and a refused request shows an error with Retry instead of a spinner that never stops.

UI & theming

The integrations folder button opens a folder

Quick look

The button beside the folder for your own integrations did nothing on a fresh profile, because the folder did not exist and the shell's error was thrown away. It creates the folder first, and says so when it cannot.

Links

Preset menus are grouped and searchable from the keyboard

Quick look

Both rule preset menus list presets under the integration or family they belong to, focus their search box as they open and clear it as they close, and let ArrowDown carry on into the list. A rule made from a preset keeps its old name, so existing rules are still recognised.

Links

The settings nav is in labelled sections

Quick look

Nineteen settings pages sit under eight labelled sections instead of four favourites and an alphabetical run. One table places every page by id, so no provider file changed, and a plugin page that knows nothing about sections lands under Plugins rather than disappearing.

UI & theming

The Integrations list verifies itself

Quick look

Every integration is checked when the page opens, and each row says who the service thinks you are — or what is stopping it. Nothing is sent for one that is off or unconfigured, the rest go out together, and the rows draw before any of it finishes.

Links

Click a session, focus the pane it runs in

Quick look

A session running in a herdr or shefrd pane is raised in place instead of opening a browser. Three places are tried nearest first: a tab in this window, then the multiplexer pane, then the session registry on the web. Everything goes through the registry's own herdr endpoints, so no second address is configured and nothing invokes a binary.

Claude Code

The Claude panel is panes, each scrolling on its own

Quick look

Four collapsible panes on VSCode's sidebar model, each with its own scroll container, the expanded ones sharing the panel's height. The settings page behind them is grouped to match, and a switch that depends on another is disabled rather than silently doing nothing.

Claude Code

The Plugins tab lists again

Quick look

Both plugin lists rendered as nothing after the ng-bootstrap upgrade removed the accordion component the page used, which Angular reports as neither an error nor a warning. Migrated to the directive accordion, with the upgrade button moved out of the header button it was illegally nested inside.

UI & theming

The build scan asks each directory once

Quick look

Opening the Builds page spent 805ms walking the search roots, almost all of it on filesystem probes answered by a directory listing it then made anyway. The listing is read first and the expensive checks run only where it says they could succeed: 27-39ms, proved to find the identical set. Built from also says which of its two commits is the checkout's current head.

Builds

Follow hovered links and pin a preview

Quick look

Pane only immediately follows hovered links beside the source terminal. Pin a link to restore its cached content after a temporary hover, even if a network reply arrives late. Other terminals keep their hover cards. Zero counts disappear from popovers and remain muted in panes; Jira requests larger avatars.

Links

GitHub organizations and verified accounts

Quick look

Resolve repo#number through an editable, ordered list of preferred organizations. Add organizations discovered through GitHub CLI or a saved token. GitHub, Jira and Slack settings show the verified account name, avatar and connection status. Existing untouched GitHub presets migrate to match references inside prose.

Links

Rich ticket previews and nested links

Quick look

Jira tables and callouts retain their structure. Ticket titles, status controls and parent links stay above the tabs; pane comments use larger round avatars. Code blocks offer Copy and Wrap on hover. Links and recognized IDs inside previews share buffer rules, with nested popovers opt-in. Lintel also resolves plain Windows and WSL paths consistently.

Links

Formatted file previews and a shared link catalog

Quick look

Local text and source files preview in the hover card or pane. Markdown has Formatted and Raw controls, YAML metadata, and syntax colors. Lintel supplies language names, icons, mappings and platform reveal labels. Its shared preset list is searchable, includes Unblocked Code task links, and rules can be duplicated independently.

Links

Torbie's own mark, generated rather than exported

Quick look

The mark is >T — a prompt closing on the crossbar of a T, whose stem is a git-branch trunk with a commit at its foot and one at the end of the bar. Every asset comes from one definition of that geometry: three SVGs, six Linux PNGs, the Windows .ico, the macOS .icns, five tray images and the docs favicon, eighteen in all. Nothing is hand-exported, so nothing can drift. Two treatments over the one geometry — theme-aware SVGs that flip with prefers-color-scheme, and a bronze duotone that every raster bakes, because a PNG cannot flip and the Windows taskbar takes its colour from the OS rather than from the app. The splash and the accent move onto the same warm-stone palette.

UI & theming

It stops reporting into upstream's accounts

Quick look

Every build of this fork carried upstream Tabby's own credentials as literals, so its crashes went to Eugeny's Sentry project, its launches to his Mixpanel, and a published artifact would have authenticated against his Keygen distribution account — all under a version string that means nothing there. The updater and the release-notes tab read his releases too, so this build would offer to update itself to a different program. Analytics is removed outright rather than repointed, and the two switches that fed it go with it: a toggle that no longer sends anything is worse than no toggle, because it reads as a choice the user is making.

Robustness

The fork becomes Torbie, and the plugins still load

Quick look

A tortoiseshell tabby: the lineage is in the name, and the product is its own. Everything a user or the operating system reads is renamed; nothing a plugin reads is. There is no version gate anywhere in the loader — the tabby- package prefix and the tabby-plugin npm keyword are the entire compatibility contract — so touching either would silently unload everybody's plugins. Four places recognised a build by the literal 'tabby' and each was half of a pair that breaks in silence: rename one side and the scan just finds nothing, or the health check calls every stuck build healthy. They read one shared list now, which keeps both products, because an installed Tabby is still a build this machine has. The profile is copied forward before anything reads it, both environment prefixes are honoured, and tabby:// stays registered beside torbie://.

UI & theming

Something finally runs the tests

Quick look

There was no test script in any package.json and no workflow ran any of the forty test files here — every one was run by hand, which is not a slow safety net but the absence of one. The suites are grouped into tiers, because they cost three orders of magnitude apart: the fast tier is pure logic, 818 checks in four seconds, and that is what CI gates on alongside typecheck, lint, the consistency checkers and a build. The tier that launches a hidden window stays out on purpose — a gate that goes red for windowing reasons teaches people to ignore it. A missing suite file fails rather than skips, since a test that is renamed and quietly stops running is the exact thing this exists to prevent.

Robustness

The Link Tooltip page is grouped

Quick look

A 500-line flat scroll becomes four collapsible groups that remember what was open across saves and navigation. Two rows stay outside every group because nothing on the page governs them, and one setting gets a group of its own rather than being greyed out by a switch that does not actually apply to it.

Links

Which settings are this fork's

Quick look

Nothing in the running program said which behaviour is this fork's and which is upstream Tabby's — every settings row is drawn identically either way. Two switches on the Upstream page mark them: a filled diamond for a setting upstream does not have, and a hollow one for a setting it has but gives no control for. The list is recomputed from git rather than written by hand, and a checker fails when it drifts.

UI & theming

Angular 22, and the plugins that would have frozen

Quick look

Upstream is on Angular 15 and TypeScript 4.9; this runs on Angular 22 and TypeScript 6. Most of that upgrade was ordinary — module resolution that predated the exports field, a class-field semantic that changes what a field initializer may call, a webpack optimisation that produced a module with a null id. Two of them were not: Angular 22 makes OnPush the default change-detection strategy and standalone the default for components, and a Tabby plugin declares neither. The first meant the app booted, built its whole component tree, and rendered one element. The second meant a plugin's own NgModule was refused and the plugin simply did not load — eighteen instead of twenty-one, with nothing in the diagnostics log, because nothing had failed to resolve. Both defaults are restored on the one shared @angular/core object that every builtin and every plugin reaches the decorator through, rather than on this project's own eighty-seven files, which would have fixed our interface and silently frozen theirs.

Robustness

Integrations wear their own logos

Quick look

Every integration shipped with an empty icon, so cards and the Integrations list showed no logo at all. The four built-ins now carry real brand marks — and they carry the Windows Terminal fork's icon strings verbatim, with this host resolving the scheme to a PNG webpack inlines into the bundle. The JSON is identical on both sides again, so that key stops being a documented divergence.

Links

The card says which rule matched

Quick look

A line on the hover card naming the rule that produced it — or saying that none did and the defaults applied, which is the answer to "why is this link not previewed the way I set it up". Clicking it opens that rule in the settings. The button row also stops being pinned to the card's bottom edge and instead picks an edge named relative to the link, since the card flips above the line when there is no room below.

Links

A rule shows what it finds

Quick look

The rule editor takes a line of sample text and shows what the rule actually finds in it: the match highlighted where it sits, the named captures an integration would read back, and whether the pattern compiles. It runs the rule the way the terminal will — same guard, same flags, same caps, same criteria — so it cannot claim a match the terminal would refuse. Presets already in your list are no longer offered again.

Links

A preview you can read, in a pane

Quick look

A button on the card puts the same preview in a real pane beside the terminal — grouped fields, markdown bodies, comments, actions and a plugin's own HTML — with a switch that silences hover cards while one is open. One renderer component, mounted in two hosts, so the pane cannot end up less sealed than the card.

Links

What a click does is a chord you choose

Quick look

Two chords, primary and alternative, each a modifier by a gesture by an action — plus which kinds of link a click reaches at all, and a master switch. A rule may override either chord. Upstream's clickableLinks.modifier is migrated onto the primary chord rather than dropped, because it may be sitting in a real config.yaml.

Links

A rule starts from a preset, not an empty regex box

Quick look

Add rule is a split button whose caret offers nineteen searchable ready-made rules, and an Apply preset dropdown rewrites the rule you have open. A preset does not own its pattern: anything an integration already matches takes the pattern from that manifest, so the two cannot drift apart.

Links

A Slack-style <uri|label> is clickable all the way across

Quick look

The bracketed form Slack and many CLIs emit is one match at a priority above every handler, so the brackets and the label belong to the link instead of to nothing. The URI is still shown in full — collapsing it to the label would mean the renderer showing text the buffer does not hold.

Links

A WSL path resolves before anything asks whether it exists

Quick look

The \\wsl.localhost translation was correct and never ran: existence was checked on the path as written, so /home/you/notes.md was asked about as C:\home\you\notes.md, came back false, and the click did nothing. Existence is now asked once, of the path that would actually be opened — and a #L6-L7 fragment is stripped as a fragment rather than carried into the filename.

Links

The hover card stays inside the pane

Quick look

Clamping where an edge lands does nothing once the card is already wider than the pane it floats over. The width cap is now the lesser of the setting and the hovered screen's own width, written before the card is measured rather than after.

Links

A pane comes back running what it was running

Quick look

Upstream restores the furniture — the tabs, the splits, the profiles, a picture of what was on screen — but every pane comes back as a fresh shell, so the agent you had a two-hour conversation with and the multiplexer holding six sessions are simply not running any more. Each pane is asked what it is running, the answer is persisted with the layout, and it is typed back into the restored pane.

Sessions

Search the web for the selection

Quick look

Right-clicking a selection offers to search for it with whichever engine you configure. The template is parsed twice and the two origins compared, so text a remote host printed into your terminal can never turn the template into a request to a different host.

Terminal

The jump list wears each profile's own icon

Quick look

Upstream already offers your profiles when you right-click Tabby in the taskbar, but gave every entry the app's own icon, so it was a column of identical logos that told you nothing about what you were about to open. Font Awesome glyphs and inline SVG icons are rasterised into real .ico files the shell can read, and an entry is never blank and never dropped.

UI & theming

A useless process must not hold the lock

Quick look

Exactly one process answers for the app, so once that process cannot show a window, every later launch is handed to it and silently swallowed — no window, no error, no crash, indefinitely. Six hours of it, measured. A process in which no window has ever reported itself ready has run nothing and holds nothing to lose, and that one rule is what makes quitting safe.

Robustness

A startup error must not be a modal nobody sees

Quick look

dialog.showErrorBox is modal and synchronous — measured, a process showing one ran not a single timer callback in fourteen seconds. So a startup error left a process alive with no window, holding the single-instance lock, unable to run the watchdog that exists for exactly that. The failure is recorded first, the lock released second, and the box shown on its own thread third.

Robustness

An accent colour, instead of Bootstrap's pink

Quick look

Every code span in the app — paths, commits, identifiers, the build tooltip — was Bootstrap's #d63384, a pink belonging to no colour scheme here and the last hardcoded accent left in the UI. appearance.accentColor replaces it, and null follows the scheme.

UI & theming

A CDP test must prove what it attached to

Quick look

Chromium does not report a debugging port it could not bind — it just does not listen, and every request then goes to whatever is on that port. Measured here: a test assuming a fixed port attached to the user's own browser, full of logged-in tabs, and only a URL filter stopped it evaluating JavaScript in them. Ports are now found, never assumed, and nothing is attached to until it answers as Electron.

Robustness

Field groups, tabs, actions and detected patterns

Quick look

A manifest can group its fields under headings, carry a description body or a comment list behind a tab strip, offer actions that write back to the service, and name its own patterns to detect. Without these keys a manifest written for the other terminal degraded silently here — which is the real threat to "one manifest, many terminals". The six built-in manifests are now held key by key against that fork's copies, at a pinned commit — shefrd among them, a multiplexer pane address that becomes hoverable and opens the pane it names.

Links

A manifest can bring its own HTML

Quick look

An integration may render a complete HTML document in place of the field list, given the data every fetch step returned. It runs in a frame with sandbox="allow-scripts" and nothing else — an opaque origin, no require, no process — behind a CSP that refuses the network outright.

Links

xterm.js 6, and the canvas renderer retired

Quick look

The terminal renders through WebGL on xterm.js 6.0. The canvas renderer is gone — it was last released in April 2024 and xterm 6 deletes it outright — so terminal.frontend: xterm now means xterm's own DOM renderer, slow but always correct, and the fallback for a pane whose WebGL context could not be recovered.

Terminal

The splash screen follows the OS scheme

Quick look

The window's backing colour already followed the OS; only the splash CSS was hardcoded dark, so a light desktop got a black flash before the window drew. One appended media block, so the dark path's diff is nil.

UI & theming

What upstream has that we don't

Quick look

Settings → Upstream compares this checkout against the project the fork tracks: how many commits have landed there that are not here, the patch series carried on top, and where each commit is on the web. It never fetches on its own, so how stale the answer is has to be visible, and it is.

Builds

Every module that would not load

Quick look

tabby-electron alone swallows seven require failures in empty catch blocks, so a module that would not resolve left no trace and surfaced later as something unrecognisable. Module._load is wrapped, so the throw is seen before any of those catches reach it, and the error is always rethrown — this observes, it does not change what happens next.

Diagnostics

When it isn't the event loop

Quick look

Nothing blocks, the loop stays free, and the screen still lags — because frames are being dropped, or because xterm is taking a long time to lay out what was written to it. Both are timed and tallied into the same log, and a healthy hour writes no lines at all.

Diagnostics

Link hover cards, rules and integrations

Quick look

Hovering a link opens a card that says where it goes, what a click will do, and offers Open, Copy and Show in folder. A Link Tooltip settings page holds rules that customise the card per pattern, and an Integrations page runs declarative integration.json manifests that fetch a preview of what a link actually refers to — a ticket's status, a message, a session. Doing this also repaired Tabby's linkifier, which could never make a file path or a bare IP clickable at all.

Links

Why it froze

Quick look

A frozen window otherwise leaves no trace: Windows calls the process responding, nothing throws, and the app log had no timestamps to line anything up against. Every blocked event loop in the main process and in every renderer is recorded, with the synchronous calls that blocked it tallied by name — because what freezes this app is tens of thousands of individually-fast calls, not one slow one.

Diagnostics

Draw the colours the app asked for

Quick look

terminal.minimumContrastRatio defaulted to 4, and xterm.js rewrites every foreground that misses the ratio — 24-bit ones included. Solarized Light sits at 3–5:1 against a light background, so all thirteen of its colours were pushed toward mud and near-neighbours collapsed onto each other. The default is now 1, xterm's own "off" value, while the app chrome keeps its own floor of 4.

Terminal

Reset a setting; sliders that commit as you drag

Quick look

A setting that is off its default offers to go back, and a range control writes its value as it moves instead of only when the mouse is released — so dragging one previews nothing until you let go, which is exactly backwards.

UI & theming

A failed config save is reported, not dropped

Quick look

A config file that cannot be written — a read-only file in a mis-frozen build slot, most often — threw before the change event fired, so nothing persisted and nothing driven by that event re-applied either. Settings appeared to do nothing at all, in silence.

Robustness

Each window remembers where it was

Quick look

Upstream keeps one saved rectangle that every window reads and writes, which is invisible with one window and wrong the moment there are two: the second opens exactly on top of the first, and whichever closes last overwrites the other. Geometry is now per window, and a window whose title bar would land off screen is pulled back into a work area instead of being restored somewhere you cannot reach it.

Sessions

Every Tabby build on this machine

Quick look

Settings → Builds lists the installed app, the webpack output this fork runs from, electron-builder output inside a checkout, frozen build slots and installer files — with live process counts, memory and uptime, size on disk, build time, arch, branch and provenance. Processes are attributed by executable path, because two builds both called Tabby.exe are otherwise indistinguishable.

Builds

A doctor that says why a build will not start

Quick look

Written after an auto-update deleted nine of the twelve builtin plugin directories and left the app on a splash screen for ever, with Windows reporting the process as responding the whole time. Each build is health-checked on every scan, and one that will not start says so on its own card, with the cause found on disk.

Builds

Two named slots, canary and dev

Quick look

One script cuts a frozen, self-contained copy of the fork into a slot that runs beside your real Tabby: its own portable profile, shared plugins, no global hotkey and no MCP port to fight over. Exactly two slots — canary is disposable and every build replaces it; dev changes only by promoting the canary you actually tried.

Builds

One active build, and the pin that follows it

Quick look

Exactly one build is the Tabby you use: it is what the taskbar pin launches, it carries a badge, and it is never deletable — so there is always a working Tabby left on the machine. Nothing here can create a taskbar pin, because Windows removed that verb in 1809, but a Start menu entry can be written and a pin made from it is then kept aimed at the active build.

Builds

A docked Claude session panel and tab hover cards

Quick look

A panel docked to any edge of the window lists every Claude Code session on the machine — what it is doing, what it last asked, how much of its context window is gone — and a tab's hover card says the same about the session running in that tab. Tabs are joined to sessions by launch directory, never by PID, because a session inside WSL reports Linux PIDs that can never match Tabby's conpty PIDs.

Claude Code

A WSL tab knows which directory it is in

Quick look

Tabby understood iTerm's OSC 1337 but not OSC 7, which is what default bash and zsh — including WSL's — actually emit, so a WSL tab reported no working directory at all. A WSL profile's working directory can also be picked from inside the distro now, rather than typed as a guess.

Terminal

Vertical tabs, resizable and multi-column

Quick look

The side tab bar can be dragged to a width that is remembered, and flows into multiple columns once there is room for a whole one. Tab titles in this fork are paths and session names, which a horizontal strip truncates to nothing, so vertical is the default here.

UI & theming

Light-scheme contrast, borders, and an opaque window

Quick look

Control borders and surface separation come back on light schemes, hover states stay legible, swatches are labelled, and the window gets an opaque backing surface on Windows so a transparent frame does not show the desktop through the chrome.

UI & theming

Split and open-in-new-window for every tab

Quick look

The tab context menu offers to split or move out any tab, not only a terminal — and the new window inherits the running session rather than starting a fresh one.

UI & theming

The tab bar says which build this is

Quick look

Running several builds side by side means constantly answering "which one is this?". A hint in the tab bar names the build, and its tooltip carries the commit, the branch, how old the build is and the paths it is running from — kept inside the window rather than opening off the edge of the screen. The version beside them is compiled in rather than read back at runtime, because a source build and a packaged build of the same commit used to answer that question differently.

UI & theming

A build must load its own plugins

Quick look

A Tabby exports NODE_PATH to every shell it starts, and the module lookup appended its own paths to whatever it inherited — so a Tabby launched from a terminal inside another Tabby resolved tabby-core to the other build's copy: two Angulars, and a boot that stops dead on the splash screen. This build's paths now go first, and the builtins that must not be got wrong are required by absolute path.

Robustness

: , and / stay inside a clickable URL

Quick look

Tabby's URL handler dropped a colon, comma or slash from a path or query, so a link to a line number or a list parameter stopped short of where it pointed. Three characters added to two character classes.

Links