Take back desktop YouTube.
Bring back a familiar layout, put comments beside the video, and clear noise from your feed. Every control is optional. There is no Astra account and no telemetry.
Download for Chromium or Firefox · Install the userscript · Browse the features
- Restore what changed. Switch to a 2020 or 2016 style page, bring back classic player controls, or tighten the current interface.
- Use the whole screen. Theater Split keeps the video playing beside a live, scrollable comments column.
- Cut the clutter. Hide channels, keywords, Shorts, watched videos, sponsored requests, and the page elements you never use.
- Keep control local. Settings stay in the browser. AI summaries use your own provider or Ollama, and Astra never sees the request.
The searchable Command Deck covers playback, themes, comments, feed cleanup, downloads, transcripts, and hundreds of smaller choices. Start with the defaults, then change only what bothers you.
Current build facts
| Fact | Current source value |
|---|---|
| Release | v4.88.5 |
| Runtime floors | Node >=24; Chrome 120+ / equivalent Chromium release; Firefox 142+ |
| Extension locales | 11: ar, de, en, es, fr, it, ja, ko, pt_BR, ru, zh_CN |
| Settings schema | 487 entries across 18 categories |
| Runtime graph | 117 modules, including 27 peeled feature modules and 303 declared feature IDs |
| Selector surfaces | 35 shipped surfaces from 33 selector packs (2 aliases) |
| Build profiles | store-safe, chromium-store, github-full; github-full adds 6 full-only origins |
| Themes | 7 named color themes plus oledTheme, denseMode, tokenThemeBridge controls |
| Compatibility modes | Desktop YouTube extension; bounded YouTube Music theme/OLED/density compatibility; bounded /embed/:id player mode; mobile browsers and YouTube Studio; userscript follows the host desktop browser |
Option A, Load unpacked from ZIP:
- Download
astra-deck-chromium-store-chrome-v*.zipfor a download-free Chrome Web Store/Edge-compatible package, or chooseastra-deck-store-safe-chrome-v*.zip/astra-deck-github-full-chrome-v*.zipfor companion-capable self-hosted installs, from the latest release - Extract it to a permanent folder
- Open
chrome://extensions/, enable Developer mode - Click Load unpacked and select the extracted folder
Option B, Local folder:
- Download or clone the
extension/folder - Open
chrome://extensions/, enable Developer mode - Click Load unpacked and select the
extension/folder
Releases ship the ZIP, not a CRX. Self-hosted CRX installs are Linux-only on modern Chrome, so the ZIP + Load unpacked is the supported Chromium path.
The released .xpi is unsigned. Firefox Release and Beta install only
add-ons signed by Mozilla, and they reject an unsigned XPI with "This add-on
could not be installed because it appears to be corrupt", so about:addons →
Install Add-on From File does not work on the Firefox most people run. Pick
one of these instead:
Release builds also emit updates.json, and the companion-capable store-safe
Firefox manifest points at the stable latest-release update feed. That feed is
effective only after the XPI is signed; the currently released unsigned XPI
still requires one of the manual installation paths below.
Easiest, the userscript. Works on every Firefox edition, installs in one click, and auto-updates. See Userscript below.
Temporary, any Firefox edition. The add-on is removed when Firefox restarts.
- Download
astra-deck-chromium-store-firefox-v*.xpifor the download-free package, orastra-deck-store-safe-firefox-v*.xpi/astra-deck-github-full-firefox-v*.xpifor companion-capable installs, from the latest release - Open
about:debugging#/runtime/this-firefox - Click Load Temporary Add-on… and select the
.xpi
Permanent, Developer Edition, Nightly, or ESR only. These builds can be told to accept unsigned add-ons; Release and Beta cannot.
- Open
about:configand setxpinstall.signatures.requiredtofalse - Open
about:addons→ gear icon → Install Add-on From File - Select the
.xpi
Requires Firefox 142+ (set by strict_min_version in
scripts/manifest-patch.js, so Firefox's built-in
data-consent permissions cover the documented collection categories).
A userscript build is also available. Install Tampermonkey or Violentmonkey, then install the current YTKit.user.js artifact. Its generated @require loads the separately versioned Astra Deck YTKit Core Library from the same repository, so a separate Greasy Fork core publication is not required.
The userscript starts at document-start and continuously collapses known ad shells, but a userscript manager cannot guarantee interception before the browser starts page requests. Use the extension when browser-level ad-request blocking is required. Its download cascade never calls public Cobalt/community APIs: after local and direct methods fail, an external web page opens only when the user has explicitly configured a valid HTTPS downloader URL. Without a {url} placeholder, the canonical watch URL is placed in the fragment rather than the navigation request.
SharedAudio remains userscript-only. The
store-safeandgithub-fullextension profiles can use Astra Downloader; thechromium-storeartifact is download-free. GitHub-full can also use a Cobalt instance the user operates or is authorized to use after an exact-origin browser grant; Astra Deck does not include Cobalt's public service.
Video and audio downloads are handled by Astra Downloader, a separate program with its own repository, releases, and documentation. Astra Deck and Astra Downloader are separate installs: the extension above works on its own, and downloads need the companion running on this device.
Download AstraDownloader.exe from the
latest Astra Downloader release
and run it, or use the in-page Download setup prompt, which points at the
same place. Then return to YouTube and choose Check again. The toolbar
popup also has recovery actions to re-enable the setup prompt and request an
on-demand companion update from a running service.
Everything about the companion, installing from source, building the executable, the per-site sign-in store, subscriptions, the URL policy, and its security model, is documented in its README. It downloads from any site yt-dlp supports, not only YouTube.
Two details matter on this side of the boundary:
- Discovery is by port, not configuration. The extension probes
127.0.0.1across the ports inscripts/companion-port-catalogue.json. That file is duplicated byte-for-byte in the Astra Downloader repository and checked in both, so changing the ports is a two-repository change. - Releases here never carry
AstraDownloader.exe. Publishing a second, independently versioned copy behind the same update check is how installs previously ended up four versions stale, sonpm run release:readinessfails if the executable is staged inbuild/or listed in the release manifest.
The PO-token provider and Deno sections below are companion prerequisites. They improve downloader reliability after Astra Downloader itself is running; they are not browser extension install steps.
YouTube has no setting that gives you the old player or the old page back. Astra has three, and they are CSS only, so nothing is rebuilt and nothing is left behind when you turn them off.
| What you want back | Setting |
|---|---|
| The pre-2025 page: tighter spacing, smaller masthead, older watch-page proportions | classicLayoutProfile, set to classic-2020 or classic-2016 |
| The old player controls: opaque square buttons, the classic progress bar, the original time display | classicPlayerChrome |
| The new player's overflow panel and pill actions hidden, with a tighter progress bar | newPlayerUiRestore |
A caveat worth stating plainly. These work by restyling what YouTube ships, so they last only as long as YouTube keeps shipping something to restyle. If it removes the underlying markup, they stop, and no extension can prevent that.
Two things in this space are usually paid, and Astra gives both away.
| Elsewhere | Astra | |
|---|---|---|
| Nested subscription groups, feed sorting, unlimited mark-as-watched | PocketTube, $3.99/mo | Built in, no account |
| AI video summaries | Glasp meters free users at 3 a day; NoteGPT and Harpa meter tokens | Bring your own key, or run a local model through Ollama. No metering, because Astra never sees the request |
There is no Astra account, no server, and no telemetry. Summaries go straight from your browser to whichever provider you configured, or to your own machine.
| Feature | Default |
|---|---|
| Zero-Ad Desktop Surface, static MV3 request blocking plus document-start ad-shell collapse; userscript provides shell collapse only | Built in |
| Theater Split, responsive video and comments panes with a click-or-drag divider, compact live header, matching themes, and exact inline-style restoration on exit | On |
| Video Hider, hide videos/channels from feeds with X buttons, keyword filter, regex, duration filter | On |
| Video Context Menu, right-click player for downloads, VLC/MPV streaming, transcript, screenshot | On |
| Settings Panel, searchable, categorized, instant-apply, export/import/reset | On |
| Known-Breakage Notices, pause features YouTube has broken until a fix ships | On |
| Comment Search, filter watch-page comments inline | Off |
| DeArrow, replace clickbait titles/thumbnails via crowdsourced database | Off |
YouTube changes its layout without warning, and when it does, some features stop working. Cutting a release is a slow answer to that, so Known-Breakage Notices reads a short list from this repository at most once every six hours and pauses the features that list names for the versions they are broken in. The card in Settings says so and links the issue. The list can pause a feature and nothing else: it cannot switch anything on, cannot read or change a setting, carries no code and no links, and cannot name anything the extension does not already ship. Your own toggle is left exactly as you set it. It is on by default, under Advanced, and with it off no request is made.
GitHub-full builds can optionally follow one user-selected HTTPS Video Hider filter list after an exact-origin browser prompt. Remote lists are anonymous, data-only requests capped at 1 MiB: unknown fields and malformed payloads are rejected, publisher predicate code is discarded, and the exact response is recorded with SHA-256 plus ETag/Last-Modified validators. The popup shows the source host, format, verification age, and active/stale state; users can choose daily, weekly, or manual checks and pause last-known-good rules whenever a refresh fails or the last verification becomes older than seven days.
| Feature | Default |
|---|---|
| Logo Quick Links, hover dropdown with History, Watch Later, Playlists, Liked, Subs | On |
| Hide Sidebar / Hide Shorts / Hide Related / Hide Description | On |
| Subscriptions Grid / Homepage Grid Align / Videos Per Row | On |
| Styled Filter Chips / Compact Layout / Thin Scrollbar | On |
| Square Search Bar / Square Avatars | On |
| Compact Unfixed Header / Force Dark Everywhere | Off |
| Feature | Default |
|---|---|
| Watch Page Restyle, matched dark and light canvas, search, metadata, actions, and comments | On |
| Native Comments Layout, keep YouTube comments clean without extension restyling | On |
| Expand Video Width / Disable Ambient Mode | On |
| Hide Merch, AI Summary, Hashtags, Pinned Comments, Info Panels | On |
| Clean Share URLs, strip tracking params | On |
Return YouTube Dislike, estimated dislike count with est. disclosure + ratio |
Off |
| Auto-Expand Description / Sticky Chat / Scroll to Player | Off |
| Feature | Default |
|---|---|
| Always Best Quality, picks highest available stream, prefers 1080p Premium when offered | On |
| Auto-Resume Position (configurable threshold) | On |
| Custom Progress Bar Color (color picker) | Off |
| Remaining Time Display / Time in Tab Title | Off |
| A-B Loop / Fine Speed Control / Persistent Speed / Per-Channel Speed | Off |
| Speed Control Chip (in-chrome popup: 0.25× → 3×, 10 presets) | On |
| Codec Selector (H.264/VP9/AV1) / Force Standard FPS | Off |
| Video Screenshot / Video Zoom (Ctrl+scroll, up to 5x) | Off |
| Cinema Ambient Glow / Nyan Cat Progress Bar | Off |
| Speed Indicator Overlay / Custom Speed Buttons (0.5x-3x) | Off |
| Pop-Out Player (Document PiP) / PiP Button / Fullscreen on Double-Click | Off |
| Feature | Default |
|---|---|
| Remove Shorts / Redirect Shorts to Regular Player | On |
| Channels open on Videos Tab | On |
| Hide Collaborations / News / Playlists / Playables / Members Only | On |
| Hide Watched Videos (dim or hide) / Grayscale Thumbnails | Off |
| Anti-Translate / Not Interested Button / Open in New Tab | Off |
| Disable Infinite Scroll / Disable SPA Navigation | Off |
| Feature | Default |
|---|---|
| Download Options Popup, format, quality, and save directory per download | On |
| Video Formats, MP4, MKV, WebM | MP4 |
| Audio Formats, MP3, M4A, Opus, FLAC, WAV | MP3 |
| Quality Selector, Best, 4K, 1440p, 1080p, 720p, 480p | Best |
| Custom Save Directory, override per download or set globally | Downloads |
| Context Menu, quick "Download Video" and "Download Audio" on right-click | On |
| Auto-Download on Visit | Off |
| Download Thumbnail (maxres) | Off |
Downloads use Astra Downloader, the bundled local yt-dlp + ffmpeg companion. Both profiles probe
9751plus fallback ports (9761,9771,9781,9791,9851) and only accept health responses that identify as the Astra downloader service. The store-safe ceiling keeps the companion handoff but excludes AI, Ollama, and Cobalt. GitHub-full can show the fallback after the user enters the root HTTPS origin of a self-hosted Cobalt instance and grants access to that one host;api.cobalt.toolsis deliberately unavailable. See Astra Downloader Companion Setup for the current install and release-asset state.
The GitHub-full popup maintenance actions are recoverable. yt-dlp updates run
against a staged sibling executable; companion updates must pass checksum and
hidden startup checks. Each path retains one verified last-known-good binary,
activates atomically, and restores that backup automatically when the new
binary fails its post-update check. The popup and /health.updateRecovery
identify the active and rollback versions without exposing local paths or
digests.
YouTube binds PO tokens to video IDs in 2026; without a provider, the web client increasingly fails with "Sign in to confirm you're not a bot" on a subset of videos. Astra Downloader auto-detects a bgutil-ytdlp-pot-provider HTTP server on 127.0.0.1:4416 and routes yt-dlp through it when available.
Quickest setup (Docker):
docker run --name bgutil-provider -d --restart unless-stopped -p 4416:4416 brainicism/bgutil-ytdlp-pot-providerThen install the yt-dlp plugin so yt-dlp.exe knows to consult the provider:
pip install bgutil-ytdlp-pot-providerAstra Downloader's /health endpoint will surface poTokenProvider: { ok, port, version } once the server is reachable. If absent, downloads still work on most videos, the provider is opt-in hardening, not a hard requirement.
yt-dlp >= 2026.04 uses external EJS challenge solvers for YouTube. Astra
Downloader defaults to Deno >=2.3 and can fall back to Node >=22; choose
Auto, Deno, or Node in companion Settings. Runtime presence alone is not
enough: the companion verifies the version and executes a bounded JavaScript
capability probe before allowing a runtime-required download.
Install Deno once:
# Windows
winget install DenoLand.Deno
# macOS / Linux
curl -fsSL https://deno.land/install.sh | sh(Or grab the installer from https://deno.com/. To use Node instead, install
Node 24 or newer and select Node 24+ in companion Settings.)
Astra Downloader's /health endpoint surfaces javascriptRuntime: { runtime, version, supported, ejsReady, reason } while retaining denoRuntime as a compatibility alias. The download health panel names the selected runtime and offers one-click Deno provisioning only when Deno is an eligible choice. Unknown versions, probe failures, and unsupported runtimes stop with actionable errors; older pre-runtime yt-dlp builds remain allowed.
yt-dlp and its pins live in the Astra Downloader repository, which runs the bounded media smoke against a stable public fixture before accepting extractor dependency bumps.
| Feature | Default |
|---|---|
| Sort Comments Newest First | Off |
| Creator Comment Highlight | Off |
| Comment Handle Revealer, show original channel name next to @handle | Off |
| Preload Comments | Off |
| Feature | Default |
|---|---|
| Premium Live Chat styling | On |
| Configurable element hiding (header, emoji, super chats, polls, etc.) | On |
| Chat Keyword Filter | Off |
| Adaptive Live Layout | Off |
| Reaction Spammer, opt-in floating panel, randomized emoji loop (500 ms floor) | Off |
| Feature | Default |
|---|---|
| Auto-Dismiss "Still Watching?" | Off |
| Auto Theater Mode / Auto Subtitles / Auto-Like Subscribed | Off |
| Auto-Pause on Tab Switch / Pause Other Tabs | Off |
| Auto-Open Chapters / Auto-Open Transcript | Off |
| Auto-Close Popups (cookie/survey/premium) | Off |
| Prevent Autoplay / Disable Autoplay Next | Off |
| Redirect Home to Subscriptions | Off |
| Remember Volume / Persistent Speed | Off |
| Feature | Default |
|---|---|
| Resume Playback (500-entry cap, 15s save interval) | Off |
| Mini Player Bar (floating progress/play/pause on scroll-past) | Off |
| Playback Stats Overlay (codec, resolution, dropped frames, bandwidth) | Off |
| Watch Time Tracker (90-day retention) + Analytics Dashboard | Off |
| Timestamp Bookmarks (inline notes, persistent storage) | Off |
| Transcript Viewer (sidebar with clickable timestamps) + Export | Off |
| AI Video Summary (OpenAI / Anthropic / Gemini / Ollama, BYO key) | Off |
| Subtitle Styling (font, size, color, background, position) | Off |
| Blue Light Filter (adjustable 10-80%) | Off |
| Focused Mode (hide everything except video + comments) | Off |
| Custom CSS Injection | Off |
| CPU Tamer (background tab timer throttling) | Off |
| Settings Profiles / Statistics Dashboard / Debug Mode | Off |
| Fit Player to Window | Off |
Toggle individual elements on/off through the settings panel:
- Action Buttons, Like, Dislike, Share, Ask/AI, Clip, Thanks, Save, Sponsor, More Actions
- Player Controls, Next, Autoplay, Subtitles, Captions, Miniplayer, PiP, Theater, Fullscreen
- Watch Elements, Join Button, Ask Button, Save Button, Ask AI Section, Podcast Section, Transcript Section
- Chat Elements, Header, Menu, Popout, Reactions, Timestamps, Polls, Ticker, Leaderboard, Super Chats, Emoji, Bots
Click the gear icon in the YouTube masthead or player controls, or use the toolbar popup's Open Full Settings action.
Keep the video visible while you read or write comments. The divider can collapse, click open, or drag to the width you want. Dark and light modes follow YouTube.
Captured from the packaged extension in a disposable offscreen Edge session.
- Command Deck workspace with a mission card and three live preference summaries on every category
- Searchable sidebar spanning eleven destinations, including the dedicated Video Hider workflow
- Full-width semantic control sections with dependency rails for nested settings
- Toggle switches with instant apply
- Sub-feature controls for granular element hiding
- Textarea editors for keyword filters, quick links, custom CSS
- Schema-validated Export / Import / Reset with credential scrub
- Conflict detection (auto-disables conflicting features with toast notification)
- Verified dark/light and RTL layouts at supported desktop viewports, including normal YouTube, native Theater, and Theater Split. The live browser check measures metadata, comments, related videos or chat, scrolling, and player geometry across repeated mode changes. The mobile light state is exercised in the settings fixture; mobile browser support remains host-dependent.
The toolbar popup keeps common toggles, backups, diagnostics, and language selection close at hand. Selector drift and external service failures stay in the health panels and export bundle. They don't open automatic overlays on YouTube.
This generated knowledgebase documents all 482 user-facing settings in the canonical schema. The remaining 5 schema entries are internal migration/profile metadata, not user controls. Defaults, accepted values, build availability, scope, apply behavior, capability requirements, and introduction version are source-derived; purpose copy comes from the shipped feature definition or an audited subordinate-field description.
Extension onlysettings are unavailable in the standalone userscript.GitHub-full onlysettings require a compatible GitHub-full build/profile and any permission shown in the UI.Deferred applymeans the value is consumed on the next relevant render or navigation rather than rebuilding the current surface immediately.
Shell and appearance: 48 settings
Navigation and Guide: 18 settings
| Setting | Purpose | Default and accepted values | Availability and behavior |
|---|---|---|---|
Hide Create ButtonhideCreateButton |
Remove the "Create" button from the header toolbar | Default: On | Extension + userscript Store-safe + GitHub-full Global Live apply + reversible teardown Since v0.1.0 |
Hide Voice SearchhideVoiceSearch |
Remove the microphone icon from the search bar | Default: On | Extension + userscript Store-safe + GitHub-full Global Live apply + reversible teardown Since v0.1.0 |
Logo Click → SubscriptionslogoToSubscriptions |
Point the native YouTube home mark to your subscriptions feed | Default: On | Extension + userscript Store-safe + GitHub-full Global Live apply + reversible teardown Since v0.1.0 |
Clean Share URLscleanShareUrls |
Strip tracking params (si, pp, feature) from copied/shared YouTube links | Default: On | Extension + userscript Store-safe + GitHub-full Global Live apply + reversible teardown Since v0.1.0 |
Quick LinksquickLinkMenu |
Adds a compact quick-links menu in the masthead with customizable links | Default: On | Extension + userscript Store-safe + GitHub-full Global Live apply + reversible teardown Since v0.1.0 |
Quick link itemsquickLinkItems |
Defines up to ten masthead quick links, one Label and YouTube path per line; unsafe schemes and non-YouTube destinations are rejected. | Default: 6 preset lines | Extension + userscript Store-safe + GitHub-full Global Live apply Since v0.1.0 |
Normalize Clickbait TitlestitleNormalization |
Convert ALL CAPS titles to Title Case. Reduces clickbait without changing meaning. | Default: Off | Extension + userscript Store-safe + GitHub-full Global Live apply + reversible teardown Since v0.1.0 |
Redirect Home to SubscriptionsredirectHomeToSubs |
Automatically redirect the YouTube homepage to your subscriptions feed | Default: Off | Extension + userscript Store-safe + GitHub-full Global Live apply + reversible teardown Since v0.1.0 |
Clean Share MenushareMenuCleaner |
Removes social media buttons from the share dialog, leaving only the URL copy option | Default: Off | Extension + userscript Store-safe + GitHub-full Global Live apply + reversible teardown Since v0.1.0 |
Open Videos in New TabopenInNewTab |
Makes video links on the home/subscriptions page open in a new tab instead of navigating away | Default: Off | Extension + userscript Store-safe + GitHub-full Global Live apply + reversible teardown Since v0.1.0 |
Search While WatchingsearchWhileWatching |
Show YouTube search results in a lightweight watch-page panel without interrupting playback. | Default: Off | Extension only Store-safe + GitHub-full Watch page Live apply + reversible teardown Since v4.49.0 |
Open In Alternative FrontendopenInAlternativeFrontend |
Adds a button next to the player to open the current video in your configured alternative frontend (Invidious / Piped / FreeTube). Default instance is yewtu.be; change via alternativeFrontendInstance setting. | Default: Off | Extension + userscript GitHub-full only Global Live apply + reversible teardown Store-sensitive Since v0.1.0 |
Alternative frontend instancealternativeFrontendInstance |
Sets the HTTPS frontend origin used when Open in Alternative Frontend builds an external video link. | Default: https://yewtu.be |
Extension + userscript GitHub-full only Global Live apply Store-sensitive Since v0.1.0 |
Channel landing tabchannelLandingTab |
Which channel tab "Channels to Videos Tab" opens. Applies only while that feature is on, and falls back to Videos when the channel does not carry the chosen tab. | Default: videosValues: videos, shorts, streams, podcasts, playlists, posts |
Extension only Store-safe + GitHub-full Global Live apply Since v4.89.0 |
Bypass Playlist Mode on ClicksbypassPlaylistMode |
Strip the &list= parameter from clicked thumbnails so you don't get stuck inside someone's playlist | Default: Off | Extension + userscript Store-safe + GitHub-full Global Live apply + reversible teardown Since v0.1.0 |
Hide Guide ElementshiddenGuideElementsManager |
Choose individual left-navigation (Guide) entries to hide | Default: Off | Extension + userscript Store-safe + GitHub-full Global Live apply + reversible teardown Since v4.49.0 |
Hidden guide elementshiddenGuideElements |
Lists the individual Guide and mini-Guide destinations hidden by Hide Guide Elements. | Default: Empty list Choices: home, subscriptions, history, playlists, yourVideos, watchLater, likedVideos, trending, music, movies, live, gaming, news, sports, learning, premium, studio, settings, reportHistory, help, footer |
Extension + userscript Store-safe + GitHub-full Global Live apply Since v4.49.0 |
Hide Own AvatarhideOwnAvatar |
Remove your account avatar button from the header | Default: Off | Extension + userscript Store-safe + GitHub-full Global Live apply + reversible teardown Since v4.49.0 |
Shorts controls: 9 settings
Feeds and layout: 13 settings
Watch page and player controls: 75 settings
Playback, audio, and utilities: 109 settings
Quality and codecs: 12 settings
Video Hider and content filtering: 47 settings
Comments: 24 settings
Live chat: 7 settings
Subscriptions: 13 settings
SponsorBlock, DeArrow, and enrichment: 37 settings
| Setting | Purpose | Default and accepted values | Availability and behavior |
|---|---|---|---|
DeArrowdeArrow |
Replace clickbait titles and thumbnails with SponsorBlock data licensed under CC BY-NC-SA 4.0 | Default: Off | Extension + userscript Store-safe + GitHub-full Player Live apply + reversible teardown Remote API Since v0.1.0 |
Watch PagedaSurfaceWatch |
Use DeArrow on the primary video and its metadata | Default: On | Extension + userscript Store-safe + GitHub-full Global Live apply + reversible teardown Remote API Since v4.86.0 |
Related VideosdaSurfaceRelated |
Use DeArrow in the recommendations beside a video | Default: On | Extension + userscript Store-safe + GitHub-full Global Live apply + reversible teardown Remote API Since v4.86.0 |
Home FeeddaSurfaceHome |
Use DeArrow on the YouTube home feed | Default: On | Extension + userscript Store-safe + GitHub-full Global Live apply + reversible teardown Remote API Since v4.86.0 |
Search ResultsdaSurfaceSearch |
Use DeArrow in YouTube search results | Default: On | Extension + userscript Store-safe + GitHub-full Global Live apply + reversible teardown Remote API Since v4.86.0 |
Subscriptions FeeddaSurfaceSubscriptions |
Use DeArrow in the subscriptions feed | Default: On | Extension + userscript Store-safe + GitHub-full Global Live apply + reversible teardown Remote API Since v4.86.0 |
PlaylistsdaSurfacePlaylist |
Use DeArrow on playlist pages and in the watch-page playlist panel | Default: On | Extension + userscript Store-safe + GitHub-full Global Live apply + reversible teardown Remote API Since v4.86.0 |
Replace TitlesdaReplaceTitles |
Replace clickbait titles with crowdsourced alternatives | Default: On | Extension + userscript Store-safe + GitHub-full Player Live apply + reversible teardown Remote API Since v0.1.0 |
Replace ThumbnailsdaReplaceThumbs |
Replace clickbait thumbnails with video screenshots | Default: On | Extension + userscript Store-safe + GitHub-full Player Live apply + reversible teardown Remote API Since v0.1.0 |
Title FormatdaTitleFormat |
How to format replacement titles | Default: sentenceValues: sentence, title_case, original |
Extension + userscript Store-safe + GitHub-full Player Live apply Since v0.1.0 |
Casual ModedeArrowCasualMode |
Keep descriptive titles unchanged and only replace titles that have crowd-submitted DeArrow alternatives | Default: Off | Extension + userscript Store-safe + GitHub-full Player Live apply + reversible teardown Since v4.47.0 |
Format Original TitlesdaFallbackFormat |
Format the original title when no crowdsourced submission exists | Default: On | Extension + userscript Store-safe + GitHub-full Player Live apply + reversible teardown Since v0.1.0 |
Show Original on HoverdaShowOriginalHover |
Hover over a replaced title to see the original | Default: On | Extension + userscript Store-safe + GitHub-full Player Live apply + reversible teardown Since v0.1.0 |
Show Original TitledaShowOriginalTitle |
Show the original title beneath the DeArrow replacement | Default: Off | Extension + userscript Store-safe + GitHub-full Player Live apply + reversible teardown Since v4.57.0 |
Cache DurationdaCacheTTL |
Hours to cache branding data locally before refreshing | Default: 4Values: 0, 1, 4, 12, 24, 72 |
Extension + userscript Store-safe + GitHub-full Player Live apply Since v0.1.0 |
SponsorBlocksponsorBlock |
Automatically skip sponsored segments, intros, outros, and other non-content sections using SponsorBlock data licensed under CC BY-NC-SA 4.0 | Default: On | Extension + userscript Store-safe + GitHub-full Player Live apply + reversible teardown Remote API Since v0.1.0 |
SponsorBlock API hostsponsorBlockBaseUrl |
Primary HTTPS host used by SponsorBlock and DeArrow. | Default: https://sponsor.ajay.appValues: https://sponsor.ajay.app, https://sponsorblock.kavin.rocks |
Extension + userscript Store-safe + GitHub-full Global Live apply + reversible teardown Remote API Since v4.57.0 |
SponsorBlock fallback hostsponsorBlockMirrorUrl |
Approved HTTPS mirror tried once when the primary host fails. | Default: https://sponsorblock.kavin.rocksValues: (empty), https://sponsor.ajay.app, https://sponsorblock.kavin.rocks |
Extension + userscript Store-safe + GitHub-full Global Live apply + reversible teardown Remote API Since v4.57.0 |
Skip SponsorssbCat_sponsor |
Paid promotions and sponsorship segments | Default: On | Extension + userscript Store-safe + GitHub-full Player Live apply + reversible teardown Remote API Since v0.1.0 |
Skip IntrossbCat_intro |
Intro animations and branding | Default: On | Extension + userscript Store-safe + GitHub-full Player Live apply + reversible teardown Remote API Since v0.1.0 |
Skip OutrossbCat_outro |
Endcards and outro sequences | Default: On | Extension + userscript Store-safe + GitHub-full Player Live apply + reversible teardown Remote API Since v0.1.0 |
Skip Self-PromotionsbCat_selfpromo |
Creator promoting their own products or channels | Default: On | Extension + userscript Store-safe + GitHub-full Player Live apply + reversible teardown Remote API Since v0.1.0 |
Skip Interaction ReminderssbCat_interaction |
"Like, subscribe, comment" reminders | Default: On | Extension + userscript Store-safe + GitHub-full Player Live apply + reversible teardown Remote API Since v0.1.0 |
Skip Non-MusicsbCat_music_offtopic |
Non-music sections in music videos | Default: On | Extension + userscript Store-safe + GitHub-full Player Live apply + reversible teardown Remote API Since v0.1.0 |
Skip PreviewssbCat_preview |
Preview or recap of upcoming content | Default: On | Extension + userscript Store-safe + GitHub-full Player Live apply + reversible teardown Remote API Since v0.1.0 |
Skip FillersbCat_filler |
Tangential or filler content | Default: On | Extension + userscript Store-safe + GitHub-full Player Live apply + reversible teardown Remote API Since v0.1.0 |
Highlight Point of InterestsbCat_poi_highlight |
Jump to the highlight/point of interest (disabled by default) | Default: Off | Extension + userscript Store-safe + GitHub-full Player Live apply + reversible teardown Remote API Since v0.1.0 |
SponsorBlock Per-Channel ProfilessbPerChannelProfiles |
Override which SponsorBlock categories are skipped on a per-channel basis. Adds a chip next to the channel name on the watch page to configure overrides. Overrides persist in sbPerChannelProfilesData with a 500-entry cap. | Default: Off | Extension only Store-safe + GitHub-full Player Live apply + reversible teardown Remote API Since v4.47.0 |
SB per channel profiles datasbPerChannelProfilesData |
Stores extension-only SponsorBlock category overrides keyed by channel. | Default: Empty object | Extension only Store-safe + GitHub-full Player Deferred apply Remote API Since v4.47.0 |
Return YouTube DislikereturnDislike |
Restore an estimated dislike count via the public Return YouTube Dislike API. Cached locally; respects a 100 req/min budget. No cookies sent. Off by default. | Default: Off | Extension + userscript Store-safe + GitHub-full Player Live apply + reversible teardown Remote API Since v0.1.0 |
Thumbnail Like-Ratio BarsreturnDislikeOnCards |
Show an estimated like-ratio bar on visible video thumbnails, using the same bounded Return YouTube Dislike cache. | Default: Off | Extension + userscript Store-safe + GitHub-full Player Live apply + reversible teardown Remote API Since v0.1.0 |
Return dislike cache hoursreturnDislikeCacheHours |
Sets how many hours Return YouTube Dislike data remains fresh in the local cache. | Default: 24Range: 1 to ∞ |
Extension + userscript Store-safe + GitHub-full Player Live apply Since v0.1.0 |
Return dislike show ratioreturnDislikeShowRatio |
Shows the estimated like-to-dislike ratio alongside Return YouTube Dislike counts. | Default: On | Extension + userscript Store-safe + GitHub-full Player Live apply + reversible teardown Since v0.1.0 |
De arrow channel overridesdeArrowChannelOverrides |
Stores per-channel DeArrow modes so a channel can use replacements, originals, or disable processing. | Default: Empty object | Extension + userscript Store-safe + GitHub-full Player Live apply Since v0.1.0 |
DeArrow Per-Channel OverridesdeArrowChannelOverridesPanel |
Adds a small DeArrow mode chip next to the channel name on the watch page. Cycles through DeArrow → Original → Off → DeArrow per click. Overrides persist in deArrowChannelOverrides keyed by channel ID. | Default: Off | Extension + userscript Store-safe + GitHub-full Player Live apply + reversible teardown Since v0.1.0 |
DeArrow VotingdeArrowVoting |
Vote on DeArrow title replacements. Adds thumbs up/down buttons next to replaced titles on the watch page. Uses a locally generated private userID that never leaves DeArrow requests. Off by default. | Default: Off | Extension only Store-safe + GitHub-full Watch page Live apply + reversible teardown Remote API Since v0.1.0 |
DeArrow Peek ButtondearrowPeekButton |
Hold Alt to temporarily reveal original YouTube titles (undoes DeArrow/custom titles while pressed) | Default: Off | Extension + userscript Store-safe + GitHub-full Player Live apply + reversible teardown Since v0.1.0 |
Downloads and Astra Downloader: 15 settings
Subtitles: 12 settings
Research, wellbeing, and AI: 18 settings
| Setting | Purpose | Default and accepted values | Availability and behavior |
|---|---|---|---|
Digital WellbeingdigitalWellbeing |
Break reminders every N minutes of active playback + optional daily watch-time cap. Timers persist across SPA navigation. | Default: Off | Extension + userscript Store-safe + GitHub-full Watch page Live apply + reversible teardown Since v0.1.0 |
DW break interval mindwBreakIntervalMin |
Sets the continuous-watch interval after which Digital Wellbeing prompts for a break; zero disables break prompts. | Default: 30Range: 0 to 1440 |
Extension + userscript Store-safe + GitHub-full Watch page Live apply Since v0.1.0 |
DW daily cap mindwDailyCapMin |
Sets the daily watch-time cap enforced by Digital Wellbeing; zero disables the cap. | Default: 0Range: 0 to 1440 |
Extension + userscript Store-safe + GitHub-full Watch page Live apply Since v0.1.0 |
DW watch time todaydwWatchTimeToday |
Stores the dated, merge-safe daily watch-time accumulator used by Digital Wellbeing. | Default: {"date":"","seconds":0} |
Extension + userscript Store-safe + GitHub-full Watch page Live apply Since v0.1.0 |
Local AI Summary (Browser Built-In)localAiSummary |
Use Chrome's built-in Summarizer API when available; use the configured BYO-key lane when it is unavailable. | Default: Off | Extension + userscript Store-safe + GitHub-full Watch page Live apply + reversible teardown Experimental Since v0.1.0 |
Transcript Q&AlocalAiTranscriptQa |
Ask citation-backed questions with Chrome on-device AI or an explicitly selected configured provider. | Default: Off | Extension only Store-safe + GitHub-full Watch page Live apply + reversible teardown Remote API Since v0.1.0 |
Transcript Q&A providertranscriptQaLane |
Choose on-device processing or the configured OpenAI, Anthropic, Gemini, or Ollama provider. | Default: on-deviceValues: on-device, configured-provider |
Extension only Store-safe + GitHub-full Watch page Live apply Remote API Since v4.84.3 |
Study / Work ExportresearchSpacedReview |
Export study/work-mode data to Markdown or CSV, or build a bounded local transcript study pack from visible videos. | Default: Off | Extension + userscript Store-safe + GitHub-full Watch page Live apply + reversible teardown Since v0.1.0 |
Transcript Search IndexresearchTranscriptIndex |
Indexes captions for eligible videos you visit through the shared transcript service, without opening YouTube's transcript panel. Search stays local in IndexedDB; no telemetry. | Default: Off | Extension + userscript Store-safe + GitHub-full Watch page Live apply + reversible teardown Since v0.1.0 |
Transcript Search PanelresearchTranscriptSearchPanel |
Adds a "Search transcripts" button on the watch page that opens a search UI over the local IndexedDB transcript index. Requires Transcript Search Index to be on. Default off. | Default: Off | Extension + userscript Store-safe + GitHub-full Watch page Live apply + reversible teardown Since v0.1.0 |
Reddit CommentsredditComments |
Find Reddit discussions mentioning the current video (button in secondary sidebar) | Default: Off | Extension + userscript Store-safe + GitHub-full Watch page Live apply + reversible teardown Remote API Since v0.1.0 |
Watch History AnalyticswatchHistoryAnalytics |
Modal dashboard visualizing your 30-day YouTube watch time as a CSS bar chart (requires Watch Time Tracker) | Default: Off | Extension + userscript Store-safe + GitHub-full Watch page Live apply + reversible teardown Since v0.1.0 |
AI Video SummaryaiVideoSummary |
Bring-your-own-key LLM summary of the current video transcript (OpenAI/Anthropic/Gemini/Ollama) | Default: Off | Extension + userscript GitHub-full only Watch page Live apply + reversible teardown Remote API Since v0.1.0 |
AI summary endpoint URLaiSummaryEndpoint |
Chat-completions endpoint for OpenAI, Anthropic, Gemini, or a local Ollama. | Default: https://api.openai.com/v1/chat/completions |
Extension + userscript GitHub-full only Watch page Live apply Remote API Since v0.1.0 |
AI summary modelaiSummaryModel |
Sets the provider-specific model identifier sent with AI video-summary requests. | Default: gpt-4o-mini |
Extension + userscript GitHub-full only Watch page Live apply Remote API Since v0.1.0 |
AI summary provideraiSummaryProvider |
Provider id: openai, anthropic, gemini, or ollama (local). | Default: openaiValues: openai, anthropic, gemini, ollama |
Extension + userscript GitHub-full only Watch page Live apply Remote API Since v0.1.0 |
Transcript → AI One-Click HandofftranscriptAiHandoff |
Adds a player-button that copies the transcript and opens your chosen AI tool with a summarization prompt pre-filled | Default: Off | Extension + userscript Store-safe + GitHub-full Watch page Live apply + reversible teardown Since v0.1.0 |
Transcript AI targettranscriptAiTarget |
Chooses the external AI workspace opened by Transcript to AI Handoff after copying the prepared transcript. | Default: notebooklmValues: notebooklm, chatgpt, claude, gemini, perplexity |
Extension + userscript Store-safe + GitHub-full Watch page Live apply Since v0.1.0 |
Privacy, profiles, and sync: 10 settings
Accessibility and performance: 11 settings
Diagnostics: 4 settings
network boundary
rules/zero-ads.json Static MV3 rules, blocks known YouTube ad request surfaces
document_start
early.css Zero-ad shell collapse plus feature-scoped anti-FOUC CSS
ytkit-main.js MAIN world, canPlayType patching for codec/format filtering
document_idle
runtime-bootstrap.js ISOLATED world, reads settings and starts the guarded loader (<150 KB)
runtime-core-loader.mjs dynamic module graph, core + download bootstrap + ytkit
features/* dynamic, settings-gated feature modules
background.js Service worker, fetch proxy, downloads, gated cookie handoff
- Split-context model, MAIN world for page API interception, ISOLATED world for extension APIs and DOM
- Lazy runtime graph, normal YouTube pages inject only the small bootstrap; the module catalogue is exposed through a per-session dynamic URL and loaded idempotently after the bootstrap turn
- Settings gate, a deferred feature module is skipped only when every feature it owns is switched off. Route gating is deliberately absent: a module is not withheld because of the page you happen to be on, since an SPA navigation would then have to fetch it mid-flight. Inline fallbacks preserve startup and userscript parity
- SPA-aware, hooks
yt-navigate-finish,yt-page-data-updated,popstate, andvideo-idattribute changes - Tiered feature init, critical features load synchronously, normal features in
requestAnimationFrame, lazy features inrequestIdleCallback - Crash recovery, features that crash 3 times auto-disable with console warning
- Conflict map, 6 conflict pairs enforced at both toggle and init time
- Trusted Types compliant, all innerHTML via
TrustedHTMLpolicy wrapper - Safe mode, append
?ytkit=safeto any YouTube URL, orytkit.unsafe()in console to exit
- Report sensitive security issues through private vulnerability reporting, not public issues.
- Zero-ad request rules use the static MV3
declarativeNetRequestAPI, are restricted to YouTube initiators and known advertising endpoints, and do not inspect or transmit request contents - Reversible anti-adblock recovery reports the visible YouTube enforcement selector and sampled playback state without touching the native dialog. Pausing Astra's own rules takes an explicit click, shows a 15-minute deadline, and restores them through a browser alarm even after the page closes
- EXT_FETCH proxy uses domain allowlist, blocks SSRF to private networks
- Request/response headers filtered (
Cookie,Set-Cookie, etc. stripped globally;Authorizationonly forwarded to explicit BYO-key/local service origins such as OpenAI/Anthropic/Ollama/MediaDL) - Response body capped at 10 MB, fetch timeout capped at 60s
- HTTP methods validated, download URLs protocol-checked (HTTP/S only)
- Authenticated downloads expose only four required secure YouTube cookie names behind a 20-second, one-use capability bound to the requesting tab and document after Astra Downloader proves native API v2 identity; legacy health tokens cannot release cookies
- Quick Links blocks
javascript:,data:, andvbscript:URIs and accepts only YouTube-owned destinations - Explicit CSP:
script-src 'self'; object-src 'self'; connect-srcallowlists documented provider origins. GitHub-full alone carries a scheme-scopedhttps://*connection lane because CSP cannot know a user-selected host in advance; browser permissions still require one exact host and never grant all sites.
Releases carry SHA256SUMS and the allowed-signers file from this
repository, and once a signing key is published (see below) a detached
SHA256SUMS.sig alongside them. Two commands, and both have to pass. The
first says who produced the list of hashes:
ssh-keygen -Y verify -f allowed-signers -I releases@astra-deck -n astra-deck-release -s SHA256SUMS.sig < SHA256SUMSThe second says your downloads match it:
sha256sum -c SHA256SUMSssh-keygen ships with Git for Windows, macOS, and every Linux, so there is
nothing to install. On Windows use Git Bash; PowerShell users can substitute
Get-FileHash for the second command.
Why both. Releases are built on one machine with no CI, so the artifacts and their checksum file come from the same place. Anyone who can forge one can forge the other, which makes an unsigned checksum file a corruption check and not a provenance claim. The signature is what makes it a claim about origin.
No signing key is published yet, so allowed-signers currently lists none and
the first command has nothing to check against. Until it does, treat releases
as unsigned and prefer the source tree.
- Fully open-source, every line of extension, companion, and build tooling is auditable
- No telemetry, no analytics, no tracking, zero data leaves the browser except to APIs you explicitly enable
- SBOM + checksummed manifest on every release build: a CycloneDX bill of materials for the npm tree, plus
release-manifest.jsonandSHA256SUMScovering every artifact and the manifest itself. Those let you confirm a download is intact. They do not prove who built it (signing-claim: unverified): no release signing key is published yet, soSHA256SUMS.sigis absent and the hashes travel from the same place as the files. Treat provenance as unverified untilallowed-signerscarries a key - External CRX signing key, maintainer-only, never in the repo or CI
- Credential scrub on settings export, API keys, tokens, and secrets are automatically stripped
- Profile-split permissions, store-safe builds retain the authenticated companion handoff but strip AI, Ollama, and user-selected remote origins; GitHub-full keeps those capabilities behind runtime prompts, with Cobalt limited to an authorized self-hosted instance
- Inspectable remote rules, optional Video Hider subscriptions preserve a hashed last-known-good payload with HTTP validators and visible freshness; stale rules are explicit and user-disableable, never silently replaced by a malformed response
- A repair channel that can only ever pause, the known-breakage feed names a shipped feature, an issue, and a version range; it cannot enable anything, write a setting, or supply copy, code, or links, and it is switchable off
- 26+ hardening passes documented in CHANGELOG with per-fix CVE/audit traceability
- Privacy policy covers data handling for every API origin the extension contacts
- SponsorBlock data attribution, the SponsorBlock and DeArrow features use SponsorBlock API/database data licensed under CC BY-NC-SA 4.0. Astra Deck may reformat titles and visualize segments; those presentation changes are made by Astra Deck and are not endorsed by SponsorBlock.
The optional Reaction Spammer feature lets you pick a set of YouTube live-chat reactions and fire them in a randomized loop at a chosen interval. It ships in two forms:
- Bundled in the MV3 extension as a Live Chat feature toggle, surfaces a floating launcher on
live_chatpages. - Standalone as
YT_Reaction_Spammer.user.js, a Tampermonkey / Violentmonkey userscript with no extension dependency.
Default: OFF, opt-in only. Rapid synthetic reactions could trigger YouTube's automated-behavior heuristics and result in account rate- limiting or flagging. The first time you open the launcher per profile, an amber toast surfaces this warning. The minimum interval is clamped to 500 ms in both the extension and the standalone userscript, faster than ~2 Hz is unsafe.
Use at your own risk.
Astra Deck ships with 11 bundled UI locales. These are extension only, YTKit.user.js bundles no locale catalogues, so the userscript tier is English:
| Code | Language |
|---|---|
en |
English (default) |
ar |
العربية |
de |
Deutsch |
es |
Español |
fr |
Français |
it |
Italiano |
ja |
日本語 |
ko |
한국어 |
pt_BR |
Português (Brasil) |
ru |
Русский |
zh_CN |
简体中文 |
The popup language dropdown's "Auto (browser default)" option shows the
detected language inline. The selection writes
chrome.storage.local._localeOverride; the in-page YouTube workspace
picks up the override on next page navigation. Feature-definition entries
inside ytkit.js resolve through generated locale keys with English fallbacks;
community translations welcome via PR against extension/_locales/<lang>/messages.json.
| Browser | Method | Status |
|---|---|---|
| Chrome / Edge / Brave | Extension (MV3) | Fully supported |
| Firefox 142+ | Extension (MV3) | Supported, but the XPI is unsigned, so a permanent install needs Developer Edition / Nightly / ESR; Release and Beta can only load it temporarily (see Firefox) |
| Chrome / Firefox | Tampermonkey / Violentmonkey | Supported (userscript) |
| Safari | Userscripts app | Limited |
Not supported: Mobile browsers and YouTube Studio. YouTube Music has
bounded theme/OLED/density compatibility; embedded /embed/:id pages have
bounded player/quality support, not full watch-page parity.
Astra Deck probes optional APIs before using them. The popup diagnostics bundle
includes the same generated matrix used by the runtime at
build/browser-capability-matrix.json, so support reports identify both the
available capability and the promised fallback.
The platform API adoption policy also records why six newer extension and web APIs are retained or deferred at the Chrome 120 and Firefox 142 floors. A capability doesn't get a second runtime path unless that path lets Astra remove more compatibility code than it adds.
| Capability | Chromium | Firefox | Fallback when absent |
|---|---|---|---|
| Built-in Summarizer | Chrome 138+ when the local model is exposed | Not exposed | Local Summary uses the configured BYO-key lane explicitly |
| Built-in Translator | Chrome 138+ when the requested language pack is exposed | Not exposed | Transcript translation says so and uses the configured BYO-key lane |
| Astra Downloader | Companion health endpoint reachable | Same companion contract | User-authorized self-hosted Cobalt path after an exact host grant; companion-only panels stay unavailable |
| Ollama | Local server at 127.0.0.1:11434 |
Same loopback contract | Selected remote/BYO provider, never an implicit provider switch |
| Document PiP | Chrome 116+ | Firefox 151+ | Standard video PiP |
| Language Detector | Chrome 138+ when the local model is exposed | Not exposed | Conservative text comparison |
| Prompt API | Chrome 138+ when Gemini Nano is ready | Not exposed | Transcript viewing/export remain available; no implicit remote Q&A |
npm ci
npm test
npm run check
# Python dependency auditing lives in the Astra Downloader repository
npm run build # Build store-safe + Chromium-store + GitHub-full artifacts
npm run build:userscript # Include userscript, SBOM, manifest, and SHA256SUMS
npm run check:zero-ads # Validate the static rule contract and packaged manifest
npm run smoke:zero-ads:live # Cold-load desktop YouTube and verify blocked requests + collapsed shells
npm run smoke:a11y # Check real extension pages plus controlled locale and accessibility states
npm run smoke:live-chat # Open a current YouTube live-chat frame and verify Astra attached
npm run smoke:firefox # Prove Firefox DNR, shell collapse, search, and SPA player behavior
npm run smoke:userscript-managers # Install and exercise YTKit in real Tampermonkey + Violentmonkey builds
npm run release:browser-smokes # Run Chromium, live-chat, Firefox, and userscript-manager release gates
npm run smoke:settings-overlay -- --desktop-only # Verify every extension settings destination at desktop sizes
npm run smoke:settings-userscript # Verify every userscript settings destination at desktop sizes
npm run release:prepare # Check + desktop browser gates + build + readiness
npm run release:prepare:no-crx # Same release gates, without any CRX or maintainer key
npm run release:sbom # Regenerate build/astra-deck-npm-sbom.cdx.json
npm run release:manifest # Regenerate release-manifest.json + SHA256SUMS
npm run release:readiness -- --require-pass # Generate release readiness JSON/Markdown
npm run release:health # Gate manifest, selectors, startup, and real-DOM smoke
npm run release:channels # Validate the checked-in channel ledger
npm run release:promote -- --channel userscript # Promote only after release:health passes
npm run release:rollback -- --channel userscript # Restore the recorded artifact without rebuilding
npm run release:verify-digests -- --tag vX.Y.Z # Compare uploaded asset digests after release upload
node build-extension.js --profile store-safe
node build-extension.js --profile chromium-store
node build-extension.js --profile github-full
node build-extension.js --bump patch # Bump and build
node build-extension.js --bump minor --with-userscriptThe UI test inventory drives 44 live builders against connected DOM fixtures. It catches wrong-parent mounts, duplicate children, missing state, and teardown that leaves controls behind.
The live browser gates are desktop-only and require network access, Firefox,
and geckodriver on PATH (or FIREFOX_PATH / GECKODRIVER_PATH). They use
throwaway Firefox profiles and never touch the normal browser profile. The
real-manager lane downloads only the versioned AMO XPI URLs pinned in
scripts/userscript-manager-fixtures.json and verifies each size and SHA-256
before temporary installation.
The live Firefox zero-ad smoke also records the home page, search, SPA player, blocked probe, and collapsed ad-shell states. Disposable profile cleanup is bounded to the profile path used by that run.
The pinned manager smoke passes with Violentmonkey 2.47.0 and Tampermonkey 5.5.0. It verifies the install flow and the shell-only userscript contract in fresh Firefox profiles.
The extension loads Player Dock from its preloaded feature module and keeps only a descriptor in the large content-script bundle. The generated userscript core uses the same module source, so runtime checks exercise the code that ships rather than a discarded fallback copy.
Video Hider follows the same layout. Its feed, filter-list, and direct-watch
runtime lives in the preloaded feature module, while ytkit.js keeps only the
settings descriptor needed if that module cannot load.
The Chromium zero-ad smoke tries the installed browser candidates in order. A
candidate without MV3 declarativeNetRequest support is reported and skipped,
so a local Chrome policy block does not prevent the Edge proof from running.
npm run build is safe for validation builds: if no maintainer key is
configured, CRX files are signed with ephemeral key material that is not
retained. Public release builds that include the userscript or bump a version
must use the external maintainer key via ASTRA_CRX_KEY_PATH, the default
%LOCALAPPDATA%\Astra-Deck\keys\ytkit.pem location, or
node build-extension.js --crx-key <path>.
Or skip the CRX entirely. --no-crx (equivalently ASTRA_SKIP_CRX=1)
produces the ZIP / XPI / userscript / SBOM / manifest / SHA256SUMS set with no
CRX at all, and therefore needs no key, without it a release build with no key
aborts before producing anything:
npm run release:prepare:no-crx # one command: build + SBOM + manifest + readiness
node build-extension.js --with-userscript --no-crx # or just the buildThis is the normal path for this project. Self-hosted CRX installs are
Linux-only on modern Chrome, and the last two published releases (v4.50.2,
v4.50.7) shipped no CRX at all, so the maintainer key does not gate a release.
Release readiness records the build as crxSigningMode: "none" and verifies
that build/ really contains no CRX before accepting it.
Outputs in build/ (the .crx files only when the build was not run with --no-crx):
astra-deck-chromium-store-chrome-v*.zip(download-free Chrome Web Store / Edge posture)astra-deck-chromium-store-firefox-v*.zip+.xpiastra-deck-store-safe-chrome-v*.zip+.crx(companion-capable self-hosted posture)astra-deck-store-safe-firefox-v*.zip+.xpiastra-deck-github-full-chrome-v*.zip+.crx(AI, local companion, optional self-hosted Cobalt)astra-deck-github-full-firefox-v*.zip+.xpiytkit-v*.user.js(with--with-userscript/npm run build:userscript)astra-deck-npm-sbom.cdx.json,release-manifest.json, andSHA256SUMSrelease-readiness/release-readiness.jsonandrelease-readiness/release-readiness.mdafternpm run release:readinessrelease-health.jsonafternpm run release:health; promotion refuses a failed or stale health report
release-channels.json records the active, last-known-good, and rollback
artifact for every extension profile/browser channel plus the userscript. A
promotion checks the exact manifest hash and candidate asset digest before
moving those pointers. If a release fails after publication, run
npm run release:rollback -- --channel <id> (or omit --channel for all
channels); rollback points the channel back to the stored artifact reference
and does not rebuild or mutate the failed artifact.
Companion release assets are intentionally separate from the default extension
build output. Only a companion release/staging pass should add
AstraDownloader.exe and AstraDownloader.exe.sha256 to build/. No
published release attaches the companion asset pair yet; verify the live
release asset list before promising the one-click setup path.
Requires Node 24+ (package.json engines and .nvmrc both pin it).
Most controls live in the settings panel; a few advanced flows are exposed only on window.* for power users:
| Entry point | What it does |
|---|---|
?ytkit=safe URL parameter |
Append to any YouTube URL to load with all features disabled (recovery mode). |
ytkit.unsafe() |
Exit safe mode from the DevTools console. |
window.__ytkitOpenAnalytics() |
Open the Watch History Analytics modal (30-day bar chart of watchTimeTracker data). |
window.__ytkitSearchTranscripts(query) |
Full-text search over the local IndexedDB transcript index (researchTranscriptIndex setting). Returns up to 200 hits. |
window.__ytkitClearTranscriptIndex() |
Wipe the local transcript index. |
window.__ytkitDiagnostics.download() |
Download a JSON bug report containing the diagnostic log ring buffer, selector-health snapshot, and active feature list. |
window.__ytkitProfiles |
Settings profile manager, .save(name), .load(name), .delete(name), .export(), .import(json). |
window.__ytkitAnnounce(message) |
Push a string into the polite screen-reader live region (requires globalAriaLiveRegion). |
| Doc | Audience |
|---|---|
| ROADMAP.md | Single source of truth for planned work, existing plans plus research-driven additions. |
| CHANGELOG.md | Per-version release notes |
| INSTALL.md | How to install on Chrome, Edge, Firefox, or as a userscript |
| HARDENING.md | Cumulative hardening / audit log (H1 → H25) |
| CONTRIBUTING.md | Repo layout, build / test commands, "Adding a Feature" guide |
| SECURITY.md | Supported versions and private vulnerability reporting policy |
| docs/architecture.md | Trust boundaries, data flow, where things live, conventions a new contributor needs |
| docs/cws-submission-checklist.md | Chrome Web Store submission preflight (manifest, privacy policy, screenshots) |
| docs/store-permission-rationale.md | Copy-paste store-review permission, host, and single-purpose rationale |
| docs/privacy-policy.md | Stable privacy policy source for README, homepage, CWS, and AMO listing links |
| docs/selector-fixture-workflow.md | How to refresh MHTML captures when YouTube DOM changes |
| docs/screen-reader-smoke.md | NVDA / JAWS / VoiceOver release-gate checklist |
| docs/predicate-sandbox-investigation.md | Threat model and design of the safe expression DSL for advancedLocalPredicate |
| Astra Downloader cookie threat model | Cookie flow and redirect-leak mitigations for Astra Downloader / yt-dlp |
| docs/signing-keys.md | CRX3 packaging key management |
| Project | Description |
|---|---|
| MediaDL | Local download server (yt-dlp + ffmpeg) with one-click installer |
| YoutubeAdblock | Standalone aggressive ad blocker with deeper proxy hooks |
| Chapterizer | Offline AI chapter generation via NLP |
MIT, Matthew Parker




