Chrome extension that supercharges Google Gemini with completion notifications, scroll control, a floating timeline, side-panel shortcuts, and other productivity boosts.
- Features
- Installation
- Usage Guide
- Technical Architecture
- Core Implementation Notes
- Permissions
- Manual Testing
- Changelog
- License
- Third-Party Libraries
| Feature | Description |
|---|---|
| 🔊 One-click Read Aloud | Injects a speaker icon beneath each message so Gemini’s native text-to-speech plays without digging through menus. |
| 📅 Conversation Timeline | Floating panel that lists every user prompt and AI reply; click any entry to jump there instantly. |
| 🌓 Dark Mode Ready | Adapts to system theme so the timeline panel and injected UI look crisp in both modes. |
| 🔔 Completion Notifications | Sends desktop notifications only after a genuine completion; toggles persist immediately in storage and apply to future sessions. |
| 🛑 Auto-scroll Blocker | Prevents Gemini from forcing the thread to the bottom during generation and restores the Visibility API when turned off. |
| 🔒 Quick Toggle | Floating button that switches the scroll interceptor on/off (🔒 enabled / 🔓 disabled). |
| ⬇️ Jump to Bottom | Smoothly scrolls to the latest response using the detected scroll container. |
| 🖼️ Side Panel Support | Opens Gemini in the Chrome side panel with every enhancement still active. |
| 🔄 Side Panel Refresh | Adds a hover refresh control in the iframe so you can reload Gemini without browser chrome. |
| 👻 Background Throttle Guard | Overrides the Page Visibility API to stop Chrome from throttling Gemini when hidden. |
| ⚡ Maximum Performance | Blocks only programmatic scrolling, keeping manual wheel/keyboard input untouched. |
| 📝 Markdown Repair | Bundles markdown-it to fix **bold** rendering during streaming output and smart quotes. |
| ⚙️ Per-feature Settings | The Options page lets you toggle each module independently. |
| 🧠 Default Mode Picker | Automatically switches Gemini to your preferred mode (Fast / Thinking / Pro) on every page load and SPA navigation. |
| 🏷️ Dynamic Tab Titles | Locks the real [data-test-id=”conversation-title”] into the browser tab so it never resets to “Chats.” |
| 🧺 Bulk Chat Delete | Batch select and delete multiple conversations from the sidebar at once with an automated cleanup controller. |
- Clone or download this repository.
- Open Chrome and visit
chrome://extensions/. - Enable Developer mode in the top-right corner.
- Click Load unpacked.
- Select the project root directory.
Install the extension and open gemini.google.com; everything activates automatically.
- A floating panel on the right lists every user prompt and Gemini reply.
- Click any entry to scroll smoothly to that message and highlight it.
- Badges: 🟢 U (green) = user prompts, 🔵 ✦ (blue) = Gemini responses.
- Tap the panel header to collapse or expand it.
- Automatically adapts to light/dark themes.
- Click the extension icon to open Gemini inside Chrome’s side panel.
- A floating refresh button sits at the top-right of the iframe for quick reloads.
- The side panel keeps scroll blocking, notifications, and all other enhancements.
- Note: The in-page timeline hides inside narrow side-panel layouts, so rely on Chrome’s native list there.
Right-click the extension icon → Options:
- Block automatic scrolling: toggles the scroll interceptor. Turning it off restores native visibility behavior to save power.
- Completion notifications: toggles desktop alerts triggered only after real completions. The preference writes to storage immediately; refresh Gemini tabs for instant effect if needed.
- Default mode: choose Off / Fast / Thinking / Pro. When set, the extension auto-selects that mode on every page load and when navigating between Gems.
- Hover over the conversation sidebar to reveal the Bulk Delete Toolbar.
- Click checkboxes on individual rows or use Select visible to mark the chats currently visible in the sidebar.
- Click Delete Selected to start the automated cleanup process. The helper will walk through each chat, opening its menu and confirming deletion for you.
Built on Manifest V3 plus modern Chrome APIs:
graph TD
User[User Actions] --> Options[Options Page]
User --> SidePanel["Side Panel (iframe)"]
subgraph Chrome Extension
Options -->|Open| SidePanel
Options -->|Sync settings| Storage[Chrome Storage]
Background[Service Worker] -->|webRequest| API["Gemini API Calls"]
Background -->|Notify| Notifications[System Notifications]
Background -->|DNR Rules| Network[Network Overrides]
subgraph Content Scripts
Injector["injector.js (Isolated World)"]
ScrollBlocker["scroll-blocker.js (Main World)"]
end
end
subgraph Gemini Page
Injector -->|DOM observers| MutationObserver
Injector -->|Timeline UI| TimelineUI["Timeline Panel"]
ScrollBlocker -->|Intercept| ScrollAPI["Native Scroll APIs"]
ScrollBlocker -->|Override| VisibilityAPI["Visibility API"]
end
Storage -->|Setting changes| Injector
Injector -->|Messages| ScrollBlocker
Network -->|Remove headers| CSP["X-Frame-Options / CSP"]
- Main-world injection (
scroll-blocker.js) usesworld: "MAIN"plusall_frames: trueso it can redefinewindow.scrollTo,Element.prototype.scrollIntoView, and the Visibility API even inside side-panel iframes. - Side panel + DNR uses
chrome.sidePanelto pin Gemini whiledeclarativeNetRequestremovesX-Frame-Options/CSP headers for extension-initiated frames only. - Markdown repair relies on
markdown-itwithrequestIdleCallbackscheduling to keep long chats smooth.
background.jstracks in-flight Gemini requests viachrome.webRequest, gating completion notifications with duration thresholds and tab-focus checks.injector-shared.jsholds shared selectors/utilities,injector-timeline.jsowns timeline rendering/scanning,injector-title-mode.jsmanages tab title/default mode behavior, andinjector.jskeeps the main content-script orchestration.scroll-blocker.jsoverrides scroll APIs and toggles Page Visibility overrides based on the scroll setting.- Notification gating is request-driven and keyed by
tabId + frameId, soall_framesdoes not let one Gemini frame clobber another frame's generation state. - Content-script work is frame-aware: heavy UI, title, and mode logic run only in the primary Gemini frame; timeline and selector logic prefer structural DOM hooks and use text-based selectors only as fallback.
- Shared constants live in
constants.js, whileinjector.csscentralizes styling so Chrome loads a single stylesheet.
notifications: display desktop alerts when completions finish outside the tab.storage: persist per-feature settings.tabs: inspect Gemini tabs before showing notifications and reactivate the right Gemini tab from a notification.sidePanel: register Gemini inside Chrome’s side panel.declarativeNetRequest: enable the bundled static ruleset inrules.json.declarativeNetRequestWithHostAccess: allow that ruleset to modify response headers on the Gemini endpoints used by the side panel iframe.webRequest: monitor Gemini API calls for completion detection.
Host permissions: https://gemini.google.com/*, https://alkalimakersuite-pa.clients6.google.com/*.
The extension only targets Gemini surfaces. The secondary Google host permission is required because Gemini generation traffic and frame responses can originate from alkalimakersuite-pa.clients6.google.com, which is also the endpoint affected by the side-panel header overrides.
Use TESTING.md for a focused post-change regression pass covering scroll blocking, notifications, timeline, side panel, default mode, and settings persistence.
Current test status:
- Manual regression coverage exists in
TESTING.md. node scripts/smoke-test.mjsprovides an automated smoke check aroundweb-ext lint.- No automated browser test suite is included today.
- No Playwright, Puppeteer, or Selenium harness is configured in this repository today.
Key maintenance checks after Gemini UI changes:
- Verify notifications still fire from real
batchexecute/StreamGeneratecompletions. - Verify timeline still prefers
[data-message-author-role]messages before fallback selectors. - Verify mode switching still finds the visible mode trigger and mode options without relying on a single
data-test-id.
- 🎨 Refined the extension UI system across Options, side panel, timeline, and floating controls for a cleaner, more consistent product feel.
- 🧭 Simplified the side panel chrome to avoid duplicate in-panel headings and preserve more room for Gemini itself.
- 🗑️ Polished bulk-delete status messaging and action styling for clearer feedback during multi-chat cleanup.
- ✨ Added Sidebar Bulk Delete: Introduces a powerful controller to batch-select and delete multiple conversations from the Gemini sidebar.
- 🧺 New Batch Toolbar: Floating action bar at the top of the conversation list with multi-selection and automated deletion flow.
- 📦 Selector Update: Refined
injector-shared.jswith comprehensive sidebar, menu, and dialog selectors to support automated interactions.
- 🏷️ Refined Tab Title Manager: Added route-aware fallback titles (e.g., "Settings", "New Chat") and improved navigation sync to clear stale title caches.
- 🖼️ Updated Side Panel: Changed the default landing page to
gemini.google.com/app(New Chat) for a cleaner start.
- 🧠 Added default mode picker: auto-select Fast / Thinking / Pro on page load and SPA navigation.
- ⚙️ New "Default mode" dropdown in the Options page.
- 🔄 ModeSwitcher watches URL changes for seamless Gem switching.
- 🎨 Unified glassmorphism styling across Options, Side Panel, floating buttons, and timeline with automatic theme sync.
- 🧭 Smoother side-panel feel with blurred refresh control, synced iframe background, and richer dark gradients.
- 🔕 Removed the “Gemini is AI and can make mistakes.” disclaimer and added
data-gemini-helper-hiddenguards so it stays hidden. - 🔊 Restored the read-aloud button for Gemini’s updated toolbar layout.
- 🏷️ Tab titles now prioritize
[data-test-id="conversation-title"]and fall back to the first user prompt as a backup.
- 🧭 Disabling “Block automatic scrolling” now restores the Visibility API immediately so Chrome can throttle hidden tabs.
- 🔕 Removed the unused
TOGGLE_NOTIFYmessage from Options to avoid console noise. - 📋 Documentation updated to reflect these fixes.
- 🧭 Added a “generation state gate” so notifications never misfire when Chrome starts or a tab resumes.
- 🔔 Notifications fire strictly after confirmed completions to avoid background false positives.
- 🔔 Disabling notifications fully suppresses auto alerts and
SHOW_NOTIFYmessages. - 🧭 Scroll-blocker toggles propagate instantly to all open Gemini tabs.
- 📝 Markdown repairs keep applying to live streaming additions.
- 🧹 Added
G_CONSTANTSfor shared keywords and thresholds. - ⚡
MarkdownPatcherusesrequestIdleCallbackto avoid long-thread jank. - 🎨 Prefixed every injected DOM ID with
gemini-helper-for CSS isolation. - 🐛 Restored automatic timeline hiding in narrow or side-panel frames.
- 🔇 Demoted context warnings to debug logs.
- 🔒 Patched a potential XSS vector inside
TimelineUIby usingtextContentonly. - 🛡️ Improved timeline filtering and null guards.
- ⚡ Optimized
findScrollContainerto reduce layout scans. - 📝 Finished English localization for comments/logs and removed dead code.
- 🚀 Delivered the performance + memory roadmap goals.
- ⚡ Limited
MutationObserverscope to themaincontainer to reduce streaming overhead. - 🧠 Added automatic cleanup for request logs in the service worker.
- 🛡️ Consolidated all v1.7.x context-protection patches into stable.
- 🛡️ Fixed crashes from “Extension context invalidated.”
- 🛡️ Added background fallbacks for
Message port closederrors. - 🎨 Standardized floating buttons at 48px.
- 📅 Timeline defaults to an icon to reduce overlap.
- ⚡ Markdown patches DOM ranges in place for better performance.
- 🏷️ Improved tab-title detection reliability.
- ✨ Added the one-click read-aloud button with Material Outlined styling.
- 🎨 Tuned alignment to match Gemini’s layout.
- 🛡️ Hardened DOM injection to prevent duplicate buttons in complex layouts.
- ✨ Added dynamic tab titles that lock the conversation name in Chrome.
- 🛠️ Prevented the site from resetting titles back to “Chats.”
- ✨ Added the timeline navigation panel with dark-mode support and gradient badges.
- ⚡ Optimized the timeline scanner and introduced
_findUserNeighbor. - 🐛 Fixed user/AI ordering mix-ups and recovered missing final prompts.
- 🧹 Refactored
TimelineScannerfor readability.
- ✨ Added the floating scroll-toggle button (🔒/🔓).
- 🐛 Fixed intermittent scroll-blocker failures.
- ⚡ Always intercept programmatic scrolling regardless of interaction state.
- 🧹 Removed legacy debug code to slim the bundle.
- 🔔 Improved background notification reliability with
webRequesthooks. - 👻 Added Page Visibility API overrides.
This project is licensed under the MIT License.
- markdown-it (MIT) — resilient Markdown rendering and patching engine.