Skip to content
CAI
Software that uses CAICheck a score

puemos/hls-downloader

64.9

Adequate · 21 September 2026

19k

lines of production code

TypeScript

with JavaScript

4

measurements over time

CAI band scale
CAI trend line
CAI lens gauges

What this system is

This system is a browser extension that captures and downloads HLS media streams, processing them client-side into MKV or MP4 containers with embedded subtitles. It manages the full download lifecycle, including playlist detection, encryption handling, and disk-backed storage for large files, while providing a modern React-based popup interface for user configuration and monitoring. The architecture has been modernized to support Manifest V3, utilizing a monorepo structure with Vite, TypeScript, and Redux Toolkit for state management.

How it got here

2018 — Modernization and MV3 migration

11 changes.

The project underwent a comprehensive architectural overhaul, migrating from a legacy Create React App and Redux-based stack to a modern Vite, TypeScript, and pnpm monorepo structure. This period focused on upgrading to React 19, replacing Redux with Redux Toolkit, and refactoring the background service to support Manifest V3, while simultaneously removing obsolete UI components and state management modules.

2020–2024 — Core architecture and UI redesign

25 changes.

This period established the foundational architecture for a media processing extension, introducing core data models, service interfaces, and a Redux-based state management system. It implemented a robust download pipeline with disk-backed storage, MKV muxing, and subtitle support, while simultaneously rebuilding the user interface with a new design system and comprehensive popup modules.

2025–2026 — storage management and test coverage

8 changes.

This period focused on enhancing storage handling by introducing disk-backed muxing for large downloads and adding UI components for storage usage monitoring and cleanup. Comprehensive test suites were implemented across core, background, popup, and design-system modules to ensure reliability. Additionally, a dependency patch was applied to fix a CommonJS entry point issue in brace-expansion.

Features

Added FFmpeg WASM core for client-side media processing

The application now includes the FFmpeg WASM core library (ffmpeg-core.js) in the assets, enabling client-side video and audio processing capabilities such as merging, subtitle support, and MKV handling without relying on server-side transcoding.

src/assets/assets · high confidence

Added hooks for theme management and local storage persistence

The design-system now includes two new React hooks to support theming and data persistence. The \useTheme\ hook automatically detects the user's system color scheme preference (light or dark) and applies the corresponding class to the document root, keeping the UI in sync with OS settings. The \useLocalStorage\ hook provides a \useState\-like interface for persisting state to the browser's local storage, handling JSON serialization and deserialization while gracefully managing server-side rendering scenarios.

src/design-system/src/hooks · high confidence

Background listeners for playlist detection and tab state management

The background service now includes dedicated listeners to automatically detect HLS playlist requests (M3U8) and update the active tab state. When an HLS playlist is loaded, the system checks if the source is blocked via the blocklist, verifies the content type and HTTP status, and ensures the playlist hasn't already been added before storing it in the store. Additionally, it subscribes to the playlist's processing status to update the extension icon when a playlist becomes ready or encounters an error. A separate listener tracks tab activation to keep the current tab context synchronized.

src/background/src/listeners · high confidence

Initial Storybook configuration for the popup UI

Added Storybook setup files (main.ts, preview.tsx, and a webextension-polyfill mock) to enable isolated component development and documentation for the popup interface. The configuration integrates the design system and core library modules, and pre-seeds a Redux store with sample playlists, download jobs, and storage data so that components relying on state hooks can be previewed immediately.

src/popup/.storybook · high confidence

Initial release of the design system component library

The design system is now available as a public API, exposing a curated set of UI components including buttons, tabs, scroll areas, aspect ratios, separators, inputs, sliders, hover cards, badges, progress indicators, switches, selects, and cards. Additionally, the library provides utility hooks for local storage and theme management, along with shared utility functions, allowing consumers to import these primitives directly from the main entry point.

src/design-system/src · high confidence

Introduces core data models for media processing

The \src/core/src/entities\ module now defines the foundational data structures used throughout the application, including \Fragment\, \Level\, \Job\, \Playlist\, and \Key\. These models support the new capabilities for handling HLS streams, MKV output containers, and subtitle tracks by providing the necessary type definitions for media segments, processing jobs, and level metadata.

src/core/src/entities · high confidence

New Job module with detailed download status and storage tracking

The popup now includes a dedicated Job module (JobController, JobModule, JobView) that provides a polished, consistent workflow for managing downloads. Users can see granular status updates (Pending, Queued, Downloading, Saving, Ready, Completed, Error) with specific progress percentages and labels. The view displays storage information, including expected file size, stored bytes, and remaining space, helping users monitor disk usage. It supports actions like downloading, deleting, canceling, and saving jobs, with visual indicators for errors and active states.

src/popup/src/modules/Job · high confidence

New Redux store architecture for core application state

The application has introduced a new Redux-based state management system in the core store, organizing data into distinct slices for configuration, jobs, levels, playlists, storage, subtitles, and UI tabs. This change enables users to manage download settings (such as concurrency, output containers, and auto-delete options), track the status of download and save jobs, handle playlist and level metadata, monitor storage usage and cleanup, and manage subtitle downloads through a centralized, predictable state structure.

src/core/src/store/slices · high confidence

New Settings module with configurable download behavior and output format

The Settings page now features a dedicated module that allows users to manage download concurrency, set limits on active downloads (including an unlimited option), adjust fetch retry attempts, and toggle whether a save dialog appears after downloads. Users can also enable automatic deletion of source files after saving, choose between MP4 and MKV output containers for new downloads, and select a preferred audio language from a comprehensive list. Additionally, the module integrates storage information, displaying usage stats and providing options to refresh or clean up storage.

src/popup/src/modules/Settings · high confidence

New UI component library with Storybook documentation

The design system now includes a comprehensive set of accessible UI components, including AspectRatio, Badge, Button, Card, HoverCard, Input, Progress, ScrollArea, Select, Separator, Slider, Switch, and Tabs. Each component is implemented using Radix UI primitives and styled with Tailwind CSS, and is accompanied by Storybook stories to demonstrate usage and variants.

src/design-system/src/components · high confidence

New disk-backed download and muxing infrastructure with MKV and subtitle support

The background service now uses a new disk-backed storage system (OPFS) for large downloads to reduce memory pressure, replacing the previous in-memory approach. This change introduces a dedicated disk-muxing pipeline that offloads media merging to a background worker, enabling the output of MKV files and the embedding of WebVTT subtitles alongside video and audio tracks. The update also adds a new crypto decryptor service for handling encrypted content and a robust fetch loader with retry logic and byte-range support for reliable segment retrieval.

src/background/src/services · high confidence

New popup UI components and storage formatting utility

This change introduces a suite of new UI components for the popup interface, including BackButton, BottomSheet, DetailScreen, DetailSurface (with header, panel, and row sub-components), InlineConfirm, and ScreenHeader, alongside a Metadata component for displaying stream and audio properties. It also adds a formatBytes utility to handle human-readable byte formatting. These additions support a more polished and consistent workflow within the popup, specifically enhancing detail views and confirmation interactions.

src/popup/src/components · high confidence

New storage management hook for tracking usage and cleanup

A new \useStorageInfo\ hook has been added to the popup interface, providing a unified way to access storage state and trigger management actions. Users can now refresh storage data, initiate cleanup processes, and automatically reset the cleanup status after completion, all managed through Redux actions from the core storage slice.

src/popup/src/hooks · high confidence

New storage usage summary and low-storage warning in the popup

The popup now includes a StorageSummary component that displays current browser storage usage, available space, and quota status, along with badges for conditions like 'No fixed limit', 'Persistent', 'Low space', and 'Cleaned'. It also introduces a StorageBanner that appears when storage is low, prompting the user to clean up cached fragments. Both components provide a 'Clean storage' action that stops active downloads and clears cached data from the browser's storage.

src/popup/src/modules/Storage · high confidence

Playlist view now supports audio and subtitle track selection

The playlist interface has been updated to allow users to select specific audio and subtitle tracks for HLS streams. This change introduces a new controller and view layer that manages video, audio, and subtitle levels, automatically preferring tracks based on user language settings or default/auto-select flags. Users can now inspect track details, copy track URIs, and see encryption status for each media type before downloading.

src/popup/src/modules/Playlist · high confidence

Removals

Removal of Redux-based state management for downloads and tabs

The Redux store modules for managing downloads and browser tabs have been completely removed. This includes the deletion of action creators, action types, reducers, selectors, and utility functions for both the \downloads\ and \tabs\ areas. Consequently, the application no longer maintains download progress or active tab state via this specific Redux architecture.

src/modules/downloads · high confidence

Removal of legacy download saga implementation

The legacy download saga logic located in \src/modules/downloads/sagas\ has been removed. This includes the deletion of \index.js\, which previously handled playlist parsing, segment fetching, and blob assembly via a custom queue system, as well as \queue.js\, which provided the concurrent worker thread management for segment processing. Users relying on this specific code path for background downloads will no longer have this implementation available.

src/modules/downloads/sagas · high confidence

Removal of legacy public assets and manifest

The public directory's static assets, including the logo SVG, the HTML entry point, and the browser extension manifest, have been removed. This cleanup eliminates the previous manifest configuration (which included permissions like 'debugger' and 'webRequestBlocking') and associated UI resources, reflecting a shift away from the prior extension structure.

public · high confidence

Architecture

Introduction of core service interfaces for media processing

The core services module now exposes a set of TypeScript interfaces that define the contract for media processing capabilities. This includes IDecryptor for handling encrypted content, ILoader for fetching media segments with retry and byte-range support, IParser for handling HLS playlists and encryption inspection, and IFS for managing storage buckets, subtitles, and download preparation. These interfaces establish the foundational architecture for the download and playback pipeline, allowing implementations to be swapped or extended without altering the core logic.

src/core/src/services · high confidence

Behavioural changes

Background service refactored to TypeScript with MV3 build support

The background script has been rewritten from JavaScript to TypeScript, introducing a new build configuration via Vite that supports both Manifest V2 and Manifest V3 targets. This change replaces the previous Webpack-based setup and legacy JavaScript files (including the old parser and listener modules) with a structured TypeScript entry point. Users benefit from improved build reliability and the ability to run the extension on browsers requiring Manifest V3, while the background logic now strictly coordinates services as intended by the new architecture.

src/background · high confidence

Core download logic restructured into granular use-case modules

The core download engine has been refactored from a monolithic structure into a set of distinct, single-responsibility use-case modules (e.g., \download-single-fragment\, \decrypt-single-fragment\, \get-fragments-details\). This change introduces specific capabilities for handling HLS content, including robust fallback URL support for fetching playlists and fragments, configurable retry attempts, and support for byte-range requests. It also adds dedicated logic for subtitle tracks (downloading, text extraction, and storage), encryption inspection (validating AES-128 support), and storage management (calculating usage stats and bucket cleanup). Additionally, filename generation is now standardized with sanitization and NFC normalization to ensure consistent, safe file names.

src/core/src/use-cases · high confidence

Core download orchestration and subtitle support

The download controller layer has been restructured into a set of dedicated Redux-Observable epics that manage the full lifecycle of media downloads. This change introduces native support for downloading and bundling subtitles into MKV containers, automatically selecting the MKV format when subtitle tracks are present. A new download queue system enforces concurrency limits via a configurable max-active-downloads setting, ensuring stable resource usage. The workflow now includes automatic cleanup of temporary storage on initialization, auto-deletion of jobs after a successful save (if enabled), and robust error handling with retry logic for playlist and level fetching.

src/core/src/controllers · high confidence

Downloads module refactored with storage info and filtering

The Downloads module has been restructured into a controller-view pattern (DownloadsController and DownloadsView) that integrates storage usage data via the useStorageInfo hook. Users can now view storage details in a bottom sheet and see a warning when storage is near quota. The interface also includes a filter input to search through download jobs, with specific behavior to keep the filter visible if existing jobs do not match the search term.

src/popup/src/modules/Downloads · high confidence

Introduction of conditional blocklist and disk-backed download infrastructure

The background service now includes a new blocklist mechanism that prevents downloads from specified domains, which users can opt out of by setting the VITE\_NO\_BLOCKLIST environment variable. Additionally, the download pipeline has been refactored to use disk-backed file storage for large downloads, with an offscreen document handling the actual file preparation and release to ensure stability. State persistence logic has also been updated to correctly handle audio language preferences and maximum active download limits when loading from local storage.

src/background/src · high confidence

Introduction of utility function and core module reorganization

The design system now includes a new utility function, cn, which combines clsx and tailwind-merge to handle conditional class names more effectively. Additionally, the core module has been reorganized, with the background script moved from public/background.js to src/core/src/index.ts, indicating a structural change in how the core functionality is exposed and managed.

src/core/src, src/design-system/src/lib · medium confidence

Manifest updated to v5.5.0 with Manifest V3 support for Chrome

The extension configuration in src/assets has been updated to version 5.5.0. A new manifest.chrome.json file introduces Manifest V3 support for Chrome (requiring version 111+), utilizing a module-based service worker and the 'offscreen' permission. The existing manifest.json retains Manifest V2 for Firefox/Gecko (requiring version 128.0+) with a persistent background script. Additionally, a new offscreen.html asset is added to support the offscreen document capability required by the Chrome V3 implementation.

src/assets · high confidence

The extension now includes a dedicated About module that displays the application name, version, and description pulled from the browser manifest. The interface has been redesigned to feature a grid of action buttons allowing users to open the source code repository, report issues, view the privacy policy, and read the MIT license in new browser tabs. This replaces the previous implementation with a polished, consistent layout that includes an icon and attribution to the creator.

src/popup/src/modules/About · high confidence

New Redux store architecture with expanded state slices

The application's state management has been restructured to use a new Redux store configuration. This change introduces dedicated state slices for subtitles, storage usage, level inspections, and playlist preferences, which are now integrated into the root reducer. The store setup also incorporates redux-observable for side effects and redux-logger for debugging, providing a more modular and observable state management foundation.

src/core/src/store · high confidence

New build, publishing, and testing tooling scripts

The project has replaced the legacy Webpack-based build script with a new suite of Node.js scripts to support Manifest V3 builds, conditional blocklist variants, and automated Firefox Add-ons (AMO) publishing. Users can now build specific variants (e.g., MV2 vs MV3, with or without blocklists) via the new \build-variant.mjs\ script, which sets the appropriate environment variables and output paths. A new \publish-firefox.mjs\ script automates the signing and submission of MV2 packages to AMO, requiring specific API credentials and a clean git state. Additionally, new scripts for coverage reporting (\coverage-report.mjs\, \coverage-badge.mjs\) and local end-to-end testing (\e2e-local-browser.mjs\) have been added to improve development feedback loops, while a security verification script ensures patched dependencies behave as expected.

scripts · high confidence

New tab-based navigation with persistent state in the popup

The popup now uses a dedicated RouterView component to manage navigation between four tabs: Capture, Downloads, Settings, and About. This new architecture persists the user's selected tab in local storage, ensuring the view remains consistent across sessions, and integrates a storage usage banner that appears when quota is near.

src/popup/src/modules/Navbar · high confidence

Patched brace-expansion to fix CommonJS entry point

The patch for brace-expansion (v1.1.16) updates the module's main entry point to correctly resolve to the fixed implementation. Previously, the legacy CommonJS entry point was not wired to the corrected logic, which could lead to unexpected behavior. This change ensures that consumers of the library receive the secure and current version of the expansion logic.

patches · medium confidence

The popup interface has been migrated from a legacy Create React App setup to a modern Vite-based build system. This change introduces Tailwind CSS for styling, replacing the previous styled-components approach, and updates the underlying React infrastructure to React 18. For users, this results in a faster, more responsive popup experience with improved visual consistency and performance.

src/popup · high confidence

Popup UI restructured with new theme and routing entry points

The popup interface now initializes via a new App component that applies the design-system theme and renders a RouterModule for navigation. Styling is handled by a new index.css file that defines light and dark color palettes, sets the popup dimensions to 500x600px, and includes utility classes for scrollbars and motion transitions. The entry point (index.tsx) now explicitly sets up the React root with a Redux provider wrapping the app in StrictMode, and test setup includes jest-dom matchers.

src/popup/src · high confidence

Redesigned Sniffer with direct URL input and playlist previews

The Sniffer module has been rebuilt to support direct playlist URL entry via a new 'Direct' workflow, allowing users to manually add streams alongside auto-detected ones. The interface now includes a filterable list of captured playlists, the ability to copy all playlist URLs to the clipboard, and inline video previews for HLS streams to verify content before downloading. Individual playlists can be removed without clearing the entire list, and the view provides visual feedback for loading states and errors.

src/popup/src/modules/Sniffer · high confidence

Removal of Redux-based state management infrastructure

The application no longer uses Redux for state management. The store configuration, combined reducers (covering router, requests, tabs, and downloads), and the root saga (handling downloads) have been removed from the codebase, indicating a migration away from the previous state management architecture.

src/modules/store · high confidence

Removal of ejected Create React App configuration files

The project has removed the standard Create React App configuration files (including webpack, Jest, environment, and path configs) from the config directory. This indicates the application is no longer using the default CRA build setup and has likely been ejected or replaced with a custom build configuration, requiring users to rely on the new build system for development and production builds.

config · high confidence

Removal of legacy Redux and React Router Redux modules

The Redux action creators, reducers, selectors, and normalizr schemas for the requests module have been removed, along with the entire router module (history, middleware, reducer, and selectors) that relied on react-router-redux. This eliminates the previous state management and routing integration layer, indicating a migration away from the react-router-redux library and its associated Redux store structure.

src/modules/requests · high confidence

Removal of legacy UI components and theme assets

The application has removed the previous implementation of its core user interface, including the main App shell with its navigation tabs, the About view, the Downloads list with row styling, the Request list and detail views with playlist rows, and the associated SVG icon components. Additionally, the centralized color theme file defining the application's palette has been deleted. This change eliminates the old visual structure and styling assets from the codebase.

src/components · high confidence

Fixes

Large downloads now use disk-backed muxing

A new disk-mux-worker has been added to handle media muxing by mounting input fragments directly from the file system rather than keeping them entirely in memory. This change allows large downloads to be processed without exhausting browser memory limits, as the worker reads fragment files from storage and writes the final output to a disk-backed handle.

src/background/src/workers · high confidence

Test coverage

Added comprehensive test suite for core download logic; Added tests for the popup router controller; Added tests for the useLocalStorage hook; Expanded test coverage for background services.

Dependencies

Migrate to pnpm monorepo with security overrides and modern tooling

The project has switched from npm to pnpm, adopting a monorepo structure with separate packages for the core logic, background script, design system, and popup UI. This migration introduces pnpm overrides to patch several vulnerable dependencies, including brace-expansion, shell-quote, undici, and ws, ensuring a more secure dependency graph. The build tooling has been modernized by replacing Webpack and Babel with Vite and TypeScript, and the testing framework has moved from Jest to Vitest. Additionally, the React ecosystem has been upgraded to version 19, and Redux has been updated to version 5 with Redux Toolkit.

(dependencies) · high confidence

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

How this codebase got here

This is the PUBLIC form of this artifact. Findings are listed in full, but the details of SECURITY findings — which rule fired, in which file, on which line, and how to fix it — are deliberately withheld, and any secret-scanner results are excluded entirely. Where detail is absent here it was REMOVED FOR PUBLICATION; it is not missing from the analysis. The complete artifact is available from the repository owner.

Score

  • CAI 62 → 65 (+3.1)
  • Rubric changed (rubric-2026.08.19 → rubric-2026.09.15) — scores are not directly comparable.

Lenses

  • Code Health 94 → 89 (-4.9)
  • Architecture 90 → 92 (+2.0)
  • Maturity 62 → 67 (+4.4)
  • Readiness 57 → 64 (+7.4)
  • Security 61 → 62 (+1.4)
  • Accessibility 63 → 63 (+0.0)

Resolved (13)

  • Change coupling: DownloadsView.tsx ↔ SnifferView.tsx (src/popup/src/modules/Downloads/DownloadsView.tsx)
  • Coverage not included — suite not readable by the collector
  • Dependency hygiene not measured — dependency manifest found but not parsed for hygiene
  • High CVE: [GHSA redacted] (pnpm-lock.yaml)
  • High CVE: [GHSA redacted] (pnpm-lock.yaml)
  • High CVE: [GHSA redacted] (pnpm-lock.yaml)
  • High CVE: [GHSA redacted] (pnpm-lock.yaml)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • No exposed public API
  • Off-boarding risk: anonymized user #1
  • Test reliability not included

New (44)

  • Coverage not measured — JavaScript/TypeScript suite
  • DownloadsView.DownloadsView (cognitive 23) (src/popup/src/modules/Downloads/DownloadsView.tsx)
  • DownloadsView.DownloadsView (cyclomatic 23) (src/popup/src/modules/Downloads/DownloadsView.tsx)
  • FileTooLong: Job/JobView.tsx (src/popup/src/modules/Job/JobView.tsx)
  • FileTooLong: services/disk-backed-fs.ts (src/background/src/services/disk-backed-fs.ts)
  • FunctionTooLong: PlaylistPreview.PlaylistPreview (src/popup/src/modules/Sniffer/PlaylistPreview.tsx)
  • High CVE: [GHSA redacted] (pnpm-lock.yaml)
  • High CVE: [GHSA redacted] (pnpm-lock.yaml)
  • High CVE: [GHSA redacted] (pnpm-lock.yaml)
  • High CVE: [GHSA redacted] (pnpm-lock.yaml)
  • High CVE: [GHSA redacted] (pnpm-lock.yaml)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • Hotspot: scripts/e2e-local-browser.mjs (scripts/e2e-local-browser.mjs)
  • Hotspot: src/popup/src/modules/Sniffer/PlaylistPreview.tsx (src/popup/src/modules/Sniffer/PlaylistPreview.tsx)
  • …and 24 more

Changes since last survey

  • 5 commits — 5 feature/other, 0 fixes

By area

  • (root) — 3 commits
  • (repo) — 2 commits

Notable commits

  • change: build(deps): bump the production-dependencies group across 1 directory with 3 updates (#559)
  • change: build(deps-dev): bump the development-dependencies group with 18 updates (#572)
  • change: build(deps-dev): bump vitest from 4.1.10 to 4.1.11 (#569)
  • change: build(deps-dev): bump vitest from 4.1.10 to 4.1.11 in design-system (#568)
  • change: build(deps-dev): bump vitest from 4.1.10 to 4.1.11 in popup (#567)

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

Survey your own repository

puemos/hls-downloader was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.

About this page

  • The score is its most recent published measurement, taken on 21 September 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
  • Measured at commit c6392f2ff2a52762faaac9542dcf7c9ff20f0cf6 — the exact code this score is about.
  • Scored under rubric-2026.09.15 — the same rubric and the same method as every other entry in this index.
  • Measured by watchdog.canine.dev using codehealth-analyzer preprod-b84573e22831.