Two named slots, canary and dev
Explore this workspace.
Technical background
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.
The problem
Testing a change means running a build beside the Tabby holding your live sessions. Doing that from a checkout means the two fight over the global hotkey, the MCP port and the config directory — and a build cut from a moving tree cannot be trusted to still be the thing you tested.
How it works
scripts/make-slot.mjs builds a frozen, self-contained copy into ~\Tabby\builds\: its own portable data\, plugins shared through a junction, app files marked read-only so a slot cannot drift after it is cut. There are exactly two — canary is disposable and every build replaces it; dev is the one you work in and changes only by promoting the canary you actually tried.
Try it
node scripts/make-slot.mjs— build and install canary.- Use it. When it is good:
node scripts/make-slot.mjs --promote— copy canary into dev. --dry-run --skip-buildprints what it would do, including which profile it would seed from.
Details
- Promotion copies the canary that was built and tried, never a fresh compile. Otherwise "promote what I verified" would quietly mean "build something new and call it verified". Dev's
BUILD-INFO.txtis canary's with aPromoted:line, so dev can never claim a commit that was not in its binaries. - A slot that is running is never replaced, and the check is on that slot's own path rather than "any Tabby" — the point of two slots is that the other one keeps running while you rebuild this one.
- Rebuilding a slot keeps its
data\. A genuinely new slot seeds from the other slot, and from the installed app's profile only when there is no other slot at all. The choice is printed. - The seeded profile drops the global toggle hotkey and blacklists the MCP server, because a slot runs beside your Tabby: otherwise whichever instance starts first takes both and the other silently half-works.
- Anything under
~\Tabby\builds\that is neither slot is pruned on every run — unless it is running, in which case it is reported and left. That is what makes "only ever two" structural rather than a habit.
What this does not claim
- The first version of
freeze()frozedata\config.yamltoo, and a read-only config file makes a slot lose every settings change in silence: the config write is an atomic rename, which isEPERMover a read-only file on Windows, so the save throws before the change event fires. Nothing persists, and nothing driven by that event re-applies either — so theme, spaciness and docking appear to do nothing at all while you are still in the window.freeze()now skipsdataby name and the script asserts the config is writable before reporting success. - The naming scheme was replaced. Slots used to be
<version>-<MMDD>-<HHmm>-<sha>directories, one per build, which accumulated until somebody noticed the disk — and every slot on the machine at the time was stale enough to hang, so what piled up was three copies of a trap. cpSynccarries the read-only bit, so promoting a frozen canary lands frozen files in dev and the very next write failsEPERM. Attributes are cleared after the copy as well as before it.