Home (All Topics) → Technology → Software → AI-Created Software
By Marios Alexandrou on September 9, 2026.
The following 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 (Manifest V3) that adds custom HTTP request headers to the domains you choose, and shows you which of your rules are actually firing.
Useful for hitting a staging API that needs an auth token, testing feature flags behind a header, or faking a X-Forwarded-For against your own dev server. Rules are applied by Chrome’s declarativeNetRequest engine, so headers are set before the request leaves the browser and nothing in your page code changes.
An unpacked, developer-mode extension. There is no store listing.
chrome://extensionsAfter editing any file, hit the reload arrow on the extension’s card.
The popup is for quick work: add a rule, flip one on or off, glance at what’s firing. Manage all rules opens the full manager, which adds filtering, import, export and the last URL each rule matched.
A rule is three things:
| Field | Example | Notes |
|---|---|---|
| Domain or URL pattern | api.staging.example.com |
See matching, below |
| Header name | Authorization |
Case-insensitive |
| Header value | Bearer eyJhbGci… |
May be empty |
Domain is the default and covers most cases. It uses requestDomains, which matches the host and any subdomain of it, on any port and any path. So example.com matches https://api.example.com/v1 but not https://other.test/?ref=example.com.
URL pattern is the escape hatch, using Chrome’s urlFilter syntax:
| Pattern | Matches |
|---|---|
||localhost:3000 |
localhost on port 3000 only |
https://api.example.com/v2* |
one path prefix |
*/graphql |
any host, that path |
|| anchors the host, * matches anything, | anchors the start or end of the URL. Type a port, a path or a * into the domain field and the rule is converted to a URL pattern for you, with a note saying what it became.
Rules apply to main frames, sub frames, XHR/fetch and scripts.
The count next to a rule is how many requests it has modified since the browser started. It comes from onRuleMatchedDebug, which Chrome only reports for unpacked extensions — pack this and the counts stay empty while the rules themselves keep working. Counts live in session storage and reset when Chrome restarts; Clear counts resets them by hand.
If a rule shows “Rejected”, Chrome refused it. The message says why, and the other rules keep working: rules are re-applied individually when a batch fails, so one bad rule can’t take the rest down with it.
Export writes every rule, including the disabled ones, to a JSON file. Import offers to add them to what you have or replace everything.
{
"format": "header-injector-pro/rules",
"version": 1,
"exportedAt": "2026-09-08T12:00:00.000Z",
"rules": [
{ "enabled": true, "matchType": "domain", "match": "api.example.com",
"key": "Authorization", "value": "Bearer …" }
]
}
Rule ids are deliberately left out so an imported file can never collide with rules you already have. A bare array of rules is also accepted, as is the old {"domain": …} field name.
Exports contain header values in plain text. They are usually credentials. Treat the file accordingly and keep it out of version control.
manifest.json Permissions, worker, icons, options page
background.js Service worker: rule sync, match tracking, toolbar state
popup.html/.js Quick add, per-rule switches, live match counts
options.html/.js Full manager: filter, edit, duplicate, import, export
lib/store.js Rule model, validation, storage, import/export (pure + tested)
lib/dom.js DOM builders, icons, relative times, toasts
lib/ui.css Design tokens and shared components
icons/ Toolbar and store artwork, plus icon.svg source
tools/ make_icons.py, regenerates every PNG from one definition
tools/make_icons.py renders all eight PNGs on a 2048px master and downsamples them, writing straight into icons/.
Needs Pillow and NumPy:
Sizes 16 and 32 are drawn from a simplified two-line variant with a solid arrowhead, because the three-line mark and its thin chevron blur together that small. Keep both the active and -off sets: background.js names all eight paths and setIcon throws if one is missing.icons/icon.svg is the vector source for the large variant.
lib/store.js holds everything that decides what a rule means, so the worker and both pages can’t drift apart. The top half is pure and has no dependency on the chrome namespace, which makes it testable outside the browser.
Stored rules migrate automatically the first time 1.3 reads them.
Each gains an id and an on switch, and the old domain field is re-read: plain domains become domain matches, anything with a wildcard becomes a URL pattern.
Matching got stricter. Version 1.2 wrapped every domain as *domain* and substring-matched it against the whole URL. If you were relying on that — a rule whose “domain” was really a path fragment, say — it will stop matching. Switch that rule to URL pattern mode and write the pattern explicitly.
| Permission | Why |
|---|---|
declarativeNetRequest |
Registers the header rules with Chrome’s network engine |
declarativeNetRequestFeedback |
Reports which rules matched, for the counts |
storage |
Saves rules locally, and match counts for the session |
<all_urls> |
modifyHeaders rules need host access to the sites they touch |
Nothing leaves your machine. Rules are in chrome.storage.local, counts are in chrome.storage.session, and neither syncs to your Google account.
responseHeaders block in the rule action.Host, Connection and friends; the form rejects those names at entry.
Service worker logs: chrome://extensions → Service worker on the card
What is actually registered: run this in the service worker console
Confirm the header on the wire in DevTools → Network → the request → Headers → Request headers. DevTools sometimes shows provisional headers for cached requests, so do a hard reload.
The pure half of lib/store.js has a test suite covering normalisation, the v1 migration, id stability and the import parser.
With Node 18+:


Leave a Reply