Skip to content

v1.0.0: rule-based dedup, tab groups, settings sync, new UI - #9

Open
jontsai wants to merge 5 commits into
masterfrom
feature/v1-rewrite
Open

jontsai wants to merge 5 commits into
masterfrom
feature/v1-rewrite

Conversation

@jontsai

@jontsai jontsai commented Sep 29, 2026

Copy link
Copy Markdown
Member

Summary

A ground-up rewrite of the extension while keeping it vanilla JS with no build step and no dependencies. Fixes the long-standing bugs, adds entity-aware deduplication, respects pinned tabs and tab groups everywhere, and adds a real settings page with sync, export/import and remote rules.

Bugs fixed

  • Bring All Windows To Front never worked. The action entry lacked callback: and the handler reassigned a const.
  • Popup died mid-action. The popup ran the tab logic itself; Chrome closes the popup the moment a window is created or focused, killing the promise chain. All logic now runs in the service worker and the popup only sends messages.
  • Collate raced its own cleanup. N parallel windows.create calls each ran a global blank-tab sweep that could close a sibling window before its tabs arrived. Windows are now created sequentially.
  • Sort and collate mangled pinned tabs. Pinned tabs are never moved by any action now.
  • Dedupe kept an arbitrary copy. It now keeps pinned, then active, then the most recently viewed tab.
  • Removed Bootstrap (160 KB for 8 buttons), the <srript> typo, and the missing jQuery reference.

Features

  • Duplicate rules. URLs that differ but mean the same page collapse to one key: PR subpages (GitHub, Bitbucket, GitLab), Jira issue forms, Confluence, LinkedIn profile tabs, Google Docs edit/view, Notion slugs, YouTube short links, HubSpot records, Slack threads, Figma, Amazon, Stack Overflow, Reddit, X. 19 built-in rules, all user-editable JSON with a live URL tester.
  • Auto-deduplicate (opt-in): opening a link that is already open closes the new tab and focuses the existing one.
  • Close Tabs Like This One: same domain, same site section, or same kind of page, with preview and a keep-current toggle.
  • Tab groups: Group by Domain (native groups), Ungroup, and sort that keeps groups contiguous. Consolidate and Split move whole groups between windows and merge into a same-named group in the destination.
  • Memory relief: Close Stale, Free Memory (discard), Park Window to Bookmarks, Restore Last Parked.
  • Safety: preview list before any close from the popup; Undo for the last close.
  • Settings page: chrome.storage.sync with local fallback, JSON export/import, optional remote rules URL refreshed on a schedule.
  • Keyboard shortcuts for every action, duplicate-count badge, context menu grouped into sections, proper icon sizes, light and dark themes, inline help.

Testing it locally

git fetch origin && git checkout feature/v1-rewrite
make test     # 21 unit tests for URL normalization, rules, dedup, sort order
make e2e      # 36 checks in a real headless Brave: every action, undo, auto-dedupe, group merge
make dev      # opens a throwaway Brave profile with the extension and two windows of sample tabs

make dev seeds tabs that hit every rule (PR subpages, LinkedIn profile pages, YouTube short link, Stack Overflow /q/, wikipedia with utm/fragment/http) plus blank tabs, so you can click through Deduplicate, Close Tabs Like This One, Group by Domain, Sort, Consolidate and Split and watch what happens. The profile persists between runs; make dev-clean removes it. BROWSER=/path/to/chromium make dev picks another browser. Google Chrome's branded build no longer honours --load-extension, so for your real Chrome profile use chrome://extensions → Load unpacked.

Things worth checking by hand in your real profile:

  • Sort a window that has pinned tabs and a couple of groups.
  • Consolidate All with a group of the same name in two windows: they should merge.
  • Turn on auto-dedupe in Settings, then open a PR link you already have open.
  • Export settings, then import them on another profile.

Layout

src/background.js      service worker: message router, context menus, shortcuts, auto-dedupe, badge
src/lib/url.js         pure URL logic (tested)
src/lib/settings.js    storage.sync persistence, export/import, remote rules
src/lib/actions.js     action registry and everything that touches the tabs API
src/popup.*            toolbar popup
src/options.*          settings page
test/url.test.js       node --test
scripts/e2e.mjs        headless browser test over the DevTools protocol
scripts/dev.mjs        dev profile launcher

Screenshots

Popup Preview before closing Inline help
popup preview help

🤖 Generated with Claude Code

jontsai and others added 3 commits September 29, 2026 15:44
Architecture
- All tab operations now run in the module service worker; the popup only
  sends messages. Previously the popup ran the logic itself and was killed
  as soon as an action created or focused a window.
- Pure URL logic (normalization, entity rules, duplicate detection, sort
  order) lives in src/lib/url.js with a node --test suite.
- scripts/e2e.mjs drives a real headless Brave/Chromium over the DevTools
  protocol and exercises every action (make e2e).

Fixes
- "Bring All Windows To Front" never worked: the action entry lacked a
  callback and the handler reassigned a const.
- Collate raced its own blank-tab cleanup and could close a window before
  its tabs were moved in. Windows are now created with their first tab,
  sequentially.
- Sort and collate mixed pinned tabs into the sort order; pinned tabs are
  now never moved and tab groups stay contiguous and sorted by name.
- Dedupe kept an arbitrary copy; it now keeps pinned, then active, then
  the most recently viewed tab.
- Removed Bootstrap (160 KB) and the missing jQuery reference.

Features
- Duplicate rules: URLs that differ but mean the same page (PR subpages,
  Jira issue forms, LinkedIn profile tabs, Google Docs edit/view, Notion
  slugs, YouTube short links and 12 more) collapse to one key. Rules are
  user-editable JSON with a live tester.
- Auto-deduplicate new tabs (opt-in): opening an already-open link closes
  the new tab and focuses the existing one.
- Close Tabs Like This One: pick same domain, same site section, or same
  kind of page, with a preview and a keep-current toggle.
- Group Tabs by Domain using native tab groups; Ungroup; Close Stale;
  Free Memory (discard); Park Window to Bookmarks and Restore Last Parked.
- Preview list before any close from the popup, and Undo for the last
  close in the session.
- Settings page: preferences and rules in chrome.storage.sync with local
  fallback, JSON export/import, and an optional remote rules URL refreshed
  on a schedule. Inline help in the popup and a help section in settings.
- Keyboard shortcuts for every action, duplicate count badge, context menu
  grouped into sections, proper icon sizes, light and dark themes.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Moving a tab to another window drops it from its group. Consolidate and
Split now move whole groups with tabGroups.move, merge into an existing
group with the same name in the destination, and rebuild the group when
only part of it moves or the browser cannot move groups across windows.

Also adds `make dev`, which launches a throwaway browser profile with the
extension loaded and two windows of sample tabs, and extends the e2e
suite with group-merge and split assertions.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Dev and e2e browser profiles now live under ~/.holodeck, the designated
throwaway sandbox. The dev profile is named in the browser so every window
shows where you are. AGENTS.md documents the architecture rules, tests and
the holodeck for contributors and AI agents; CLAUDE.md imports it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
jontsai and others added 2 commits September 29, 2026 21:31
The e2e job installs Chrome for Testing with @puppeteer/browsers into the
holodeck and runs the suite headless. The script now identifies the
extension by manifest name, since browsers ship built-in extensions with
service workers of their own, and adds container-friendly flags under CI.
Verified locally on Chrome for Testing 154 and Brave.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
zip ships with macOS and the CI runners, 7z does not. The package job
uploads organize_tabs-<version>.zip as a workflow artifact after the unit
and e2e jobs pass. The e2e script accepts EXT= to test an unzipped
package, which is how this build was verified.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant