A userscript that adds small tools to YouTube watch pages. No build step, no
npm, no dependencies; it's a single standalone .user.js file.
A floating 📋 Copy button on watch pages (and Shorts) opens a small source picker. Check what you want, hit Copy, and it lands on your clipboard as one Markdown document (shared frontmatter + a section per source):
- Description: expands the description and copies it, turning chapter
timestamps into clickable links and unwrapping YouTube's
/redirectlinks to point straight at the real destination. - Transcript: auto-opens the transcript panel and copies chapter-grouped prose with clickable timestamp links.
- ✦ Ask: copies YouTube's own ✦ Ask (Gemini) answers as
**Q:**/**A:**pairs, keeping the AI's cited timestamps as links. Opportunistic: if you haven't asked anything, it's skipped rather than blocking the transcript.
On Shorts (which have no transcript panel) the button hops to the same video's watch page and copies from there.
- Ask AI (external): send the transcript to an LLM we call and ask about the video.
You need a userscript manager, Violentmonkey or Tampermonkey (both work on Chrome and Firefox). Then:
- GreasyFork (recommended): install from the GreasyFork page in one click, with auto-update.
- One-click from source: open the raw
yt-toolkit.user.js; the manager intercepts it and offers to install, also with auto-update on every push. - Manual: copy the contents of
yt-toolkit.user.jsand create a new script in the manager (no auto-update this way).
The manager keeps its own copy of the script. With one-click install it auto-updates; with a manual paste, re-import after editing the file.
Browsers can't write local files, so each tool copies to the clipboard rather than saving. The transcript reader walks YouTube's live DOM (handling both the "classic" and "viewmodel" transcript layouts) and groups segments into paragraphs; it doesn't scrape a saved HTML dump. The ✦ Ask reader converts the answer HTML already rendered in YouTube's Ask panel back into Markdown. The description reader expands the description first, since YouTube only fills in the full text once it's open, and reads just that block so the panels YouTube slots alongside it (the Show-transcript button, the social links) stay out.
Clipboard write prefers navigator.clipboard.writeText (verifiable) and falls
back to GM_setClipboard.
No network calls, no tracking, no external services. The script only reads the
page you're already on and writes the result to your clipboard; nothing
leaves your browser. @grant is limited to GM_setClipboard (a clipboard
fallback); there are no remote requests.
YouTube is a single-page app, so the button re-mounts on in-app navigation
(yt-navigate-finish), not just on hard page loads.
MIT © kalmigs
