Summon ✨ magical links ✨
A browser extension that captures the active tab as a shareable Link and places it on the system clipboard, ready to paste into chat apps, docs, and markdown editors.
Press a single keystroke (or click the toolbar icon) and the current page lands on your clipboard as a Link in two forms:
- Rich text form —
<a href="url">title</a>, written to the clipboard'stext/htmlslot. Pastes into Notion, Slack, Gmail, or Word as a clickable, formatted link. - Markdown form —
[title](url), written to the clipboard'stext/plainslot. Pastes into Obsidian, GitHub issues, or a code editor as readable markdown.
Whichever form the paste target prefers, it gets a useful representation. You don't pick.
A small pipeline of site-specific transformers cleans up the link text
where the raw page title isn't quite right — for example, stripping
YouTube's (69) unread-notification prefix from watch-page titles.
- Firefox — install from addons.mozilla.org/firefox/addon/link-mage.
- Chrome / Chromium — not yet published; build from source (see
below) and load
dist/as an unpacked extension viachrome://extensions.
- Press Alt+Shift+L to summon a Link from the active tab.
- Or click the 🧙 toolbar icon.
- The icon flashes ✅ on success and ❌ on failure (e.g. on restricted
pages like
about:config, the new tab page, oraddons.mozilla.org, where extensions can't reach).
Reproduces the published dist/ directory that ships inside the .xpi.
- Bun 1.3.14 (pinned in
mise.toml). If you use mise,mise installpicks it up automatically. Otherwise install Bun 1.3.14 directly.
bun install
bun run buildOutput lands in dist/:
dist/manifest.json— copied verbatim frompublic/manifest.jsondist/background.js— bundle ofsrc/background.tsdist/copy-link.js— bundle ofsrc/copy-link.ts(IIFE format, loaded as a content script)dist/icons/— copied verbatim frompublic/icons/
bun run package # produces web-ext-artifacts/link-mage-1.0.0.xpi
bun run package:source # produces web-ext-artifacts/link-mage-source-1.0.0.zipThe .xpi is what gets uploaded to AMO. The source zip is what AMO's
reviewer uses to reproduce the build.
bun run dev:firefox # build, watch sources, run a Firefox dev profile
bun run dev:chromium # same, against Chromiumbun run typecheck # tsc --noEmit
bun run lint:ext # web-ext lint against dist/web-ext lint will always emit one MANIFEST_FIELD_UNSUPPORTED
warning about /background/service_worker. That's expected — see
ADR-0001.
- Bump the version in
public/manifest.jsonandpackage.json(keep both in sync). Semver — patch for bugfixes, minor for features, major for breaking changes. - Commit and push to
main. - In GitHub: Actions → Release → Run workflow.
The workflow typechecks, lints, builds, signs and uploads the
.xpi to the AMO listed channel, tags the commit v<version>,
and creates a GitHub release with auto-generated notes. It refuses
to run if the tag already exists.
Updates appear on the AMO listing after Mozilla's review.
One-time prerequisites:
- The AMO listing exists (v1.0.0 was uploaded manually through the AMO web UI).
- Repository secrets
AMO_API_KEYandAMO_API_SECRETare set (generate at https://addons.mozilla.org/developers/addon/api/key).
CONTEXT.md— domain glossary (Page, Link, Summon, Transformer, etc.). Read this first if you're contributing.docs/adr/— architecture decision records explaining the cross-browser manifest, the synthetic-copy-event clipboard pattern, and the bundled-content-script pipeline.src/— TypeScript sources for the background script, content script, and transformer pipeline.public/— static assets copied verbatim into the build:manifest.jsonandicons/.scripts/— icon generator and source-zip packager.
File issues at https://github.com/KieranHunt/link-mage/issues.
MIT © 2026 Kieran Hunt