What a click does is a chord you choose
Explore this workspace.
Technical background
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.
The problem
Whether a link opens on a click, and what it opens with, was one boolean and one modifier. Alt+click and shift+click are selection gestures; middle click pastes; ctrl+left is a right click on Windows by default. All of those overlap with "follow the link", and one setting cannot express which one you meant.
How it works
Two chords, primary and alternative, each a modifier × gesture × action — plus which kinds of link a click reaches at all (detected, rules, osc8) and a master switch. A rule may override either chord's action: '' inherits, 'none' suppresses. clickChords.ts is the whole decision, kept pure so the test can measure it rather than drive a window.
Settings
linkTooltip.clickable:trueWhether clicking a link activates it at all. Off, links are still detected, highlighted and previewed.
linkTooltip.clickableKinds:['detected','rules','osc8']Which kinds of link a click reaches.
linkTooltip.primaryClickModifier:'none'Matched exactly — Ctrl+Shift does not satisfy a plain-Ctrl chord.
linkTooltip.primaryClickGesture:'left'left, middle or double.
linkTooltip.primaryAction:'open'What the primary chord runs.
linkTooltip.alternativeClickModifier:'ctrl'The second chord's modifier.
linkTooltip.alternativeClickGesture:'left'The second chord's gesture.
linkTooltip.alternativeAction:'open'What the alternative chord runs.
Details
- Left resolves on release; middle and double resolve on the press. A press is also the start of a selection drag, so a left chord has to wait and then refuse if a selection was made. The other two have something to beat on the same event — the terminal pastes on a middle mousedown, and a double press selects a word — so they listen on
.xterm-screenand stop propagation, but only once they know an action will actually run. - xterm calls
activateon any button's mouseup, with no button check, so a middle release would fire a second time after the press already did.activatetherefore handles left gestures only. - OSC 8 clicks are taken over, not forwarded.
tabby-linkifier's own handler decides for itself from the legacy modifier; leaving it in the wrapper would mean an OSC 8 link ignoring both the chords and theosc8filter, and opening twice whenever they agreed.
What this does not claim
- Alt+click and shift+click no longer follow a link. Modifiers match exactly, so a Ctrl chord does not fire mid-Ctrl+Shift-drag — and the price is that two gestures the old
!modifiertest allowed now do not. Both are selection gestures, and this is what Windows Terminal does. terminal.rightClick: 'menu'— the Windows default — already treats ctrl+left as a right click, so the default alternative chord pops a context menu as well as following the link. Unchanged from before, since the oldclickableLinks.modifier: nullhad exactly the same overlap.
In upstream Tabby
clickableLinks.modifier is upstream's key and is migrated, not dropped — it may be sitting in a real config.yaml. The migration moves it onto the primary chord, silences the alternative (which defaults to Ctrl+click and would otherwise re-enable the very click the user turned off), and clears the key as it reads it, so it is idempotent without a config.version bump. A fork-owned bump would make upstream's own migrations skip these configs at the next sync.