CLI tool
josh-berry/tab-stash avatar
josh-berry/tab-stash

tab-stash: saving Firefox tabs as bookmarks you can restore later

Firefox extension to save and restore tabs as bookmarks. Clear your tabs, clear your mind.

1,098 stars77 forksTypeScriptMPL-2.0

At a glance

What is it?
Tab Stash is a Firefox extension that takes a batch of open tabs and stores them in your bookmarks as organised groups, so you can clear the browser and pick the session up again later, restoring a single tab or a whole group. The interesting part for developers is the build: a Make driven pipeline that also builds an experimental Chrome port, checks types, tests, style and translations, and packages for the Mozilla Add-Ons store.
Who is it for?
Tab Stash fits a Firefox user whose tab list is a filing problem rather than a memory problem, and who wants the saved state to live in something they already back up and can edit by hand. It does not fit a Chrome user, because the port is described as highly experimental and unpacked, and it does not fit a team that wants to distribute a patched build, which the author asks you not to do.
Can I use it commercially?
Yes, with conditions. MPL-2.0 is a weak copyleft licence: you can use it inside commercial and closed-source software, but if you distribute changes to its own files, you must publish those changes under the same licence.
Is it still maintained?
Yes. The repository last received commits 3 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The whole idea is one sentence long

The description of Tab Stash fits on a line: a Firefox extension to save and restore tabs as bookmarks, with the tagline about clearing your tabs and your mind.

The README puts the problem first. You cannot keep all your tabs straight, you need to clear your plate, but you want to come back to your tabs later. The answer is a no-fuss way to save and organise batches of tabs as bookmarks. You sweep the browser clean with one click of the Tab Stash icon, if it is configured for that, and your open tabs are stashed away in your bookmarks, conveniently organised into groups. When it is time to pick up where you left off, you open Tab Stash and restore just the tabs or the groups you want.

The design decision that follows from that is the interesting one, and it is the reason the project is worth an article. The saved state is not a proprietary database with an import and export format. It is your bookmarks, in folders, in the browser's own bookmark tree, which means the saved sessions are visible to you, editable by hand, and travel with the profile the way bookmarks do.

For a browser extension, that is an unusual choice. Most extensions of this kind invent their own storage and give you a list. Tab Stash uses the mechanism the browser already has, and the cost of that choice is that the organisation is expressed through folder names and bookmark titles rather than through a richer internal model.

The project is licensed under MPL-2.0, the primary language is TypeScript, and the homepage is a documentation site at josh-berry.github.io/tab-stash.

Firefox first, with a Chrome port that is called experimental

Tab Stash is a WebExtension, and the install route is the Mozilla Add-Ons store, which the README links as the way to try it.

The build output tells you about the platform support. There is a dist directory, which is the unpacked Firefox extension, and a dist-chrome directory, which is described as a highly experimental port to Chrome, also unpacked. A separate script in the repository, patch-manifest-for-chrome.js, exists to adapt the manifest for the other browser, which is the kind of work that makes a port experimental rather than finished.

The repository has the other artefacts of a serious extension project. There is a SECURITY.md, a CODE_OF_CONDUCT.md, a contributing guide in docs/, a .prettierrc.json with a plugin that organises imports, an .editorconfig, a .vscode directory, an AGENTS.md, and a set of helper scripts that reveal how the project is maintained: process-icon.js, resize-ff-devedition-for-screenshots.sh, issues-top-10.bash, check-i18n.js and missing-translations.md.

The dev dependencies are worth a second look, because they describe the architecture. The sidebar interface is a Vue 3 application, built with Vite 8 and the Vue plugin, and there are three separate Vite configs, one for the base setup, one for the HTML entry points and one for the library build, which is what a browser extension with a popup, a sidebar and an options page tends to need. The webextension-polyfill is there so the same code runs on browsers without the promise-based extension APIs. idb is a dependency, so IndexedDB is used for the extension's own internal state, while the user-facing saved sessions live in bookmarks. And web-ext is the tool for the Mozilla add-on workflow.

The last detail is the version number. The package manifest says version 0.1.0, but the Makefile reads the real version from assets/manifest.json, which is where a browser extension keeps it, and the npm version is just a placeholder for the workspace.

Building it takes a UNIX shell, GNU tools and Inkscape

The build instructions are unusually specific about the environment, and they begin with the constraint that matters most.

You need a UNIX-like system, a Mac or a Linux, to build Tab Stash. Building on Windows is not supported because of the multiple build steps involved, and the author says patches to make the build more cross-platform are welcome. So this is a project where a Windows contributor is a second-class citizen unless they are prepared to send a patch, which is a candid and reasonable thing for a maintainer to say.

Dependencies can be installed with the handy install-deps.sh script, which works automatically on supported systems, with the latest macOS and Ubuntu 22.04 known to work. Doing it by hand means GNU make, git, diff, patch, rsync and zip, plus the usual set of standard UNIX utilities, and Node.js with npm, either the latest Current or LTS release. The package manifest states the same requirement in machine readable form, with npm 9 or newer and node 20 or newer.

The third dependency is the one that catches people out. You need Inkscape version 1.0 or newer, with the command line available as inkscape in your PATH, and the README notes that Inkscape is known not to work when installed via snap, so on Ubuntu you should install it with apt-get instead. The icons are generated with it, which is why it is a hard requirement rather than an optional one.

bash
./install-deps.sh

A development build is one make, a release build is a ritual

Two commands, and the difference between them matters.

For a debug or development version you run make, and you can pass a -j argument for a parallel build.

bash
make

For a release version, for packaging or review, there are three steps. Your source tree must have no uncommitted changes, so git status should say nothing to commit, working tree clean. Then you check out the tag for the version you want to build, with the note that Mozilla reviewers can skip that step because the source bundle they receive already has the right tag checked out. Then you run make rel, again with -j if you want it parallel.

bash
git checkout <tag>
make rel

The outputs are four things. The dist directory holds the unpacked Firefox extension, and dist-chrome holds the unpacked experimental Chrome port. For release builds only, there is a packed extension zip named releases/tab-stash-X.XX-hhhhhhh.zip, which is what gets uploaded to the Mozilla Add-Ons site, and a source tarball named releases/tab-stash-src-X.XX-hhhhhhh.tar.gz, which is a clean checkout of the source tree and is also uploaded for review.

The version string in those file names is assembled by the Makefile from the manifest version, a dev tag if the commit is not tagged, the short commit hash, and a dirty tag if the working tree has changes. That is why the clean tree requirement exists, and it is worth remembering that a build with local modifications produces a differently named artefact rather than silently producing the same one.

The default target runs four checks before it builds

The Makefile's comment on the default target explains the design, and the design is good. The target is unrolled so that the things most likely to fail, and fastest to fail, fail first, and so that style issues can be automatically fixed.

So the debug target runs check-types, which is vue-tsc with no emit, then builds the debug and Chrome debug bundles, then runs check-tests, then runs check-style with a fallback that fixes the style and runs the build again, and finally check-i18n.

The individual checks are each worth knowing about. The test check runs mocha under c8 for coverage, which is why the repository has a .c8rc.json and a .mocharc.json along with a mocha-setup.mjs. The style check is prettier with a check flag, and the fix target is the same command with write. The i18n check is a small script, check-i18n.js, and the repository keeps a missing-translations.md file, which suggests the translation status of the interface is tracked as a file rather than left to a service.

The Makefile also uses the version variables to fail early, with explicit errors if the version or the commit cannot be determined, so a broken checkout stops the build with a clear message rather than producing an artefact with an empty name.

There is also a separate script for building for the Mozilla add-ons workflow, build-for-amo, which runs the dependency installation and then make rel, so the release path is one command for the maintainer even though it is several for a contributor.

Redistribution is welcome, with two conditions

The re-distribution section is short and has an unusual request in it, and the request is about trust rather than about law.

The author says you are more than welcome to re-distribute Tab Stash according to the terms of the licence, and that he is happy to work with you to make sure users have a great experience on your platform. Then the two requests.

The first is to only ship release packages built using make rel as the instructions describe, because debug builds may cause performance problems or include other changes that make for a poor user experience. The second is that if you need to patch Tab Stash, work with the author ahead of time to get the changes merged into a release, because the author cannot provide support to users running patched builds, and if a patch introduces a bug it causes a lot of headache for the user and only for the author to have to tell them to install the official version.

The reasoning in that second request is the interesting part. A patched build is a build the maintainer cannot see failing in the wild, with the fault attributed to them. That is the classic argument for asking distributors to work upstream, and it is a more honest version of the usual licence position, since MPL-2.0 permits modification and the author is asking for a courtesy rather than claiming a restriction.

The repository was last pushed to on 2026-10-07 and there are no GitHub releases, so the tagged versions referenced by the release instructions live in the repository's tags, and the artefacts themselves are what reach users through the Mozilla Add-Ons listing.

Editorial conclusion

Tab Stash fits a Firefox user whose tab list is a filing problem rather than a memory problem, and who wants the saved state to live in something they already back up and can edit by hand. It does not fit a Chrome user, because the port is described as highly experimental and unpacked, and it does not fit a team that wants to distribute a patched build, which the author asks you not to do. Verify three things before you build it: that you have a recent Inkscape on the path, since the icons are generated with it and the snap install is known not to work, that your tree is clean and checked out at a tag before you run make rel, because the release artefacts are named after the commit and a dirty tree produces a different file name, and that you are using the release build rather than a debug build, because the author asks redistributors to ship only what make rel produces.

Frequently asked questions

What does the Tab Stash extension do with my tabs?

It saves batches of open tabs into your bookmarks, conveniently organised into groups, so you can clear the browser with one click of the icon and later restore just the tabs or the groups you want. The saved sessions live in the browser's own bookmark tree rather than in a separate database.

How do I install Tab Stash?

From the Mozilla Add-Ons store, which the README links as the way to try it. It is a WebExtension, and the build produces a Chrome port as well, but that one is described as highly experimental and is also unpacked.

What do I need to build Tab Stash from source?

A UNIX-like system, since building on Windows is not supported because of the multiple build steps. You need GNU make, git, diff, patch, rsync and zip, Node.js with npm, and Inkscape 1.0 or newer available as inkscape in your PATH, which is known not to work when installed via snap. The install-deps.sh script handles the supported systems, with the latest macOS and Ubuntu 22.04 known to work.

How do I produce a release build of Tab Stash?

Make sure the tree is clean so that git status reports nothing to commit, check out the tag for the version you want with git checkout, and run make rel. That produces the unpacked dist and dist-chrome directories plus, for release builds, a packed releases/tab-stash-X.XX-hhhhhhh.zip for upload to the Mozilla Add-Ons site and a matching source tarball.

Can I distribute my own build of Tab Stash?

The MPL-2.0 licence permits it and the author welcomes it, with two requests: ship only packages built with make rel, because debug builds may perform badly, and if you need patches, get them merged upstream first, because the author cannot support patched builds and a bug in one still gets reported against the official version.

Official sources

  1. Issues
  2. josh-berry/tab-stash on GitHub
  3. License: MPL-2.0
  4. Project website
  5. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/josh-berry-tab-stash.svg)](https://hysenlabs.com/projects/josh-berry-tab-stash)

Was this useful?