A browser extension that turns a group of open tabs into one shareable link -- and whoever you send it to opens it in any browser with no extension, no account, and no sign-up.
- Pick a window, a tab group, or a pasted list -> one link, copied to your clipboard.
- The recipient needs no extension. The whole page list rides inside the
link (everything after the
#); their browser opens it as a slideshow / grid / list and sends the list to no one. - No account, no server, no database. The extension makes no network requests; nothing is tracked, on either side.
- Optional: password-protect the link, or shorten it with the Tab Share shortener -- the short link opens the same way, still no extension.
Browsers: Chrome, Chromium, Edge, Brave, Opera, Vivaldi, Arc, and Firefox (plus forks like Zen / LibreWolf). Desktop today; mobile is on the roadmap -- see the support matrix.
| Store | Link |
|---|---|
| Chrome Web Store (Chrome / Edge / Brave / Opera / Vivaldi / Arc) | Add to Chrome (1.0.0-beta.11) |
| Firefox Add-ons (Firefox and forks) | Get the Add-on (1.0.0-beta.11) |
Or install it yourself (about two minutes) on any supported browser.
Status:
1.0.0-beta.11is live on both the Chrome Web Store (listing) and Firefox Add-ons (approved and listed) -- German and Spanish throughout, plus localized store listings. Tested end-to-end on Chrome, Opera, Firefox, and Zen. Or run your own copy withdocs/SELF-HOSTING.md.
![]() |
![]() |
![]() |
![]() |
Screenshots are simulated mockups of the UI.
- Click the toolbar button. Pick your pages from:
- Windows -- the current window's tabs, pre-checked; a picker appears if more than one window is open;
- Tab Groups -- pick a browser tab group and + Add it (combine several);
- Paste Links -- one URL per line, or pull in the current window's tabs.
- Reorder / trim / rename the list. The list and the name survive closing the popup. Optionally set a password.
- Create share link -> it's copied to your clipboard automatically.
- The recipient opens it in any browser. Four views, switched from Change
View:
- Slideshow -- framed page, side + bottom arrows, first/last, keyboard nav, a clickable segmented pager, jump-to-page;
- Preview Grid -- large tiles with a live preview where the site allows it;
- Grid -- compact cards, numbered, full URL on hover;
- List -- a copyable numbered list (copy all, or links only). Per-view search filters by title / site / URL. Select mode adds checkboxes to any view and opens the checked pages in this window, a new window, or a new tab group. Open all pages opens every (filtered) page. Light / dark toggle, dark by default.
One MV3 codebase, two manifests (dist/chrome, dist/firefox). Sending a
link is the extension; opening one is the static viewer and works in any
modern browser, mobile included, with no extension.
| Browser | Create links | Tab Groups source | Tested |
|---|---|---|---|
| Chrome / Chromium | ✅ | ✅ | ✅ end-to-end |
| Edge | ✅ | ✅ | ⬜ same engine as Chrome; not separately click-tested |
| Brave | ✅ | ✅ | ⬜ should work; a localhost shortener may need a Shields exception (moot on HTTPS) |
| Opera | ✅ | ✅ | ✅ end-to-end |
| Vivaldi | ✅ | ✅ | ⬜ TBD |
| Arc | ✅ | ✅ | ⬜ TBD |
| Firefox (≥ 139) | ✅ | ✅ | ✅ end-to-end |
| Zen | ✅ | ✅ | ✅ end-to-end |
| LibreWolf / Waterfox / Floorp / Mullvad | ✅ | ✅ | ⬜ TBD (other Firefox forks) |
| Firefox for Android | ⬜ blocked | ❌ no tab-groups API on Android | ⬜ roadmap -- tabGroups must become optional first |
| Safari | ⬜ manifest + dist/safari/ ready, Xcode conversion not done |
❌ no tabGroups API in Safari; degrades gracefully (feature-detected) | ⬜ xcrun safari-web-extension-converter + Xcode needed -- macOS-only, can't build or test from this repo's Linux dev setup |
| Chrome / Safari on iOS & Android | ❌ no extension support | -- | -- |
| Opening a shared link (any of the above + mobile) | -- | -- | ✅ responsive viewer, no extension needed |
✅ works · ⬜ expected to work / not yet verified · ❌ not possible
The collection (page URLs + titles) is compressed with
lz-string and written into the URL
fragment -- the part after #. Browsers never transmit the fragment, so:
- no backend, no database, no accounts;
- the extension makes no network requests (unless you turn on a URL shortener);
- the viewer makes none (unless you leave the site-icons option on, which
fetches favicons from
icons.duckduckgo.com); - the link is self-contained (~500 chars for 5 pages, ~1.5 KB for 30);
"+"is swapped out of the token so chat apps can't mangle it.
A small static page (viewer/) decodes the fragment in the recipient's browser
and renders the views. You host it anywhere -- see docs/SELF-HOSTING.md.
Tick Protect with a password and the whole collection is encrypted in your browser (WebCrypto: PBKDF2-SHA-256, 210 000 iterations -> AES-256-GCM) before it goes in the link. The recipient types the password into the viewer to decrypt locally -- the password is never stored or sent. Lose it and the link can't be opened.
Tick Minimal link to drop page titles and the timestamp from the link --
URLs only, roughly half the characters -- and strip known ad / analytics query
params (utm_*, fbclid, ...) from every URL. The viewer falls back to the
site name, so the link still opens and navigates. A normal link is untouched --
same URLs you gave it. Details and the backward-compatibility notes:
docs/MINIMAL-LINKS.md.
Most big sites (Google, banks, X, YouTube, ...) send X-Frame-Options / CSP
headers that forbid being embedded in another page. viewer/frame-hosts.js
classifies hosts from a header probe of the ~730 most-visited / most-shared
domains (rebuild it with tools/frame-probe/):
- framing-friendly (Wikipedia, MDN-style docs, many reference and dev sites) preview inline automatically;
- known blockers show a clean card with just "Open this page";
- everything else shows the card plus an opt-in "Try live preview" -- and if that preview never loads, the viewer drops it and remembers the host for the session.
The grid views, Open all pages, and Select -> open sidestep framing entirely.
When a Tab Share link is opened in a browser that has the extension, a button appears in the viewer's toolbar -- Open with Tab Share -- offering to open the collection natively: into the current window, a new window, or a tab group, or to save it to history with a title. Everyone else just gets the slideshow. It's a content script that runs only on the viewer page (statically, just the packaged viewer host); point the extension at your own viewer and the options page asks you to approve that one host first. Hide the button from its own menu or the options page; bring it back from the viewer's settings menu.
A 40-page collection is ~4 KB of link -- fine to send, unwieldy to paste. The
Tab Share shortener turns
one into s.kaikay.de/swift-amber-otter. It's a small zero-dependency Node
service (also a Cloudflare Worker) that:
- takes multi-kilobyte links, fragment intact, where TinyURL / is.gd choke;
- redirects straight to the viewer, so the short link still opens in any browser with no extension -- same as the full link;
- only ever redirects to an allow-listed viewer host, so it can't become an open redirector;
- keeps no IP, no geolocation, no cookies -- aggregate day counts only, and never sold;
- is self-hostable in a couple of minutes.
Recommended. In Options -> Shorten links, pick Tab Share shortener --
it's pre-filled with the public instance at s.kaikay.de, which allow-lists the
built-in viewer, so it works with no setup. Off until you turn it on, still
opt-in per link. docs/CUSTOM-SHORTENER.md covers
the other options (da.gd, TinyURL, a custom endpoint) and how they compare on
what they log.
| Permission | Required? | Why |
|---|---|---|
tabs |
yes | Read URL + title + icon of the current window's tabs, only on button click. |
storage |
yes | Remember your viewer URL, setup choices, last 50 links, on-device (storage.local). |
tabGroups |
yes | The Tab Groups source, and creating a group on import (a content script can't request it at runtime). |
scripting |
yes | Register the import banner for a self-hosted viewer URL you set. |
| host access to a non-default viewer URL | optional, asked when you save one | Show the import button on your own viewer host. |
| host access to a shortener | optional, asked when you enable one | Send the generated link to da.gd / TinyURL / your own endpoint. |
No static host_permissions. One content script, scoped to the packaged viewer
host only (plus any host you opt into). A minimal background worker (import
actions + content-script registration). No remote code. No data collection.
User-facing statement in PRIVACY.md.
shared/ canonical codec + helpers (lz-string, share-codec, monogram)
extension/
manifest.chrome.json / manifest.firefox.json
src/ popup + options + background worker (plain HTML/CSS/JS)
src/content/ import-banner.js -- viewer-page "open with the extension" button
icons/ icon.svg + generated PNGs
viewer/ self-contained static site (slideshow / preview grid / grid / list)
frame-hosts.js header-probed allow/deny list for auto-previewing sites
tools/frame-probe/ regenerates that list from live response headers
docs/ SELF-HOSTING, BUILD, SECURITY, THIRD-PARTY, CUSTOM-SHORTENER, MINIMAL-LINKS
assets/ artwork -- icon, promo tiles, simulated screenshots, og-card (svg sources; PNGs via `npm run icons`)
dev/ mocked-chrome harness for eyeballing the UI (not shipped)
scripts/ build / sync / icons / selftest / dev-server
npm test # codec round-trip tests
npm run dev # preview popup + options + import button at localhost:8778
npm run build # dist/chrome + dist/firefox + dist/viewer
npm run serve:viewer # serve the real viewer at localhost:8777, append #<token>Load dist/chrome/ (Chromium) or dist/firefox/manifest.json (Firefox)
unpacked. Full instructions for every OS / browser without a store:
docs/SELF-HOSTING.md. Dev workflow:
docs/BUILD.md.
1.0.0-beta.11 is live on both the Chrome Web Store and Firefox Add-ons, and
tested end-to-end on Chrome, Opera, Firefox, and Zen: link creation from every
source, the four viewer views, navigation, the segmented pager at 14 and 50
pages, per-view search, selection mode, theme toggle, password unlock, the
empty-link state, and the companion import button / reversible-hide flow.
viewer/ deploys to GitHub
Pages via .github/workflows/deploy-viewer.yml; the privacy policy is published
at /privacy.html alongside it. See CHANGELOG.md for what's changed and
ROADMAP.md for what's planned (notably an offline safer-links filter).
If Tab Share is useful to you, you can support development on Ko-fi:
Licensed under the GNU AGPL-3.0 -- free to use, study, share, and modify, but
any modified version you distribute or run as a network service must be offered
under the same license with source available. Bundles lz-string (MIT) -- see
docs/THIRD-PARTY.md. Report security issues per
docs/SECURITY.md.





