Natively and easily edit and open bookmarks in multi-account containers.
This extension works well with both Temporary Containers on the Mozilla-Addons-Store and Temporary Containers Plus on the Mozilla-Addons-Store.
Pick the folder each time you bookmark (optional)
Turn on Ask where to save each time in the options page, and the bookmark button opens a small folder picker. Edit the name, pick any folder (your target folder is preselected), and press Save or Enter. The bookmark still opens in the container you saved it from.
ContainMarks attaches a one-time code (a token) to all assigned bookmarks. This ensures only bookmarked pairings open in the assigned container.
If you experience any issues with stale tokens, the extension preferences page (read more below) may be able to help.
ContainMarks works with Firefox Sync / bookmark transfer methods.
- We do not collect ANY information from you, everything is stored locally.
- There are no terms of service, use as you please. Do respect the License file, however.
- Be kind to others. This rule will be enforced by owner of this repository, at their discretion.
Test your code well before submitting it.
Using the Nix development shell (recommended in this repo), generate a Firefox extension package:
nix develop -c npm install
nix develop -c npm run build:firefoxOr without Nix (if node and npm are already installed):
npm install
npm run build:firefoxThis writes dist/*.zip (the standard WebExtension build artifact). For a local unsigned .xpi file:
nix develop -c npm run build:firefox:xpinix develop -c npm test # unit tests (Vitest, mocked browser APIs)
nix develop -c npm run test:live # real Firefox, driven over MarionetteThe live tests start a throwaway Firefox (vanilla, from nixpkgs) on a private Xvfb display, load src/ as a temporary add-on, and click real UI with xdotool. Pages are local fixtures, so no network is needed. The tests are in tests/live/; the harness is firefox-addon-live, a flake input that nix develop links in as an npm dependency.
nix develop -c npm run capture:readme # every scene
nix develop -c npm run capture:readme -- picker target # only some scenesThis rebuilds the add-on, replays each usage scene in a live Firefox, and writes a PNG still and a GIF per scene to product-page/ (640 px wide; the settings scene is taller so the whole page shows). Scenes are in scripts/capture-readme-assets.ts.
When a bookmark is assigned to a container, it receives a random token and a stable container index. The assignment is embedded in the URL's fragment, so the real URL remains intact and navigable.
E.G. https://example.com -> https://example.com#cm:r4nD0Mt_k3n:4
If the original URL already had a fragment (e.g. https://example.com#section), it is preserved after the encoding:
https://example.com#cm:r4nD0Mt_k3n:4#section
The number is the stable, first-seen container mapping index.
This token is hidden when the user goes to edit the bookmark. It is hotswapped back in when the bookmark is saved. This makes native bookmark editing possible without exposing the internal workings of the extension or requiring users to not mess with the token in the URL. This is a slight oversimplification, but this is ~90% correct. Read the code for the full details.
ContainMarks stores container mapping bookmarks in the Bookmarks Menu under ContainMarks Sync.
- Folder location:
Bookmarks Menu(menu________) - Mapping bookmark title:
Mapping: {containerName} - Mapping bookmark URL:
about:{firstSeenIndex}:{cookieStoreId}:{backupName}
This keeps container references stable across renames and helps sync behavior across devices.
Token retention behavior is configurable in the options page:
Regenerate tokens on startuptoggleRegenerate tokens on every usetoggle
The page-action shortcut always creates a bookmark for the current tab URL.
- If the tab is in a container, the bookmark is container-mapped.
- If the tab is not in a container, a plain bookmark is created.
- With
Ask where to save each timeon, the button opens a folder picker popup first. The picker preselects the target folder; Firefox's own star button and Ctrl+D are left alone.
src/backgroundApp.ts: event orchestration (startup, tab update handling, context menus, page-action flow)src/containerMappingStore.ts: stable index mapping + bookmark-backed sync persistencesrc/containerMappings.ts: URL codec for bookmark and mapping formatssrc/settings.ts: settings sanitization, validation, and storage boundaries
This separation keeps encoded URL rules and sync mapping persistence independent from browser event wiring.
All code is licensed under the MIT License.
Because innovation is desirable.





