Every link you copy is a little dossier. Paste a product URL into a chat and you often ship along utm_source, fbclid, gclid, mc_eid: a trail of who sent what, from which campaign, to whom. None of it is needed for the page to load. All of it follows the click.
cln is a tiny command-line tool that removes that trail. You give it a URL, it strips the known tracking parameters, prints the clean version, and copies it to your clipboard. One word, one clean link.
$ cln 'https://example.com/page?utm_source=nl&utm_medium=email&id=42'
https://example.com/page?id=42
removed: utm_source, utm_medium
The cleaned URL goes to stdout (so it stays pipeable) and to your clipboard (with no stray trailing newline). Anything it stripped is reported on stderr as removed: …, so you can see exactly what was taken out.
The interesting decision in cln is what it doesn't touch.
It removes tracking only: the whole UTM family (anything starting utm_), click IDs (fbclid, gclid, msclkid, igshid, …), email/campaign tokens (mc_eid, mkt_tok, _hsenc, …) and analytics/session junk (_ga, _gl, …).
It deliberately preserves affiliate and referral parameters like tag, ref, partner, irclickid, the Rakuten ran* set, and so on:
$ cln 'https://www.amazon.com/dp/B0XXXX?tag=metaend-21&utm_source=x'
https://www.amazon.com/dp/B0XXXX?tag=metaend-21
removed: utm_source
The tag=metaend-21 affiliate credit survives; the campaign tracker does not. This is intentional. A privacy tool that quietly rewrote or dropped affiliate tags would be doing the Honey thing, siphoning credit behind the user's back. cln never injects, alters, or substitutes attribution. It only ever preserves what's already there. And the default is conservative: anything not explicitly known to be tracking is kept, so a functional or revenue-bearing parameter is never stripped by accident.
cln is a single static Go binary with a deliberately minimal trust surface:
Standard library only. Zero third-party dependencies. The binary parses the URL with
net/urland does string filtering. It links no clipboard, GUI, or networking libraries.No network, ever. It reads a string, cleans it, writes a string. That's it.
Clipboard by shell-out. Instead of linking a clipboard library, it shells out to the tool already on your system, detected at runtime:
wl-copy/wl-pasteon Wayland,xcliporxselon X11. The same binary works on both.Safe by construction. The clipboard utility is always invoked with an explicit argument vector (never a shell, never string interpolation) and the URL content travels over stdin, never as a command argument. Untrusted clipboard content can't be reinterpreted as a command.
The realistic failure mode for a tool like this is parsing a URL wrong (leaking a param that should be stripped, or mangling a working link), so kept-parameter order and original encoding are preserved exactly, and the behavior is pinned by a table-driven test suite.
cln <url> # clean the given URL
cln # read the URL from the clipboard, clean it, write the result back
cln -h # usage
Bare cln is the everyday path: copy a messy link from your browser, run cln, paste the clean one.
Install needs a clipboard backend for your display server (wl-clipboard on Wayland, xclip on X11) and a one-line build:
CGO_ENABLED=0 go build -trimpath -ldflags="-s -w" -o cln .
cp cln ~/.local/bin/cln
…or just make install. The denylist of what counts as "tracking" is a single compiled-in extension point in clean.go: add a param if you decide it's pure tracking, rebuild, done. No config files, no remote rulesets, no daemon.
gourl-cleaner on gitworkshop.dev - MIT licensed.
Built by metaend - verifiable, privacy-first infrastructure.

