Home (All Topics) → Technology → Software → AI-Created Software
The following is AI-generated (aka vibe-coded) software. The software is specific to my needs and my system and may not work for you or your system. Support is limited, but if you report a bug I'll certainly look into it. All code is provided in a zip file for you to review should you choose.
A Chrome extension for handling link dumps. Copy a block of text, click the toolbar icon, see every link it contains, and decide what happens to them: open as tabs, save to a dated bookmarks folder, or push to the reading list. It also works in reverse — copy your open tabs back out to the clipboard.
Useful when someone sends you twenty links in a chat message, an email, or a spreadsheet column.
Preview before anything opens. The popup lists every link it found, with a checkbox on each. Untick the ones you don’t want.
Nothing opens until you say so.
Opens in batches. Tabs are created five at a time with a short pause between batches, so a long list doesn’t hit the network all at once. Both numbers are configurable.
Asks twice above a threshold. Past 15 selected links (adjustable), the open button needs a second click.
Local network links start unticked. Links to localhost, 192.168.x.x, 10.x.x.x and other addresses on this computer or your network are marked local network and left unticked, so a page can’t use a copy or a selection to make your browser poke your router or a dev server. Tick them to open them, or turn this off in the options.
Three destinations. Open as tabs, save to a timestamped bookmarks folder under Other bookmarks, or add to Chrome’s reading list.
Copies your tabs out. One click puts every web URL in the current window on the clipboard, either as a plain list or as Markdown links with page titles.
Works without the popup. Keyboard shortcuts and a right-click menu item cover the cases where opening the popup is the slow part. They open links straight away only when there are no more than the threshold and none are local; otherwise the popup opens with the list so you can check it first.
Cleans links up. Trailing punctuation is trimmed, so https://example.com, in a sentence doesn’t become a broken URL, and utm_source, fbclid, gclid and similar tracking parameters are stripped by default. Links that differ only by www., a trailing slash, or host capitalisation are treated as one.
chrome://extensions.manifest.json.Requires Chrome 127 or later. The reading list needs Chrome 120+, and chrome.action.openPopup() — used as a fallback when a shortcut can’t reach the clipboard — needs 127. On a Chromium browser without the reading list API, that button hides itself rather than failing.
Copy some text, click the icon. The popup reads the clipboard as it opens and shows what it found. Tick and untick, then choose Open tabs, Bookmark, or Reading list.
If Chrome blocks the clipboard read, the popup says so and opens a textarea instead — paste there and click Scan this text. That panel is always available under Paste text instead, so you can also scan text you never copied.
| Shortcut | Action |
|---|---|
Alt+Shift+V |
Open the popup |
Alt+Shift+O |
Open every link on the clipboard, skipping the preview unless there are more than the threshold or any local links |
Alt+Shift+C |
Copy this window’s tab URLs to the clipboard |
The last two never show the popup. Since there’s nowhere to print a status line, they report through the toolbar badge: a count in blue for tabs opened, green for tabs copied, grey 0 when nothing was found, and amber ? if the clipboard couldn’t be read (which also opens the popup as a fallback).
Chrome reserves some combinations. Rebind anything that clashes at chrome://extensions/shortcuts, reachable from the options page.
Select text on any page, right-click, and choose Open links in selection. Nothing has to be copied first. As with the shortcut, a long list or one with local links opens the popup for a look instead.
The handler reads the live selection through chrome.scripting rather than trusting info.selectionText, which Chrome truncates on long selections. That’s legal without host permissions because a context-menu click grants activeTab for that tab. It keeps only text you can actually see: anything the page has hidden with zero opacity, a zero font size, a one-pixel clip box or off-screen positioning is left out, since a page can hide links in a paragraph you select.
Open with the gear in the popup, or from chrome://extensions. Everything saves as you change it.
| Setting | Default | Notes |
|---|---|---|
| Confirmation threshold | 15 tabs | Second click required above this |
| Keep current tab in focus | on | Off jumps to the first link after the batch finishes |
| Remove tracking parameters | on | Applies to opening and saving alike |
| Batch size | 5 tabs | |
| Delay between batches | 400 ms | 0 disables throttling |
| Copy tabs as | one URL per line | Or Markdown links with titles |
| Treat local network links like any other | off | On ticks local links and lets the shortcut and menu open them directly |
Settings use storage.sync, so they follow your Chrome profile across machines.
The options page can back up every setting, including the backup schedule itself, to a JSON file in your downloads folder.
| Setting | Default | Notes |
|---|---|---|
| Back up settings automatically | off | The schedule is checked hourly while the browser is open |
| Back up every | 7 days | |
| Earlier backups to keep | 3 | Kept in addition to the latest backup |
| Backup folder | Clipboard Tabber Backups | Inside the downloads folder, e.g. Backups/Clipboard Tabber; created if it doesn’t exist |
Retention counts calendar days. The latest backup is always kept.
Each earlier day that has backups keeps only its newest one and counts as one against the number to keep; days without a backup count as zero.
Other backups from the same day as the latest are deleted. For example, with backups on Monday (two), Wednesday, Thursday, Friday and Saturday and 3 to keep, Saturday’s is the latest and Wednesday, Thursday and Friday are kept; both Monday backups are deleted. Old backups are only removed after the new one has finished saving, and files you saved anywhere else are never touched.
Back up now saves a backup straight away.
Restore reads a backup file, shows what it holds and, once you confirm, replaces every setting and the backup schedule with the ones in the file. Settings missing from the file keep their current values.
The schedule and the time of the last backup are kept in storage.local, since backups go to this machine’s downloads folder.
clipboard-tabber/
├── manifest.json Permissions, commands, popup and options registration
├── lib.js Shared: settings, URL extraction, opening, saving, backups
├── background.js Service worker: context menu, shortcuts, badge, scheduled backups
├── offscreen.html Clipboard host for the service worker
├── offscreen.js Clipboard read/write via execCommand
├── popup.html Popup markup
├── popup.js Popup logic: preview, actions, status
├── options.html Options markup
├── options.js Options logic: auto-save, clamping, reset, backup and restore
├── styles.css Shared styles, including dark mode
├── test_backup.mjs Tests for the backup schedule and files (node test_backup.mjs)
├── test_links.mjs Tests for spotting local network links (node test_links.mjs)
└── icons/
├── icon16.png
├── icon48.png
└── icon128.png
A few things that aren’t obvious from reading the source.
Tabs are always created inactive. Creating an active tab closes the popup, which would kill the loop partway through and lose every remaining batch. When “keep current tab in focus” is off, the extension still creates everything in the background and activates the first tab only after the run completes.
The service worker borrows a clipboard. MV3 service workers have no DOM, so navigator.clipboard doesn’t exist there. The shortcut handlers spin up an offscreen document, ask it to read or write, and close it again. The offscreen document uses document.execCommand rather than the async clipboard API, because an offscreen document is never focused and the async API requires focus.
Bookmark folder lookup is defensive. It prefers the node with folderType === 'other', falls back to the well-known id '2', and then to the last root child, rather than hardcoding an id that varies across Chromium forks.
Reading list entries need a title before the page has ever loaded, so the extension synthesises one from the host and path. Adding a URL that’s already on the list throws; those are counted as skipped and reported rather than aborting the batch.
The shortcut and menu hand off to the popup through storage.session. When a run needs a look, the service worker saves the text there, puts the link count on the badge and calls chrome.action.openPopup(). The popup takes the text on its next open, as long as it is under ten minutes old. Content scripts can’t read session storage.
Messages are checked for their sender. The offscreen document only answers the service worker, and the service worker only starts a backup for the extension’s own pages, so text running in a web page can’t read the clipboard or start a download through them.
Deduplication is normalised, opening is not.www. and trailing slashes are ignored when deciding whether two links are the same, but the URL that actually opens is the one that was on the clipboard, minus tracking parameters.
| Permission | Why |
|---|---|
clipboardRead |
Read the copied text |
clipboardWrite |
Write the tab list back out |
tabs |
Read tab URLs and titles for the copy-out feature |
bookmarks |
Create the dated folder |
readingList |
Add entries to the reading list |
storage |
Save settings |
contextMenus |
The right-click item |
activeTab + scripting |
Read the live text selection on context-menu click |
offscreen |
Give the service worker clipboard access |
alarms |
Check the backup schedule hourly |
downloads |
Save backups to the downloads folder and delete old ones |
No host permissions are requested. The extension can’t read or modify any page you visit; the only page code it ever runs is a selection read, on the tab you right-clicked, at the moment you right-click it.
http:// and https:// links. Bare example.com and www.example.com are ignored, as are mailto: and ftp:.href attributes — copying styled links out of a document — aren’t seen unless the URL is also visible as text.google.com/url?q= links aren’t unwrapped, so you land on the tracker’s redirect rather than going straight to the destination.chrome.action.openPopup() fails when a shortcut or menu run needs a look, the link count stays on the badge in orange; click the toolbar icon to see the list.Alt+Shift+O depends on the offscreen clipboard read. If Chrome refuses it, the extension opens the popup instead of failing silently, which costs you a click.
Backups land in the downloads folder as download.json Another extension that renames downloads is overriding the backup’s name. Chrome forgets the name an extension asks for whenever any extension renames downloads, so that extension has to put it back. Download Router does this; for others, turn them off or check their settings.
2.2 — The shortcut and right-click menu show the popup instead of opening links when there are more than the threshold or any local network links. Local network links start unticked in the popup. The right-click menu ignores selected text the page has hidden.
The clipboard and backup handlers only answer the extension itself.
2.1.1 — Backups keep their folder and name when Download Router or another extension that renames downloads is installed, and Clipboard Tabber no longer stops Download Router’s rules from working.
2.1 — Scheduled backups of every setting, with a frequency in days, a number of earlier backups to keep counted by calendar day, and a folder inside Downloads; Back up now and Restore on the options page.
2.0 — Preview step with per-link checkboxes; batched opening; bookmarks and reading list destinations; copy window tabs to clipboard; keyboard shortcuts; selection context menu; manual paste fallback; options page; tracking-parameter stripping; dark mode.
1.0 — Read clipboard, open every link found.


Leave a Reply