繁體中文版請見 README.md.
A Chrome MV3 extension that uses AI to automatically analyse and group tabs. Supports OpenRouter, OpenAI, and Google Gemini — call your model of choice (Claude, Gemini, GPT, etc.) — and clusters related tabs into the same Chrome tab group based only on tab title, hostname, and up to 80 characters of the URL path. Tab content is never read; query strings and URL fragments are never transmitted.
chrome.storage.sync; task snapshots live only in chrome.storage.local. Nothing routes through a developer-operated servertabIds must be in the whitelist, group names cannot be empty, each group must contain at least 2 tabsnpm install
npm run build
The build emits the unpacked extension under dist/. Open chrome://extensions, enable Developer mode in the top-right corner, click Load unpacked, and pick the dist/ directory.
npm run zip
Produces tabby-grouper.zip in the project root, ready for upload to the Chrome Web Store or for distribution.
chrome.storage.local and is never transmitted to OpenRouter or any third party.chrome.storage.local (not synced, not uploaded). Disabling the toggle stops both the recording and the summarisation calls immediately; existing on-device data is preserved.npm run dev # Vite dev mode
npm run type-check # TypeScript type-check
npm run test # Vitest unit tests
npm run gen:icons # Regenerate icons in all sizes from the source image
Stack: Vite + @crxjs/vite-plugin + plain TypeScript, no UI framework.
src/
├── background.ts # Service worker: handle messages, call APIs, create groups, register tabGroups listeners
├── lib/
│ ├── openrouter.ts # AI provider (OpenRouter / OpenAI / Gemini) calls and output validation
│ ├── grouping.ts # Shared helpers: pickColor, isGroupableTab
│ ├── tasks.ts # Task type, storage key constants, retention/capacity caps
│ ├── storage.ts # chrome.storage.local reads/writes, CAS lock, lazy prune
│ ├── groupSync.ts # group↔task map rebuild, pendingResume detection, name/color sync
│ ├── resume.ts # Task restore algorithm
│ ├── userPrefs.ts # Personalised memory: sample collection + LLM distillation (gated by opt-in flag)
│ ├── messages.ts # background ↔ popup message types (discriminated union)
│ ├── *.test.ts # Vitest unit tests
├── popup/ # Toolbar popup UI (Group / Tasks views)
└── options/ # Options page (API key, model, dragged-tab policies, personalised memory)
maxlength attribute and by a guard at the entry of classifyTabs / reclassifyTabs.max_tokens: 2048 to avoid wasted tokens from runaway model output.isGroupResultShape and filtered through the validIds whitelist, so the worst case is a manipulated group name — no arbitrary code execution and no data exfiltration (the API key only ever appears in HTTP headers, never in the prompt).See CHANGELOG.md.
See PRIVACY.md. In short:
github.com/anthropics/courses/co…). Query strings and URL fragments are always stripped and never transmitted.chrome.storage.local and are never uploaded; archived tasks are auto-removed after 7 days, and you can delete any task manually at any time.