Support matrix
Where attribution works today, browser by browser and system by system, and the one step that gets it where the default setup can’t.
Links an install to the visit on the same Mac or Linux computer in Chrome, Firefox, Edge, Brave and Vivaldi, and in Safari through the handoff command.1
Attribution (the same-machine match, the handoff command and reconstruction) runs on Standard and Enterprise. On Free, CLItrail counts visits and installs without matching them, and installs reported on Free are never matched later.
Last updated: . The same data drives the support page.
#How to read it
- Supported
- CLItrail handles it with the default tag and hook, or with the step in the last column.
- Via handoff
- The hook does not read this browser’s storage here. Show the handoff command from
prepareInstallon your install page: the token travels with the command. - Probable
- Paid plans. Reconstruction from other signals when neither a receipt nor a token arrives: always labelled probable, and sent to ad platforms only where a destination opts in.
- Not supported
- The code does not handle it. The last column says what to do instead.
- Website tag
- browser.js records the visit and writes the receipt (https or localhost, JavaScript on).
- Same-machine match
- The installer hook finds the receipt by itself: same computer, same OS user, macOS or Linux.
- Handoff command
- The page prepares an install command that carries a token; it needs a POSIX shell.
- Reconstruction
- A probable match from other signals when neither a receipt nor a token arrives. Paid plans.
#Browsers and systems
Supported Handoff command, unless a cell says otherwise: Browser-independent once prepared.
Probable Reconstruction, unless a cell says otherwise: Paid plans. When no receipt or token arrives, a match from the public network and other signals, labelled probable.
#
macOS
The hook searches the browser profile folders under ~/Library/Application Support for the user who runs it.
| Browser | Website tag | Same-machine match | Handoff command | Reconstruction | How to get attribution here |
|---|---|---|---|---|---|
| Supported | SupportedThe hook searches Chrome’s profile folder for the user who runs it. | Supported | Probable | Works with the default tag and hook. Run the hook with --doctor as the visitor’s user to confirm it finds the profile. Hook diagnostics | |
| Supported | SupportedThe hook searches Firefox’s profiles folder for the user who runs it. | Supported | Probable | Works with the default tag and hook. Confirm with --doctor on the installing Mac. Hook diagnostics | |
| Supported | SupportedThe hook searches Brave’s profile folder for the user who runs it. | Supported | Probable | Works with the default tag and hook. Desktop Brave sends a Chrome user agent, so auto mode treats it as Chrome and uses the receipt. Hook diagnostics | |
SupportedFor Safari before 26, allow worker-src blob: in the page’s CSP. | Via handoffSafari’s protected storage is never read: the prepared command carries the visit instead. | SupportedAuto mode prepares it (reason safari_requires_handoff). | Probable | Show the command from prepareInstall({ mode: 'auto' }) on your install page. For Safari before 26, allow worker-src blob: in the page’s CSP. Handoff command | |
| Supported | SupportedThe same folder layout as Chrome. | Supported | Probable | Same as Chrome. --doctor names each channel it finds. Hook diagnostics | |
| Edge | Supported | SupportedThe Microsoft Edge profile folder is searched. | Supported | Probable | Default tag and hook. Edge names itself in its user agent, so auto mode uses the receipt. Where the hook looks |
| Supported | SupportedBoth profile folders are searched. | Supported | Probable | Default tag and hook. Vivaldi sends a Chrome user agent, and its profiles are searched. Where the hook looks | |
| Supported | Via handoffArc publishes no profile folder, so the hook does not search it. | SupportedOnly when forced: Arc sends a plain Chrome user agent, so auto mode does not hand off. | Probable | Where Arc matters to your audience, use prepareInstall({ mode: 'handoff' }) so every visitor gets the prepared command. Handoff command | |
| Zen and other Firefox forks | Supported | Via handoffOn macOS only Firefox’s own profile folder is searched. | SupportedOnly when forced: these browsers send a Firefox user agent, so auto mode does not hand off. | Probable | If your audience uses Zen, LibreWolf, Floorp or Waterfox, use mode: 'handoff'. Handoff command |
| Supported | Via handoffTheir profile folders are not searched. | SupportedAuto mode prepares it (reason unqualified_browser). | Probable | Nothing beyond prepareInstall({ mode: 'auto' }): these browsers name themselves, so they get the prepared command. Handoff command | |
| Supported | Via handoffWebKit storage is never read. | SupportedAuto mode hands off when the browser reports a Safari user agent. | Probable | Same as Safari: show the command from prepareInstall({ mode: 'auto' }). Handoff command |
#
Linux
The hook searches ~/.config (or $XDG_CONFIG_HOME), ~/.mozilla, ~/.zen, and the Snap and Flatpak profile folders for the user who runs it.
| Browser | Website tag | Same-machine match | Handoff command | Reconstruction | How to get attribution here |
|---|---|---|---|---|---|
| Chromium | Supported | SupportedThe hook finds ~/.config/chromium itself, as the user who runs it. | Supported | Probable | Works with the default tag and hook. Hook diagnostics |
| Supported | SupportedThe hook finds ~/.mozilla/firefox itself, as the user who runs it. | Supported | Probable | Works with the default tag and hook. Hook diagnostics | |
| Supported | SupportedUbuntu’s Firefox snap, the Chromium snap, the Flathub Firefox and Chromium builds, and Firefox 147+ profiles under ~/.config/mozilla. | Supported | Probable | Default tag and hook. --doctor lists them as Firefox (Snap), Chromium (Flatpak) and so on. Hook diagnostics | |
| Supported | SupportedTheir ~/.config folders are searched, including Chrome Beta and Dev. | Supported | Probable | Default tag and hook. Where the hook looks | |
| Zen | Supported | Supported~/.zen and the Flathub build are searched. | Supported | Probable | Default tag and hook. Where the hook looks |
| Supported | Via handoffTheir profile folders are not searched. | SupportedAuto mode prepares it (reason unqualified_browser). | Probable | Nothing beyond prepareInstall({ mode: 'auto' }) for browsers that name themselves; force mode: 'handoff' for any other. Handoff command | |
| WebKit browsers | Supported | Via handoffWebKit storage is never read. | SupportedAuto mode hands off when the browser reports a Safari user agent. | Probable | Show the command from prepareInstall({ mode: 'auto' }). Handoff command |
#Windows
There is no native Windows hook. Run the handoff command from WSL (a POSIX shell); PowerShell and cmd are not supported.
| Browser | Website tag | Same-machine match | Handoff command | Reconstruction | How to get attribution here |
|---|---|---|---|---|---|
| Supported | Via handoffNo native Windows hook, and a Windows browser and a CLI inside WSL do not share profile folders: the prepared command carries the visit instead. | SupportedAuto mode prepares it (reason platform_requires_handoff). Run it from WSL (a POSIX shell); PowerShell and cmd are not supported. | ProbablePaid plans, when an install is reported, for example by a hook inside WSL. | Show the command from prepareInstall({ mode: 'auto' }) and run it from WSL. For packages that also run on Windows, call a platform-aware entry point, and rely on reconstruction for installs a hook reports from WSL. Handoff command |
#ChromeOS
The SDK routes ChromeOS to the handoff command. Run it in ChromeOS’s Linux environment.
| Browser | Website tag | Same-machine match | Handoff command | Reconstruction | How to get attribution here |
|---|---|---|---|---|---|
| Supported | Via handoffThe SDK routes ChromeOS to the handoff command. | SupportedRun it in ChromeOS’s Linux environment (a POSIX shell). | ProbablePaid plans, when an install is reported. | Show the command from prepareInstall({ mode: 'auto' }) and run it in the Linux environment. Handoff command |
#
iOS and iPadOS
Installs happen on a computer, so a phone visit needs the handoff command or reconstruction.
| Browser | Website tag | Same-machine match | Handoff command | Reconstruction | How to get attribution here |
|---|---|---|---|---|---|
| Supported | Not supportedThe install happens on another device. | SupportedAuto mode prepares it (reason platform_requires_handoff); the command still has to reach the computer. | ProbablePaid plans. A phone visit and a computer install on the same network can match. | Rely on reconstruction for phone-to-computer journeys on the same network. iPads that request desktop sites are routed to the handoff command too. Reconstruction |
#
Android
Installs happen on a computer, so a phone visit needs the handoff command or reconstruction.
| Browser | Website tag | Same-machine match | Handoff command | Reconstruction | How to get attribution here |
|---|---|---|---|---|---|
| Supported | Not supportedThe install happens on another device. | SupportedAuto mode prepares it (reason platform_requires_handoff); the command still has to reach the computer. | ProbablePaid plans. A phone visit and a computer install on the same network can match. | Rely on reconstruction for phone-to-computer journeys on the same network. Reconstruction |
#Install contexts
Where the install command runs matters as much as the browser. The hook needs the visitor’s own computer and OS account to find a receipt.
| Where the install runs | Same-machine match | Handoff command | Reconstruction | How to get attribution here |
|---|---|---|---|---|
| Same computer, same OS user | SupportedIn the browsers whose same-machine match is Supported above. | SupportedOptional. | ProbablePaid plans, only when no receipt arrives: the receipt wins. | The default setup. Confirm with --doctor on that computer, as that user. Hook diagnostics |
| Installer run with sudo | SupportedWhen the hook runs as the original user, not as root. | SupportedThe prepared command carries its own token and reports after your command exits 0. | ProbablePaid plans. When no receipt or token arrives, a match from the public network and other signals, labelled probable. | Do the privileged steps with sudo, then run the hook as the original user. Run as the right user |
| SSH session, remote box, devcontainer or Docker | Via handoffThe browser’s storage is on another machine or filesystem. | SupportedWhen the prepared command is pasted there. | ProbablePaid plans. Rarely matches: the box is usually on a different public network, or a shared one. | Show the prepared command on your install page, so the token travels with the paste. Handoff command |
| CI runners | Not supportedThe hook exits before reading anything when CI, GITHUB_ACTIONS, GITLAB_CI, BUILDKITE, CIRCLECI, TF_BUILD or JENKINS_URL is set. | Not supportedThe same exit. | Not supportedNothing is reported. | By design: a CI install is not a person. CLITRAIL_ALLOW_CI=1 turns reporting on to check your own integration. Opt-outs |
DO_NOT_TRACK=1 or CLITRAIL_DISABLE=1 | Not supportedThe hook exits before reading anything. | Not supportedThe token is never redeemed. | Not supportedNothing is reported. | Respected by design. Nothing is read or sent. Opt-outs |
| AI coding agent on the person’s computer | SupportedWhen the agent runs as the same OS user and the person visited in a supported browser. | SupportedWhen the agent copies the prepared command from a page that ran JavaScript. A plain HTTP fetch does not run it. | ProbablePaid plans. When no receipt or token arrives, a match from the public network and other signals, labelled probable. | Nothing extra when the agent runs as the person on their computer. How attribution works |
| AI agent in the cloud or on a remote box | Via handoffThe browser is somewhere else. | SupportedWhen it is given the prepared command. | ProbablePaid plans. Rarely matches: usually a different network. | Have the person give the agent the prepared command from your install page. Handoff command |
npx, Homebrew launchers and Python entry points | SupportedAt first launch, on the person’s computer. | SupportedPass event: 'first_run' to prepareInstall. | ProbablePaid plans. When no receipt or token arrives, a match from the public network and other signals, labelled probable. | Report first_run from your CLI’s entry point, and tick first_run on your ad destinations: they send completed installs only by default. First-run events |
#Methodology
The coverage figures answer one question: what share of desktop install-page visits happen in a browser where CLItrail can re-link a same-machine install through the receipt? A visit counts as covered when its user agent names a browser family whose storage the hook searches on that system: Chrome, Edge, Firefox or Brave on macOS, and Chrome, Chromium, Edge, Firefox or Brave on Linux. Vivaldi and Chromium sit inside “Chrome” in user-agent data. Windows, ChromeOS, iOS and Android count as zero.
These are shares of visits (requests, respondents or unique visitors), never of installs, and they are upper bounds:
- user-agent “Chrome” includes Arc and other Chromium forks the hook does not search, and “Firefox” includes Zen and other forks;
- a covered browser is only the first condition: the install must also run on the same computer, as the same OS user, while the receipt is still there (see below).
#Developer audiences
Nine Devographics surveys, measured from each respondent’s user agent (desktop OS mix × that edition’s browser split). Buckets under about 10 responses are suppressed by the API and treated as not covered. “With handoff” adds Safari on macOS through the handoff command.
| Survey (fielded) | macOS / Windows / Linux | Receipt path | With handoff |
|---|---|---|---|
| State of JS 2025 (Sep–Nov 2025) | 49.76 / 38.25 / 11.99 | 55.89% | 61.37% |
| State of CSS 2025 (Jun–Jul 2025) | 53.17 / 36.02 / 10.81 | 55.88% | 63.21% |
| State of HTML 2025 (Jul–Aug 2025) | 52.74 / 34.69 / 12.57 | 55.79% | 64.64% |
| State of Devs 2025 (Apr–May 2025) | 57.09 / 30.99 / 11.93 | 61.45% | 68.61% |
| State of React 2025 (Nov 2025–Jan 2026) | 60.91 / 29.92 / 9.17 | 65.09% | 69.73% |
| State of AI 2025 (Feb–Mar 2025) | 50.79 / 34.92 / 14.29 | 57.38% | 64.62% |
| State of CSS 2026 (May–Jun 2026) | 56.68 / 31.24 / 12.08 | 61.67% | 68.47% |
| State of AI 2026 (Apr–May 2026) | 56.89 / 28.98 / 14.13 | 62.70% | 70.40% |
| State of Devs 2026 (Jul–Sep 2026, latest) | 53.43 / 29.40 / 17.17 | 63.46% | 69.96% |
| Minimum – median – maximum | 55.79 – 61.45 – 65.09% | 61.37 – 68.47 – 70.40% |
Worked example, State of Devs 2026: on macOS, Chrome 752 + Firefox 242 + Edge 24 = 1,018 of 1,168 respondents (87.16%) × 53.43 = 46.57 points; on Linux, Firefox 209 + Chrome 160 = 369 of 375 (98.40%) × 17.17 = 16.90 points; together 63.46%.
Public Plausible dashboards of four developer sites, desktop unique visitors, September 2025 to August 2026:
| Site | macOS / Windows / Linux | Receipt path | With handoff |
|---|---|---|---|
| direnv.net (a CLI tool’s site) | 57.56 / 23.16 / 19.11 | 67.95% | 76.07% |
| rubyonrails.org | 54.28 / 32.53 / 12.94 | 57.22% | 66.56% |
| gleam.run | 48.76 / 31.28 / 19.37 | 54.55% | 67.30% |
| nim-lang.org | 29.64 / 48.92 / 20.57 | 42.34% | 48.88% |
These sites’ Plausible scripts are on a common blocklist, so visitors who block trackers, who lean towards Firefox and Brave (both covered), are missing.
#General web traffic
For transparency, not for marketing: on general web traffic the same browsers account for 17.3% of desktop requests worldwide and 24.0% in the US (Cloudflare Radar, August 2026, likely-human). Windows, which has no native hook, is 74.6% and 64.2% respectively. Adding Safari through the handoff command gives 23.90% and 33.21%. Worldwide, the monthly figure ranged from 15.26% to 17.79% between August 2025 and August 2026.
#Worst case
A stress test treats self-reported use of browsers the hook does not read as if it were visit share, which overstates the loss. From State of Devs 2026: 63.46 − Arc 5.73 − Zen 6.02 − Ubuntu-token Linux Firefox 2.70 = 49.01%; for the median edition, 47.96%; for direnv.net, 53.84%. So under worst-case assumptions about half of developers’ desktop visits remain in covered browsers, and the measured user-agent figures put the upper bound at about 6 in 10.
#Windows
Windows counts as zero because there is no native hook. People on Windows can still be attributed: run the handoff command from WSL (a POSIX shell). PowerShell and cmd are not supported.
#Why there is no recovery percentage
A claim such as “recover X% of your lost install attribution” would multiply the share of visits in covered browsers by factors nobody measures: how often the install runs on the same computer and OS account as the visit, whether the receipt is still there (not private browsing, not cleared, under 30 days), whether the hook runs (not CI, no opt-out, the right user), and whether the visit carried the platform’s click ID with consent. It would then divide by a number nobody defines: installs whose attribution is lost today, which include README copies, registry pages and word of mouth.
Only the first factor is measured, and only as a share of visits. Reconstruction is probabilistic and has no measured accuracy. What you can measure is your own ratio of matched, reconstructed and unattributed installs, which the dashboard’s Overview shows for your traffic.
#Sources
| Source | Data period | Metric | Retrieved |
|---|---|---|---|
| Cloudflare Radar HTTP, desktop, likely-human | Aug 2026; monthly Aug 2025–Aug 2026 | Share of HTTP requests | 2026-09-24 |
| StatCounter desktop OS, 12-month mean | Sep 2025–Aug 2026 | Pageviews | 2026-09-24 |
| Wikimedia all sites by OS and browser | 2026-08-02 – 2026-08-29 | Pageviews | 2026-09-24 |
| Devographics survey user agents | 9 editions, Feb 2025–Sep 2026 | Respondents | 2026-09-24 |
| State of CSS 2026 browsers question | May–Jun 2026 | Share of 3,787 answering, multi-select | 2026-09-24 |
| Plausible public dashboards: direnv.net, rubyonrails.org, gleam.run, nim-lang.org | Sep 2025–Aug 2026 | Unique visitors, desktop | 2026-09-24 |
| Ubuntu 22.04 release notes: Firefox is a snap | 2022 | — | 2026-09-24 |
| Firefox 147 release notes: XDG base directories | 2026-01-13 | — | 2026-09-24 |
| Google Ads Help: offline conversion imports | — | — | 2026-09-24 |
| Meta Business Help: Conversions API, custom conversions | — | — | 2026-09-24 |
| TikTok Events API 2.0: supported events | — | — | 2026-09-24 |
| CLItrail’s code: the folders the hook searches and when the SDK prepares a handoff | As of 2026-09-24 | — | 2026-09-24 |
Refreshed monthly for Cloudflare Radar and Plausible, and when new Devographics editions publish.
#Notes
- On macOS and Linux the hook searches the profile folders of Chrome, Chrome Beta, Chrome Dev, Chromium, Edge, Brave, Vivaldi and Firefox; on macOS also Chrome Canary, and on Linux also Zen and the Snap and Flatpak builds. Safari, WebKit browsers and forks that name themselves, such as Opera, get the handoff command from prepareInstall in auto mode. For browsers that present themselves as Chrome or Firefox but keep their own profiles, such as Arc or LibreWolf, use handoff mode. See where the hook looks.