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 that files downloads into subfolders automatically, based on where they came from and what kind of file they are. Set a rule like huggingface.co → Models or .pdf → Documents, and matching downloads land in that folder instead of the general pile.
Version 2.5.4. Manifest V3. Works in Chrome, Vivaldi, Edge, Brave, and other Chromium browsers.
Not published to the Web Store, so load it unpacked:
manifest.json, the HTML, JS and CSS files at the top level, with the icons in an icons subfolder beside them.chrome://extensions (or vivaldi://extensions).After editing any file, hit the reload arrow on the extension’s card.
Changes to background.js or rules.js need that reload; changes to the interface take effect the next time you open it.
Click the toolbar icon for the popup, or open the full page — right-click the toolbar icon and choose Options, or press Open full page at the bottom of the popup.
Both surfaces are the same interface, built from the same code, so anything you can do in one you can do in the other. The full page just has room to breathe: it shows all 50 activity entries instead of the most recent six, and it isn’t at risk of being dismissed when a file dialog opens.
Adding a rule. Fill in a source domain (huggingface.co), a list of file types (pdf, zip, tar.gz), or both, then a destination folder, and click Add Rule. The folder is relative to your browser’s download directory and is created on first use.
Editing. Click Edit on any rule.
The form fills in and the button turns green and reads Update Rule. Cancel Edit backs out.
Turning a rule off. The checkbox at the left of each row switches a rule on and off without deleting it. A disabled rule is dimmed, keeps its place in the list, and is skipped entirely when a download arrives — useful for testing which rule is responsible for something.
Deleting. The red X removes a rule immediately, with no confirmation.
Replacing same-name files. Each rule has a checkbox: Replace files with the same name. Off (the default) means a second download of report.pdf is saved as report (1).pdf. On means it overwrites the existing file — silently, with no prompt, and the old file does not go to the trash.
Useful for a daily export that always arrives under the same name; risky for everything else. Each rule shows its current mode underneath in the list.
The Recent activity list records the last 50 downloads and what the extension did with each: the file, the site it came from, where it was saved, and which rule matched — or No rule matched, which is usually the more useful entry when something didn’t get filed where you expected.
Entries store the source hostname only, never the full URL, along with the filename and destination path. Everything stays in chrome.storage.local. Record switches logging off (existing entries are kept until you clear them), and Clear empties the list. The log is never included in an export.
A rule can match on a source domain, on file types, or on both. Every enabled rule is tested in list order and the first one that matches wins.
github.com + zip routes only the zips from GitHub, and leaves everything else from GitHub alone.Domain matching compares the rule against the host name of the source URL and of the referrer URL, ignoring case. A rule for github.com matches github.com and any subdomain of it, such as objects.github.com. It does not match a site that only mentions the domain somewhere else in its address, such as evil.net/github.com/setup.exe or github.com.evil.net, so another site can’t drop a file into a folder you’ve set aside for a site you trust. That has consequences worth knowing:
hub.co does not match github.com.https://, *. or a port in the rule is ignored. A path after the domain, as in github.com/someorg, narrows the rule to addresses whose path starts with it.File types are matched against the end of the filename, so multi-part extensions like tar.gz work. Leading dots and case don’t matter: PDF, .pdf and pdf are the same thing. A filename literally called pdf, with no extension, is not a match.
Downloads that match nothing are left entirely alone, and disabled rules are skipped as though they weren’t there.
Subfolders work: AI/Models nests two levels deep. Before use, the folder string is cleaned up — backslashes become forward slashes, the characters : * ? " < > | are stripped, .. is removed so a rule can’t escape the downloads directory, and stray leading or trailing slashes are trimmed. If nothing survives that (a rule of .., say), the download is saved normally rather than to a broken path.
Export writes every rule to a JSON file named for the moment it was created, in local time:
download-router-settings-2026-09-06-143052.json
The file wraps the whole of the extension’s local storage:
{
"format": "download-router-settings",
"formatVersion": 2,
"exportedAt": "2026-09-06T18:30:52.114Z",
"settings": {
"rules": [
{
"id": "r-8fk21mq0",
"domain": "huggingface.co",
"extensions": [],
"folder": "Models",
"overwrite": true,
"enabled": true
}
]
}
}
Import opens a file picker, then shows what the file holds — how many rules, how many overlap with yours — before writing anything. Then choose:
The importer also accepts an export from any earlier version, a bare {"rules": ...} object, or a hand-written {"domain": "Folder"} map, so you can write a rule set by hand. Anything older is upgraded to the current shape on the way in.
Entries with no folder, or with neither a domain nor a file type, are skipped and reported in the summary rather than silently dropped.
Rules live in chrome.storage.local, which is per-profile and never synced. Export is how you move a setup to another machine, another browser, or a fresh profile.
Turn on Back up rules automatically and the extension writes the same export file on its own, into a backup folder inside your downloads folder:
Download Router Backups/download-router-backup-2026-09-06-143052.json
Backup folder — where backups go, relative to the browser’s downloads folder. It defaults to Download Router Backups, can be several levels deep (Backups/Download Router), and is created if it doesn’t exist. It’s cleaned up like a rule’s folder; if nothing is left, the default is used. Browsers only let extensions save inside the downloads folder, so a location elsewhere on disk isn’t possible.
Every n days — how often to back up, from 1 to 365. The extension checks once an hour whether a backup is due, so if the browser was closed when one fell due, it’s made within the hour of the browser opening again. Turning the schedule on makes the first backup straight away.
Keep n earlier backups — how many backups to hold on to besides the latest one. With 3, you have the latest backup plus the three before it.
Back up now — makes a backup immediately and applies the same cleanup.
Restore — puts back everything in a backup file.
See below.
Old backups are cleared only after a new one has finished saving. The count works in calendar days:
So with a keep of 3, backups on Monday (two), Wednesday, Thursday, Friday and Saturday leave you with Saturday’s plus Friday’s, Thursday’s and Wednesday’s; both of Monday’s go.
Cleanup counts backups in every folder, so after you change the backup folder, the ones in the old folder still count and are removed in turn. It only touches files the extension saved itself and that are still listed in the browser’s download history. Clearing download history leaves those older backup files on disk for good, and files you move, rename or export by hand are never deleted. Scheduled backups are skipped while there are no rules, so an empty setup never pushes out a good backup.
Restore is the counterpart to a backup. Where Import only brings in rules and lets you merge them, Restore puts back everything the file holds: it replaces your whole rule set, the backup schedule (on/off, frequency, keep count and folder), and the activity log’s Record switch. It accepts scheduled backups and Export files alike.
Pick a file and the extension shows when it was saved and what it holds before anything changes; then choose Restore or Cancel. Settings the file doesn’t have — an export from before scheduled backups existed has no schedule, for instance — are left as they are. The activity log itself is never touched.
Rules used to be stored as an object keyed by domain, which no longer works now that a rule can have no domain at all. Anything already in storage is converted to the new ordered-array shape the first time it’s read, and rewritten on install and on your next edit. Existing rules keep their folder and overwrite setting, come across enabled, and start with no file-type restriction, so routing behaves exactly as before. Old export files still import.
| File | Purpose |
|---|---|
manifest.json |
Extension metadata, permissions, icon declarations |
background.js |
Service worker; renames each download as it starts and records it, runs scheduled backups |
rules.js |
Shared model: rule shape, migration, matching, storage, log and backup helpers |
ui.js |
The interface — rule editor, backup, backup schedule and restore, activity log |
ui.css |
Styles for both surfaces |
test_rules.mjs |
Tests for matching, backup filenames and the service worker’s checks. Run with node test_rules.mjs |
popup.html |
Toolbar popup shell |
options.html |
Full-page shell |
icons/icon16.png, icons/icon32.png, icons/icon48.png, icons/icon128.png |
Toolbar, extensions page, and store sizes |
icons/icon.svg |
Icon source, for regenerating the PNGs |
downloads — required to watch downloads and change where they land. This is the whole point of the extension.storage — saves your rules and the activity log locally.alarms — wakes the extension once an hour to see whether a scheduled backup is due. The extension asks for no access to websites. The downloads API already reports each download’s source and referrer. It makes no network requests of its own and sends nothing anywhere. Everything stays in local storage.
The file picker can close the popup. Chrome sometimes dismisses an extension popup when the OS file dialog takes focus, which cancels an import mid-flight. If that happens on your system, run the import from the full page instead, where nothing can dismiss the window.
Overwrite is permanent.conflictAction: 'overwrite' replaces the file in place.
There’s no undo and nothing lands in the trash.
The extension’s own export is never routed.
Downloads made by the extension’s own pages, and scheduled backups, skip rule matching, so a loose rule can’t file your backup somewhere unexpected. The check looks at where the download came from, so a website that puts the extension’s address in its own URL is still routed and logged.
Other plugins’ backups keep their own path. Chrome drops the filename an extension asks for once any extension renames downloads, so Download Router puts it back for the scheduled backups of the other plugins in this suite (Clipboard Tabber, Header Injector, History Automator, Page Monitor, Reddit Domain Blocker, Reelgood Exporter and Show No More). It only does this for their backup filenames, so no other extension can use it to choose where its downloads land.
Scheduled backups show up in the download list. Each one is an ordinary download, and old ones disappear from the list when cleanup deletes them.
“Ask where to save each file” still applies. If that browser setting is on, you’ll get a save dialog as usual; the routed path shows up pre-filled in it.
| Version | Change |
|---|---|
| 3.3 | Security: domain rules match the site’s host name, not text anywhere in the URL. Access to all websites removed. Only the suite’s backup filenames are honored for other extensions. Backup requests are only taken from the extension’s own pages |
| 3.2 | Restore: bring back every setting from a backup file, separate from Import |
| 3.1 | Scheduled backup: back up every n days into a chosen subfolder and keep a set number of earlier backups, counted one per day |
| 3.0 | File-type matching, per-rule enable/disable, activity log, full-page options view. Rules are now stored as an ordered array; older storage is migrated on read |
| 2.7 | Icons moved into an icons subfolder |
| 2.6 | Custom icon, declared at all four sizes and shown in the popup header |
| 2.5 | Export and Import moved to a sticky top bar; paste-JSON option removed |
| 2.4 | Export filename time as six digits (143052) |
| 2.3 | Time added to the export filename |
| 2.2 | Export and import of all settings |
| 2.1 | Per-rule option to replace same-name files |
| 2.0 | Rule editing UI |


Leave a Reply