context-attachment-manager
Codex and Claude Code plugin (works in Claude Desktop): choose which past images go to the model with your next message. Unchecked images become placeholders, the conversation goes on, and requests st
Instantly save YouTube videos to your custom watch list using Alt+Click. Fast, minimal, easy to organize & privacy-focused.
PluginsJavaScript · CSSGitHub @adaddariodevSelf-installOwner unconfirmed
Paste into Claude or ChatGPT for installation instructions suited to your environment.
Have you tried it? One tap is enough. No sign-in needed.
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗YouTube's own "Watch Later" costs you three clicks, a dropdown and a page you did not want to load — and then the list only works on YouTube. Most videos saved that way are never seen again.
Watch Later Enhanced replaces that with one gesture. Hold Alt, left click any
thumbnail, and it is on your list — no navigation, no dropdown, no page load.
The list lives in your browser toolbar, reachable from any site.
Alt + left click any thumbnail, or the player itself, and the video is saved. A
small HUD confirms it with the video's real title, pulled from the page or from
YouTube's oEmbed endpoint if the page does not offer one.
Paste a YouTube link — youtube.com, the Share button's youtu.be, a Short, a
live stream, with or without https:// — anywhere on the list in the popup, or
into Info & Settings → Import & export → Add by link. There, anything that is
not a YouTube video is refused with the reason, and
a video already on the list says which tab it is in rather than being added
twice. The popup asks YouTube nothing, so the title, channel and type are filled
in by a YouTube tab: at once if one is on screen, otherwise on your next visit.
Export writes To Watch and Archive to a JSON file; Import reads one back — or a hand-written list of links — and only ever adds: a video already on the list is left exactly as it is, nothing is removed, and an Undo takes the whole import back out. The Guide beside the two buttons opens the guide's own section on them, with the file format, every field and worked examples. A file window closes the toolbar popup in some browsers, silently taking the import with it, so Import always opens the list in a small window of its own first, which it cannot close.
Pop any video out of the browser into a floating mini player. Minimize the browser, move to another app, drag the window anywhere — it keeps playing.
Alt + Shift + left click it — the
gesture that saves a video, with Shift. Or pick Play in mini player from
the video's own ⋮ menu. Or hover the thumbnail and use the button in its
top-left corner.Alt + Shift + left click the player, or the mini-player
button in YouTube's control bar. The window opens at the second the page had
reached, and the page stops playing — one video at a time, never two.background permission, so Chrome stays running after its last
window, with an icon by the clock. Its controls live in the extension's
popup while it floats: play/pause, position, volume and mute, speed,
quality, the next video in To Watch, back to the mini player, stop.
Captions do not show in it. A mini player that is the only window open
when you pin is minimized rather than closed, since the extension cannot
tell whether Chrome's own background setting will keep it running.There is only ever one mini player: asking for the video already in it brings that window forward (or, while it is pinned, leaves it floating where it is), and asking for another opens it in a window that takes the old one's place. It is a window of its own, so closing the page it came from leaves it playing.
The pin itself is a button because it has to be: a browser only grants an always-on-top window in response to a click inside the page, so no preference can ask for one on your behalf.
channel:Fireship, tag:music), which you can also type; a tag
leaves the box folded, since its chip lights up in the tag bar instead.The channel name — and a Shorts label, on a Short — sit on one line
under every title, with your own tags on a line of their own below them.
Because YouTube serves the same Short behind both /shorts/ and /watch
links, the type is worked out from the URL, then from the page around the
thumbnail, and finally — when neither settles it — by asking YouTube in the
background and correcting the label a moment later. The channel comes from the
page when it is there and from YouTube's oembed payload when it is not.
Items saved before a detail existed are filled in a few at a time while you browse YouTube, rather than left permanently blank.
Settings opens a bundled user guide: searchable, with a table of contents that tracks your scroll position, a full shortcut reference and troubleshooting. It ships inside the extension, so it works offline. Beside it, What's new links to the releases on GitHub, and the version you are running is printed at the foot of the panel — read from the manifest, so it cannot disagree with what you have installed.
| Shortcut | Where | What it does |
|---|---|---|
Alt + left click | Any YouTube thumbnail | Saves it without opening it |
Alt + left click | The video player | Saves what you are watching |
Alt + Shift + left click | Any thumbnail or title | Plays it in the mini player, without opening it |
Alt + Shift + left click | The player on a video page | Opens it in the mini player, from where the page had reached |
/ | The popup | Opens the search box |
Ctrl/⌘ + V | The list in the popup | Adds the YouTube link on the clipboard |
Enter | Add by link | Adds the pasted link |
Esc | The search box | Clears it and folds it away |
Space or K | Mini player | Play / pause |
← / → | Mini player | Back / forward 5 seconds |
M | Mini player | Mute / unmute |
Enter / Esc | Tag box | Add the tag / close without adding |
← / →, Home / End | Tag bar | Move along the tags; Enter filters by the one focused |
There is no server behind this extension. No account, no sign-in, no telemetry,
no analytics, no sync. Your list is held in chrome.storage.local on your own
machine and is never transmitted anywhere.
Every outbound request the extension itself makes:
| To | When | What it carries |
|---|---|---|
youtube.com/oembed | Saving a video whose title the page did not provide, or naming one added by its link | The video URL |
youtube.com/shorts/<id> | Saving, to tell a Short from a video | The video ID |
i.ytimg.com/vi/<id>/default.jpg | Showing a card's thumbnail, while thumbnails are on | The video ID; no referrer |
youtube.com/embed/<id> | While a mini player is open, so Pin on top can float it | The video ID; the embed is loaded in the extension's own offscreen page |
That is the complete list of what the extension asks for. The embedded player in the last row is YouTube's own, and loads what it always loads — its scripts, the video, and any ads YouTube serves before it — exactly as on any site that embeds a video. The first two go to YouTube, only from a YouTube tab, and carry nothing about you beyond the video in question — which is why a video added in the popup by its link waits for a YouTube tab to name it rather than the popup asking. The third is YouTube's image server, asked by the popup for the pictures of the cards near the screen; the browser caches them, and the extension stores none. Export and Import write and read a file on your own machine; nothing is uploaded. The extension sends nothing to any other party: the Inter typeface is bundled with the extension rather than fetched from Google, so with thumbnails switched off, opening the popup makes no request at all.
The page's own Content Security Policy enforces it — style-src 'self'; font-src 'self'; — so a remote stylesheet or font could not load even if one
were added by mistake.
Permissions requested:
storage — your list and settings.offscreen — the page with no window that the pinned video floats from.declarativeNetRequestWithHostAccess and the youtube.com host
permission — one session rule that gives that page's YouTube embed the
Referer YouTube requires, for requests made outside any tab only.background — keeps Chrome running after its last window closes, so a
pinned video keeps playing. Chrome then runs in the background whenever the
extension is installed, not only while a video floats, and on Windows it
starts with your computer.No tabs, no scripting, no access to any other site.
From the Chrome Web Store — add it here.
From source
git clone https://github.com/adaddariodev/Watch-Later-Enhanced-webplugin.git
Then open chrome://extensions/, turn on Developer mode, click
Load unpacked, and select the cloned directory.
Requires Chrome 116+. In Firefox 109+ saving and the list work; the mini player does not, since Firefox does not run the extension's background service worker.
Packaging for the Chrome Web Store
./scripts/package.sh # → dist/watch-later-enhanced-<version>.zip
It zips an allow-list of the files the extension loads, taken from the last
commit rather than the folder: the README, the store copy in docs/ and the
logos and promo banners in imgs/ stay out of what users install, and an
uncommitted edit can never ship by accident.
Vanilla JavaScript, no build step, no dependencies, no framework. Clone it and it runs.
document handles every thumbnail on the page,
rather than binding to each of the hundreds YouTube creates and destroys as
you scroll. Nothing to clean up, nothing to leak.ytd-thumbnail or ytLockupViewModelContentImage. Those names differ per
surface and change without notice; that shape does not. Where something has
to be found inside YouTube's own UI, it is found by its ARIA role — the ⋮
menu is [role="menu"], and the row added to it is a clone of one of its
own, so it inherits whatever styling that menu is wearing.oembed endpoint as a fallback. Title and channel share one
memoised oembed call rather than one each, and everything is asked of the
page's own origin so it works on m.youtube.com too.i.ytimg.com/vi/<id>/default.jpg, 120×90, a few KB),
never stored. loading="lazy" inside the render window means only cards near
the screen ask; the browser's HTTP cache answers every later redraw and
reopening, measured at zero repeat requests. The 16:9 frame inside the 4:3
file is cropped out by object-fit: cover in a 16:9 box, so no larger size is
ever fetched..
├── docs/ # Chrome Web Store listing copy
├── imgs/ # Logos and store promo banners — repo and listing only, not packaged
├── scripts/package.sh # Builds the Web Store zip from an allow-list
├── fonts/ # Inter, bundled (woff2 + OFL licence) — no CDN
├── icons/ # Extension icons (48px, 128px) and button glyphs
├── sounds/ # popup-click.mp3, video-saved.mp3
├── background.js # Service worker: opens and serialises the mini player window
├── content.js # Saving, title extraction, type detection, backfill, HUD
├── content.css # In-page HUD and injected button styles
├── detach.js # Mini player window, its ways in, and the pin
├── float.html/.js # Offscreen page the pinned video floats from
├── float-embed.js # Inside its YouTube embed: priming, the pin, reports
├── float-embed-main.js # The embed player's own API, from the page world
├── popup.html/.css/.js # The list: thumbnails, tags, search, filters, drag reorder,
│ # add by link, import/export, settings
├── wiki.html/.css/.js # Built-in user guide, opened from Settings
├── url-utils.js # Shared URL parsing and validation
├── manifest.json # Manifest V3 configuration
└── README.md
Issues and pull requests are welcome — refactors, new features, or sharper selectors for YouTube's ever-changing DOM. Fork it and open a PR.
MIT. See LICENSE.
The bundled Inter typeface is © The Inter Project Authors, licensed under
the SIL Open Font License 1.1 — see fonts/OFL.txt.
IntersectionObserver a screen ahead of the fold, so the cost of the
full rebuild each change triggers is the cost of what is on screen rather
than of everything saved. The window never shrinks while the list is the
same one, because the browser keeps your scroll position across a rebuild
only while the content is still as tall.<video>, so the window
starts at the second the page had reached rather than receiving the frame
itself.float.html) holding a YouTube embed of the same
video, prepared while the mini player is open. It is the browser's video
picture-in-picture rather than a Document Picture-in-Picture window, which
carries a title bar no page can remove and cannot be opened from an
offscreen document at all. The click on Pin on
top happens in the mini player's page; its message carries the gesture to
the worker, which hands it on synchronously over a port to a content script
inside the embed (float-embed.js), which opens the window. The player's
own API is reached from the page world (float-embed-main.js), and a
declarativeNetRequest session rule gives the embed the Referer YouTube
requires, for requests outside any tab only. The background permission
keeps Chrome running after its last window. If the floating
player is not ready, the same click pins the old way: picture-in-picture
from the mini player's page, whose window is then minimized.