Raw JSON report machine-readable
{
"data": {
"repo": {
"topics": [
"anilist",
"anime",
"anime-sama",
"aria2",
"cli",
"french",
"hls",
"mpv",
"nyaa",
"python",
"streaming",
"terminal",
"vf",
"vostfr",
"yt-dlp",
"anime4k",
"downloader",
"movies",
"series",
"tui"
],
"is_fork": false,
"size_kb": 1765,
"has_wiki": true,
"homepage": "https://github.com/freedy237/freeflix-cli",
"languages": {
"Lua": 2019,
"Shell": 16580,
"Python": 744819,
"PowerShell": 4697
},
"pushed_at": "2026-07-27T17:22:03Z",
"created_at": "2026-05-28T05:05:04Z",
"owner_type": "User",
"updated_at": "2026-07-27T17:23:45Z",
"description": "Watch movies, series & anime from your terminal — multi-source, multi-language, no browser, no ads.",
"is_archived": false,
"is_disabled": false,
"license_spdx": "GPL-3.0",
"default_branch": "main",
"license_spdx_raw": "GPL-3.0",
"primary_language": "Python",
"significant_languages": [
"Python"
]
},
"owner": {
"blog": null,
"name": null,
"type": "User",
"login": "freedy237",
"company": null,
"location": null,
"followers": 0,
"avatar_url": "https://avatars.githubusercontent.com/u/205066866?v=4",
"created_at": "2025-03-26T17:50:43Z",
"is_verified": null,
"public_repos": 3,
"account_age_days": 487
},
"license": {
"state": "standard",
"spdx_id": "GPL-3.0",
"raw_spdx": "GPL-3.0",
"file_present": true,
"scorecard_found": true,
"profile_has_license": true
},
"activity": {
"releases": [
{
"tag": "v1.9.3",
"kind": "patch",
"published_at": "2026-07-27T17:22:39Z"
},
{
"tag": "v1.9.2",
"kind": "patch",
"published_at": "2026-07-23T06:06:47Z"
},
{
"tag": "v1.9.0",
"kind": "minor",
"published_at": "2026-07-18T06:10:06Z"
},
{
"tag": "v1.8.5",
"kind": "patch",
"published_at": "2026-07-07T15:10:10Z"
},
{
"tag": "v1.8.4",
"kind": "patch",
"published_at": "2026-07-07T14:58:38Z"
},
{
"tag": "v1.8.3",
"kind": "patch",
"published_at": "2026-07-06T20:56:17Z"
},
{
"tag": "v1.8.2",
"kind": "patch",
"published_at": "2026-07-06T07:03:40Z"
},
{
"tag": "v1.8.1.post1",
"kind": "other",
"published_at": "2026-07-05T19:59:36Z"
},
{
"tag": "v1.8.1",
"kind": "patch",
"published_at": "2026-07-05T19:21:49Z"
},
{
"tag": "v1.8.0",
"kind": "minor",
"published_at": "2026-07-03T23:42:02Z"
},
{
"tag": "v1.7.9",
"kind": "patch",
"published_at": "2026-07-01T08:16:53Z"
},
{
"tag": "v1.7.8",
"kind": "patch",
"published_at": "2026-06-30T22:21:23Z"
},
{
"tag": "v1.7.7",
"kind": "patch",
"published_at": "2026-06-29T20:20:40Z"
},
{
"tag": "v1.7.6",
"kind": "patch",
"published_at": "2026-06-28T22:22:21Z"
},
{
"tag": "v1.7.5",
"kind": "patch",
"published_at": "2026-06-27T15:57:11Z"
},
{
"tag": "v1.7.4",
"kind": "patch",
"published_at": "2026-06-27T09:04:25Z"
},
{
"tag": "v1.7.3",
"kind": "patch",
"published_at": "2026-06-26T10:20:30Z"
},
{
"tag": "v1.7.2",
"kind": "patch",
"published_at": "2026-06-22T16:50:26Z"
},
{
"tag": "v1.7.1",
"kind": "patch",
"published_at": "2026-06-20T16:40:12Z"
},
{
"tag": "v1.7.0",
"kind": "minor",
"published_at": "2026-06-20T12:34:18Z"
},
{
"tag": "v1.6.12",
"kind": "patch",
"published_at": "2026-06-20T03:12:15Z"
},
{
"tag": "v1.6.11",
"kind": "patch",
"published_at": "2026-06-18T07:57:04Z"
},
{
"tag": "v1.6.10",
"kind": "patch",
"published_at": "2026-06-17T19:59:48Z"
},
{
"tag": "v1.6.8",
"kind": "patch",
"published_at": "2026-06-12T14:00:15Z"
},
{
"tag": "v1.6.7",
"kind": "patch",
"published_at": "2026-06-10T19:16:40Z"
},
{
"tag": "v1.6.6",
"kind": "patch",
"published_at": "2026-06-09T17:34:46Z"
},
{
"tag": "v1.6.5",
"kind": "patch",
"published_at": "2026-06-08T16:41:00Z"
},
{
"tag": "v1.6.4",
"kind": "patch",
"published_at": "2026-06-06T06:31:00Z"
},
{
"tag": "v1.6.3",
"kind": "patch",
"published_at": "2026-06-06T05:46:39Z"
},
{
"tag": "v1.6.2",
"kind": "patch",
"published_at": "2026-06-06T05:32:48Z"
},
{
"tag": "v1.6.1",
"kind": "patch",
"published_at": "2026-06-06T05:20:47Z"
},
{
"tag": "v1.6.0",
"kind": "minor",
"published_at": "2026-06-05T21:47:08Z"
},
{
"tag": "v1.5.9",
"kind": "patch",
"published_at": "2026-06-04T20:21:20Z"
},
{
"tag": "v1.5.8",
"kind": "patch",
"published_at": "2026-06-04T17:54:44Z"
},
{
"tag": "v1.5.7",
"kind": "patch",
"published_at": "2026-06-04T15:59:07Z"
},
{
"tag": "v1.5.6",
"kind": "patch",
"published_at": "2026-06-04T11:35:28Z"
},
{
"tag": "v1.5.4",
"kind": "patch",
"published_at": "2026-06-04T10:21:47Z"
},
{
"tag": "v1.5.3",
"kind": "patch",
"published_at": "2026-06-04T09:23:57Z"
},
{
"tag": "v1.5.2",
"kind": "patch",
"published_at": "2026-06-04T08:10:58Z"
},
{
"tag": "v1.5.1",
"kind": "patch",
"published_at": "2026-06-03T20:18:18Z"
},
{
"tag": "v1.5.0",
"kind": "minor",
"published_at": "2026-06-03T19:16:17Z"
},
{
"tag": "v1.4.5",
"kind": "patch",
"published_at": "2026-05-31T20:59:23Z"
},
{
"tag": "v1.4.4",
"kind": "patch",
"published_at": "2026-05-31T16:46:04Z"
},
{
"tag": "v1.4.3",
"kind": "patch",
"published_at": "2026-05-31T16:20:13Z"
},
{
"tag": "v1.4.2",
"kind": "patch",
"published_at": "2026-05-31T15:56:59Z"
},
{
"tag": "v1.4.1",
"kind": "patch",
"published_at": "2026-05-31T15:35:11Z"
},
{
"tag": "v1.4.0",
"kind": "minor",
"published_at": "2026-05-31T15:23:24Z"
},
{
"tag": "v1.3.3",
"kind": "patch",
"published_at": "2026-05-30T17:28:16Z"
},
{
"tag": "v1.3.2",
"kind": "patch",
"published_at": "2026-05-30T17:13:54Z"
},
{
"tag": "v1.3.1",
"kind": "patch",
"published_at": "2026-05-28T10:38:45Z"
},
{
"tag": "v1.3.0",
"kind": "minor",
"published_at": "2026-05-28T10:34:53Z"
},
{
"tag": "v1.2.0",
"kind": "minor",
"published_at": "2026-05-28T10:15:32Z"
},
{
"tag": "v1.1.7",
"kind": "patch",
"published_at": "2026-05-28T08:01:56Z"
},
{
"tag": "v1.1.6",
"kind": "patch",
"published_at": "2026-05-28T07:50:32Z"
},
{
"tag": "v1.1.5",
"kind": "patch",
"published_at": "2026-05-28T07:36:58Z"
},
{
"tag": "v1.1.4",
"kind": "patch",
"published_at": "2026-05-28T07:31:22Z"
},
{
"tag": "v1.1.3",
"kind": "patch",
"published_at": "2026-05-28T07:24:45Z"
},
{
"tag": "v1.1.2",
"kind": "patch",
"published_at": "2026-05-28T07:20:16Z"
},
{
"tag": "v1.1.1",
"kind": "patch",
"published_at": "2026-05-28T07:17:04Z"
},
{
"tag": "v1.1.0",
"kind": "minor",
"published_at": "2026-05-28T07:01:30Z"
},
{
"tag": "v1.0.0",
"kind": "major",
"published_at": "2026-05-28T05:06:37Z"
}
],
"recent_commits": [
{
"oid": "785a9fb2e5b68ff8b6aae756ee152443ba7d9a0e",
"body": "Source network errors no longer crash the app (clean panel + resilient\nget_website_url via cf_get). New Android/Termux mode: playback delegated\nto mpv-android via intent + dedicated first-run setup. See CHANGELOG.md.",
"is_bot": false,
"headline": "release: 1.9.3 — crash-proof sources + Android (Termux) mode",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-07-27T17:21:44Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "d32a8241ef70aa22fd5d21bc63b216accdf332b5",
"body": "New platform_android.py : detect Termux/proot Android + hand playback to\nan external Android player (mpv-android, then VLC) via an 'am start' intent\nthat reads FreeFlix's local proxy over the shared loopback (headers +\nm3u8 rewriting preserved). No display needed.\n\n- New 'android' player, auto-offer\n[…]\nre_runtime_deps no longer\n downloads x86_64 static builds on Android. The 'player' tool counts as\n present via mpv-android.\nUnit-tested (detection, intent fallback, pkg/apt install, wizard routing).",
"is_bot": false,
"headline": "feat: Android (Termux/proot) mode — playback + first-run setup",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-07-27T16:29:27Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "889175d66b27b598811ad9d22069265bc102b8b3",
"body": "A 'Connection reset by peer' (curl 56) in Anime-Sama's get_website_url\npropagated uncaught and killed the whole app. Now:\n- the source-handler dispatch is wrapped in a guard that shows a clean\n 'source unreachable' panel and returns to the source list (any source,\n any network/DNS/TLS error);\n- get_website_url routes through cloudflare.cf_get (retries transient\n resets, then plain, then DoH) so a flaky first hit doesn't fail outright.",
"is_bot": false,
"headline": "fix: a source network failure no longer crashes the app (R4)",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-07-27T16:28:51Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "96b460d96f99eb4133757bb116f49cdd4677ae5f",
"body": "…resilience, mpv IPC binge\n\nSee CHANGELOG.md. A3 cache, B2 posters (Windows+Linux bugs) + kitty/iterm,\n#5 hot-patchable selectors, mpv JSON-IPC live resume + auto-next episode.",
"is_bot": false,
"headline": "release: 1.9.2 — HTTP cache, reliable posters+kitty/iterm, extractor …",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-07-23T06:05:45Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "a759e23e252809d34d7a6cb2f86a6a25923dd8a8",
"body": "New mpv_ipc.py : cross-platform client (AF_UNIX socket / Windows named\npipe) for mpv's --input-ipc-server. A background PlaybackMonitor saves\ntime-pos LIVE (survives a crash — the old lua hook only wrote on clean\nexit) and learns the end reason (eof vs quit).\n\nplay_video launches mpv with --input-ip\n[…]\n EOF, the next one auto-plays\nafter a cancelable countdown (confirm_or_timeout); if the user quit early,\nit still just asks. Unit-tested against a fake mpv IPC server (pos/dur\ntracking + eof-vs-quit).",
"is_bot": false,
"headline": "feat: mpv JSON-IPC — live resume + auto-play-next / binge",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-07-23T06:01:49Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "5e7cbf25e41ff6af34753c6453c52718a582eb1e",
"body": "New scraping/resilient.py : fragile CSS selectors live in a table that a\nremote data/selectors.jsonc can override (background-fetched like portals),\nso a broken source can be fixed for everyone WITHOUT a release. first_text/\nfirst_attr try a list of selectors in order (a renamed class still resolves\nvia the next fallback). Anime-Sama search + get_series now ride on it, with\ntoday's selectors as defaults (zero behavior change until a patch is pushed).",
"is_bot": false,
"headline": "feat: hot-patchable extractor selectors + multi-strategy fallback (#5)",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-07-23T05:32:51Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f14d799a7f5151ee34606e0646ef9d83611f36b6",
"body": "Windows: force encoding='utf-8' when capturing chafa's symbol output —\ntext=True decoded as cp1252 and raised UnicodeDecodeError, so posters\nsilently never rendered during search on Windows (only the direct\nfull-screen render after selecting worked).\n\nReliability (both OSes): stop caching FAILED ren\n[…]\nect_image_protocol() hands chafa a real graphics format\n(kitty on Kitty/Ghostty/WezTerm, iterm on iTerm2) when the env AND chafa\nversion confirm support; otherwise defers to chafa's own autodetection.",
"is_bot": false,
"headline": "feat: reliable posters + kitty/iTerm2 image protocol (B2)",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-07-23T05:24:18Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "f7c14954e107c9e3b0354347f33632650d22e566",
"body": "New httpcache module (per-URL JSON on disk, TTL freshness, CachedResponse\nshim). Wired into Anime-Sama search/series/season (cache-buster-safe key)\nand the Cinemeta films/series metadata reads. Repeat browsing is instant\n(1.8s -> ~30ms). Settings gains a 'Clear HTTP cache' action with size.\nBest-effort: any I/O error behaves as a miss, never breaks a fetch.",
"is_bot": false,
"headline": "feat: persistent HTTP cache for catalogue reads (A3)",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-07-23T05:17:47Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "cb4cb0b1f479cf4b5d8c144121e240f4d395ce04",
"body": "…13 Windows)\n\n_find_in_tar passed filter='data' unconditionally; the PEP 706 backport is\nabsent on older 3.9 (e.g. the 3.9.13 Windows runner), raising TypeError and\nsilently failing the managed ffmpeg install. Fall back to a plain extract.",
"is_bot": false,
"headline": "fix: tar extract falls back when 'data' filter is unavailable (py3.9.…",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-07-18T06:15:28Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "05182ee76ca8d0b3bd04095c4984bfb3f62509f2",
"body": "_have_managed appends .exe on Windows, so the fixture files must too.\nWas a pre-existing Linux-only assumption; the new Windows CI leg caught it.",
"is_bot": false,
"headline": "test: make managed-binary tests Windows-aware (.exe suffix)",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-07-18T06:12:05Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "551a131728af8ae4744119fd67f77aee6984c339",
"body": "Perf\n- Proxy Flask démarré paresseusement à la 1re lecture (plus de Flask ni de\n port ouvert au lancement) ; options DNS déplacées dans net_config léger.\n- Badges d'épisodes : listing de dossier mis en cache (fin des ~6 stat/ligne).\n\nSécurité\n- Garde anti-SSRF sur le proxy local (refus des IP loopb\n[…]\nns (Ubuntu + Windows, py3.9/3.12) : ruff + pytest.\n- Tests clavier multi-plateformes, SSRF, démarrage proxy, santé des sources.\n\nNettoyage\n- Code mort retiré (get_language_flag, cloudflare.available).",
"is_bot": false,
"headline": "1.9.0 — optimisation & robustesse (Linux + Windows)",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-07-18T06:09:00Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "011b02f9c9a40dcec48f9fc3ab5028176bb00d4c",
"body": "_read_menu_key Windows path: read the \\x00/\\xe0 special-key scan code\nunconditionally (the kbhit() guard made arrows do nothing in classic console),\nand drain the \\x1b[… VT sequence with a short bounded wait so VT arrows aren't\nmistaken for a lone Esc. Focus events still ignored; isolated Esc still = back.",
"is_bot": false,
"headline": "1.8.5 — Windows: fix arrow keys (1.8.4 regression)",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-07-07T15:07:55Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "03e215b655c4b621c91272ce13924aee11ab66a0",
"body": "- Phantom Esc / self-close on Windows: add a msvcrt path to _read_menu_key that\n drains the full escape sequence and ignores focus (\\x1b[I/\\x1b[O) / mouse\n events (only an isolated \\x1b is Esc); handle \\x00/\\xe0 arrow prefixes. Use\n _read_menu_key in select_with_preview's non-raw path too (the se\n[…]\nder download no longer re-triggers \"install the\n players\"). _have() also resolves mpv.net/VLC via get_mpv_path/get_vlc_path on\n Windows so an installed-but-not-on-PATH player isn't reported missing.",
"is_bot": false,
"headline": "1.8.4 — Windows: robust key reader (phantom Esc) + stop player re-prompt",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-07-07T14:56:46Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "42e32a393ee1ff0033fa231d1987ce0948fd0e1c",
"body": "… themes, downloads manager\n\n- Search history: tracker.add/get_search_query; get_user_input `history=` shows a\n recent-searches helper with ↑/↓ recall; wired into anime_sama/french_stream/\n papystreaming.\n- New releases: recent.py daemon fetches newer seasons for history shows (non-\n blocking); \"\n[…]\ne_settings\n with a live preview panel.\n- Downloads manager: _downloads_summary (disk free + total size) as select_from_list\n top=; play/delete finished files; loop UX. select_from_list gains `top=`.",
"is_bot": false,
"headline": "1.8.3 — search history, background new-releases, settings categories,…",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-07-06T20:55:14Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "3fcf54a5792ab23384f452bf6c6a26920a04babe",
"body": "…+ startup bar\n\n- Home dashboard (_home_dashboard): greeting + stats line (this week / streak /\n in-progress) + Continue-watching carousel with resume/watched/downloaded\n badges, from local data. select_from_list gains a `top=` renderable rendered\n above the menu (home passes the dashboard).\n- Mo\n[…]\n startup splash + remaining Anime-Sama\n in-flow messages.\n- Fix the startup loading bar: proportional catch-up easing (x0.5, 0.06 floor)\n so it fills to 100% within a few frames instead of crawling.",
"is_bot": false,
"headline": "1.8.2 — enriched home dashboard + source order/badges + translations …",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-07-06T07:02:12Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "73690d7ad03318c98021a10354a8c8b040dcaf38",
"body": "Post-release of 1.8.1 (PyPI is immutable, so these ship as .post1).\n\n- anime_sama.get_series: replace the split('panneauAnime(\"')[2:]+break parser\n (stopped early → dropped Dr Stone S3 P2 / S4 + parts) with a regex over the\n whole page. AniList continue flow benefits too.\n- Phantom Esc: _read_menu\n[…]\nrains the full escape sequence and ignores focus\n (\\x1b[I/\\x1b[O) / mouse / paste events; only an isolated \\x1b is Esc. Add\n disable_terminal_reports() called at startup and after every player exit.",
"is_bot": false,
"headline": "1.8.1.post1 — Anime-Sama missing seasons + phantom-Esc / self-close fix",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-07-05T19:57:37Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "d8d289de83f0f1f82e78d598753591e0cc84e847",
"body": null,
"is_bot": false,
"headline": "docs: add 'Why FreeFlix' value-prop showcase to README",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-07-05T19:23:24Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "67ece522662d717470f29e1b7540a2f8a764a689",
"body": "…loaded)\n\n- select_from_list: '/' enters a type-to-filter mode (view of original indices,\n returns the original index; Enter picks, Esc clears). Status bar + i18n keys.\n- Episode badges via player_manager.episode_badges(series, season, ep) using the\n same md5(window_title) key as resume: ✓ watched (tracker.watched_episodes,\n marked on successful play in play_episode_flow), ▸NNm resume (saved position),\n ⬇ downloaded (file on disk). Wired into anime_sama / coflix / french_stream.",
"is_bot": false,
"headline": "1.8.1 — '/' filter in lists + episode badges (watched / resume / down…",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-07-05T19:17:20Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "54f09b96866eee96c3dc47b21c74e3a38753341c",
"body": "…pass\n\nNavigation\n- Breadcrumb trail rendered above every menu (crumb_reset/crumb_push + scoped\n `crumb` CM in cli_utils; wired in home/sources/settings and the anime_sama,\n coflix, french_stream, papystreaming flows). Left-truncates on long trails.\n- '?' opens a help overlay listing all shortcuts\n[…]\n get_hls_link; B904 raise-from in cloudflare; B007\n unused loop vars; E401 split imports; E741 renames; W29x whitespace; noqa-\n document the deliberate late imports (E402). Renumber run_setup steps.",
"is_bot": false,
"headline": "1.8.0 — navigation UI (breadcrumbs, ? help, status bar) + full audit …",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-07-03T23:41:11Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "acce237f43c9c6014c7ace4e7d5c340b62cac041",
"body": "VLC\n- Hide VLC's libav/libva/codec console flood (run stdout/stderr to DEVNULL,\n pass --quiet) in both proxy and direct modes.\n- Cap the HLS adaptive ladder to the chosen resolution via --adaptive-maxheight\n so VLC stops ramping to the highest variant and ignoring the picked quality.\n\nCleanup\n- Re\n[…]\ning/player, subtitles) so Ctrl-C / real errors propagate.\n- Add missing network timeouts: anime_sama/coflix `_get` wrappers + portal\n get/head calls, cloudflare.get wrapper, goldenanime requests.get.",
"is_bot": false,
"headline": "1.7.9 — VLC quiet + quality cap, internal cleanup (excepts, timeouts)",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-07-01T08:15:52Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "eb9b24637d43f50ccfc5ebc08abfb15e55736a3b",
"body": "Linux install\n- mpv & aria2 static-build repos 404'd → install both via the distro package\n manager (apt/dnf/pacman/zypper/apk) with a prompt; add VLC for parity. ffmpeg\n stays self-managed. The deps cache is version-aware so updaters re-check.\n\nNerd Font\n- run_setup installs the Nerd Font on ever\n[…]\nguage/quality badges in the player menu via _player_label.\n- toast() helper; settings confirmations use it instead of print+pause.\n\nOther\n- Update notice shows only `uv tool upgrade` (we ship via uv).",
"is_bot": false,
"headline": "1.7.8 — Linux install fix, Nerd Font dep, AniList flow upgrade, comfort",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-30T22:20:12Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "da9bf08bc4ba129ade46f2f578fa23d63087ca05",
"body": "…s set)",
"is_bot": false,
"headline": "Restore 'Continue from AniList' home-menu entry (shown when a token i…",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-29T20:56:32Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "382f2e5a84d23238e8c1ab60bf715fae7260c501",
"body": null,
"is_bot": false,
"headline": "docs: remove Project layout and French summary sections from README",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-29T20:29:28Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "7c626ad156303cd63e4b2fe3032ee7080ed59487",
"body": null,
"is_bot": false,
"headline": "docs: drop stale v1.7.2 callout from README",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-29T20:24:29Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "a82b0d60c254e59290caf3f341336039b49e9dea",
"body": "Add assets/logo.png and a centered header (logo + title + badges + tagline)\nusing an absolute raw URL so it renders on both GitHub and PyPI.",
"is_bot": false,
"headline": "docs: add FreeFlix-CLI logo + centered README header",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-29T20:23:10Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "4ab4264db7d401de31b208790e9a1dc76d84a098",
"body": "- All backends download into the hidden .temp/ dir; the final file is placed in\n Downloads (or the season subfolder) only on success. aria2c used to write the\n .mp4 directly into Downloads, leaving a partial there on a dropped connection.\n Interrupted downloads now stay in .temp/ (resumable) and \n[…]\n Downloads\" lists interrupted downloads (list_interrupted_downloads) with % (HLS\n via .ytdl) or MB, and offers Resume (resume_download) / Delete. .temp is now\n excluded from the playable-files walk.",
"is_bot": false,
"headline": "1.7.7 — no partial files in Downloads + resume interrupted downloads",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-29T20:19:34Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "9e8380e547b3a605057dc9177dd24833050b313e",
"body": "…older\n\ntest_download_fixes.py created a stable temp dir under the REAL DOWNLOAD_DIR\n(~/Downloads/FreeFlix/.temp/<title>) then \"cleaned up\" with\nrmtree(dirname(dirname(d1))) == rmtree(~/Downloads/FreeFlix), wiping the user's\nactual downloads on every pytest run. Clean up only the dirs the test created.",
"is_bot": false,
"headline": "test: stop test cleanup from deleting the real ~/Downloads/FreeFlix f…",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-28T22:37:42Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "4c2c6c56ecf375294e08cc8a29b317a37372367a",
"body": "… Font\n\n- Esc on Linux: arrow menus now read keys with a raw reader that detects a lone\n Esc via a 50 ms peek (readchar blocks on Esc waiting for a 2nd byte on POSIX,\n so Esc did nothing on Linux). Esc reliably steps back one level on every OS.\n- Anime4K on Windows: the real cause was mpv.conf's s\n[…]\nrd_font early-returned before); plus a one-time launch\n check (ensure_nerd_terminal_font) applies it when icon style is already nerd.\n- Hint \"Space: select\" at the bottom of the episode multi-select.",
"is_bot": false,
"headline": "1.7.6 — Esc works on Linux, Anime4K fixed on Windows (mpv.conf), Nerd…",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-28T22:21:27Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "9f02beb8933923d566557f9700c9add75cf21ae3",
"body": "Season downloads\n- Episode list offers a plain \"Download\" → choose quality → multi-select which\n episodes to grab (Space toggles, `a` all). Episodes already on disk are\n detected, shown locked and skipped. Each season goes into its own folder\n (Downloads/FreeFlix/<Series - Season>/) with clean pe\n[…]\npystreaming moved to EN sources and renamed (no \"VF\").\n- Subtitle download OFF by default.\n- Translate default-player names (download/manual/browser).\n- Remove \"Continue from AniList\" home-menu entry.",
"is_bot": false,
"headline": "1.7.5 — episode-select downloads, Esc=back everywhere, faster posters",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-27T15:56:19Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "62f8490fd5c5ac0c8f775c17ca8f7e1691f603fc",
"body": "…fixes\n\nNew source\n- Papystreaming (FR films & series): TMDB-based French search; series get a\n selectable seasons/episodes menu (via Cinemeta) instead of typing numbers;\n streams resolved through the shared GoldenMS resolvers.\n\nWindows fixes\n- Anime4K shaders failed to load on Windows: input.conf\n[…]\nr now eases/climbs smoothly toward the next\n milestone while each tool installs, instead of jumping 20/40/80.\n\nHome menu\n- Browse sources moved to right after Resume (before History/Downloads/Stats).",
"is_bot": false,
"headline": "1.7.4 — new source Papystreaming (FR), Windows Anime4K + install-bar …",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-27T09:03:35Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "85f01661cc7ca47a7ab43bff41f87d119d33cf44",
"body": "…ash/approx glyphs",
"is_bot": false,
"headline": "install.ps1: keep it pure ASCII (PS 5.1 encoding trap) - replace em-d…",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-26T10:21:57Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "30ba45663cc102f0d52895d77fae53a974a3083a",
"body": "…+ installer hardening\n\nDownloads\n- Esc Esc cancels a download (single + season batch); hint shown in the box.\n- aria2c progress bar fixed: reader keeps only progress lines, so aria2c's\n \"[#… (X%) …]\" line isn't overwritten by the summary block's FILE:/---- junk\n before the UI reads it -> the bar \n[…]\nss --force, so\n the one-liner always upgrades existing installs to the latest fixes.\n\nCleanup\n- Fixed latent NameErrors (print_warning / re not imported), removed duplicate\n i18n keys and dead code.",
"is_bot": false,
"headline": "1.7.3 — Esc-Esc cancel download, Esc→source list, Coflix search, 3.9 …",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-26T10:19:36Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "292bb58605fe7d68300169f2c0c3633c68412fb9",
"body": "…ice; ETA regex\n\n- play_episode_flow: ⬇ Download now shows a quality picker instead of\n silently using players[0]; also passes title=window_title so the file\n is named properly\n- player_manager: revert --console-log-level to notice (progress lines\n come from --summary-interval=1 regardless of log level)\n- progress.py: ETA regex handles aria2c format (1m30s, 1h30m)",
"is_bot": false,
"headline": "fix: ⬇ Download picks quality + passes title; revert log-level to not…",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-22T17:37:11Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "c25090779a78c841fa4e319d6adf2448b1fb9ee8",
"body": "…back\n\n- _pick_player_for_batch(): analyse le 1er épisode, probe les qualités,\n laisse l'utilisateur choisir le serveur/qualité pour tout le batch\n- _download_one_episode(): preferred_player en priorité, fallback ensuite\n- download_episodes_batch(): relaye preferred_player aux workers\n- mis à jour les 4 handlers (Anime-Sama, Coflix, French-Stream, French-Manga)",
"is_bot": false,
"headline": "feat: quality selection before batch download + preferred player fall…",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-22T17:15:01Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "086ecf3e937a4bc2c296fd5b213c2c0c9338b2ac",
"body": "- player_manager: --console-log-level=info instead of notice so\n aria2c outputs progress lines (they are at info level)\n- progress.py: widen ETA regex to handle aria2c format (1m30s, 1h30m)",
"is_bot": false,
"headline": "fix: aria2c progress bar not updating (log-level info + ETA regex)",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-22T17:04:26Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "ef0d33077da3110b16920dc704d0a76b4d9a2d51",
"body": null,
"is_bot": false,
"headline": "fix: update README release notes to v1.7.2",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-22T16:52:44Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "85fe6f1d7f0aed3b87a1786be22cf4a2ccb8352f",
"body": "- player_manager: aria2c log-level warn→notice (progress bar fix)\n- play_episode_flow: add ⬇ Download option before player selection\n- Anime-Sama / Coflix / French-Stream / French-Manga: add 📥 Download ALL episodes in each season\n- Coflix: fetch .players before batch download\n- bump version to 1.7.2",
"is_bot": false,
"headline": "v1.7.2 — add download option + batch download per season",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-22T16:49:30Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "0355635e50ce0ba81e1e1b86d12e49631ddaa322",
"body": null,
"is_bot": false,
"headline": "gitignore: add .opencode/; remove tracked plan file",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-20T20:13:57Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "a2cf83162e6f6a3cf587758dcdd44ed69a2398cc",
"body": null,
"is_bot": false,
"headline": "v1.7.1 — bump version",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-20T16:39:54Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "3bf5e707c8d9e878f4a33083b4c8fb6a0cae487b",
"body": "…handlers/*, player_manager, scraping/*, languages, tracker, notifications), remove AutoFlix references (proxy, notifications), remove player remote config fetches",
"is_bot": false,
"headline": "v1.7.1 — massive cleanup: remove unused imports (anilist, cli_utils, …",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-20T16:39:20Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "5deb909b1afdc8c145a841381c7c775f6fbe7448",
"body": "…independent)",
"is_bot": false,
"headline": "player.py: remove AutoFlix upstream remote config fetch (FreeFlix is …",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-20T16:22:49Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "dbc4dff95bbc700bda9fbec2ca26e5b74d4c3f8f",
"body": "…d Python download stall",
"is_bot": false,
"headline": "install.ps1: install Python via winget before uv tool install to avoi…",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-20T16:15:35Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "ae0d7d85a387c3447cd8279cc75fbb19ba581ee4",
"body": "…sage",
"is_bot": false,
"headline": "install.ps1: detect uv on disk even if not on PATH; show download mes…",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-20T16:08:20Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "3fb0696b9b20476a06eac82101d11920d2de8466",
"body": null,
"is_bot": false,
"headline": "install.ps1: remove Out-Null so uv progress is visible",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-20T13:35:38Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "5d4e2057682d31cd9442782f29c0fc9bfc114828",
"body": "… block)",
"is_bot": false,
"headline": "install.ps1: download uv binary directly (no iex, no execution-policy…",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-20T12:54:39Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "85ed8cf892a9e2f68f6a440617fe734629e2f501",
"body": null,
"is_bot": false,
"headline": "install.ps1: fix execution policy — add Bypass at process level",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-20T12:52:16Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "dc617edae09a10eaa1bdd338490157626d2729e5",
"body": null,
"is_bot": false,
"headline": "README: add Windows one-liner in install section",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-20T12:42:55Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "bdd18868a759ac9f42762f61d2b620ab4a4d3507",
"body": null,
"is_bot": false,
"headline": "README: keep one-liner Linux/macOS only — Windows uses install.ps1",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-20T12:41:34Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "8334f7e252c30bb56bbfba46195cd18a039076fe",
"body": null,
"is_bot": false,
"headline": "README: add Windows one-liner via WebClient",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-20T12:40:31Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "209008ca9e498a142028d7a8eb21af676a2a49f1",
"body": "…p/--version, fix docstring URL; setup_assistant.py: add aria2c+mpv managed sources for Linux",
"is_bot": false,
"headline": "README: installation section clearer, fix curl URL; install.py: --hel…",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-20T12:38:01Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "b8e786a15ec87fb9ea28e6e11543815a375b90a0",
"body": null,
"is_bot": false,
"headline": "1.7.0 — update README: new one-liner installer, doctor, cleanup",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-20T12:29:17Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "3a093dce43e6a3f37794f8c74412930850883f71",
"body": null,
"is_bot": false,
"headline": "1.7.0 — remove ArkAnime source (CDN dead), clean up",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-20T12:23:36Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "32c0d108880cdc5f13bfac57f699c0b18999e94d",
"body": "- French-Stream: add fsschal challenge detection in _get() (was only in _post())\n- French-Stream: defensive og:title fallback (title tag / URL slug)\n- French-Stream: guard #s-list parsing against missing element\n- Coflix/Anime-Sama/Player: guards against missing h1/iframe/span/a/img/h2/source\n- clou\n[…]\n DoH)\n- french_stream._get()/_post(): DoH fallback on connection/timeout errors\n- french_stream.search(): catch network timeouts instead of crashing\n- tests: 19 regression tests for scraper resilience",
"is_bot": false,
"headline": "1.6.12 — fix: scraper resilience + DoH DNS fallback",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-20T03:11:28Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "ff14fde447b463901bd12d722fcb977f43bee29e",
"body": null,
"is_bot": false,
"headline": "1.6.11 — fix: DNS timeout on all sources (remove DoH from scrapers)",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-18T07:56:05Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "72b1d6ce6ed19b7eb752befdd222005086e914a0",
"body": null,
"is_bot": false,
"headline": "1.6.10 — feat: Nerd Font auto-detection + auto-install",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-17T19:58:52Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "5011432d6be8e3affcbf59cbb89c31e0b20e1102",
"body": null,
"is_bot": false,
"headline": "1.6.9 — fix: French-Stream search (fsschal cookie)",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-17T19:45:48Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "d4a8809d112a7ab4363118c516a01dbc4be9e414",
"body": null,
"is_bot": false,
"headline": "1.6.9 — fix: French-Stream search blocked by JS challenge",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-17T19:38:10Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f4615db2bf470e569536e775cb9b2069dddda81a",
"body": null,
"is_bot": false,
"headline": "1.6.8 — feat: quality selection for downloads",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-12T13:59:27Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "735b381938539d479380bc40f8d42382b2d8de99",
"body": null,
"is_bot": false,
"headline": "1.6.7 — fix: episode title duplicate in downloads (Coflix full path)",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-10T19:15:35Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "5b982ae6021048541dba2d10bbe1f103daf2deff",
"body": "…ions)",
"is_bot": false,
"headline": "1.6.6 — fix: Python 3.9 compatibility (from __future__ import annotat…",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-09T17:33:37Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "165f919cff9109c6b4b180ca0be99354efaa9a4c",
"body": null,
"is_bot": false,
"headline": "1.6.5 — bump version to 1.6.5 for PyPI release",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-08T16:39:52Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f702119485ffa6ad308e9b1cd376652478a4f249",
"body": null,
"is_bot": false,
"headline": "1.6.5 — fix: duplicate filename in downloads + resume after interruption",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-08T16:32:35Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "c3711bac0a8eb24652a3c4b013a8d48e3fc184cb",
"body": "…ort path)\n\nLaunching `freeflix` had ~2.5 s of dead air before anything rendered. Cause:\nscraping/player.py and scraping/config.py each fetched remote JSONC overrides\n(players_info, new_url, kakaflix_players, source_portal) SYNCHRONOUSLY at import\ntime — four blocking network calls before main() eve\n[…]\nre ready long before any extraction. The vidmoly domain\ncorrection is re-asserted after the remote merge so it always wins.\n\nimport freeflix_cli.main: ~3.8 s -> ~0.6 s. Also trimmed the splash timing.",
"is_bot": false,
"headline": "1.6.4 — fix: instant startup (defer remote config fetches off the imp…",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-06T06:30:14Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "c037945492e716f330ca44fdea24fd8ff7496b0b",
"body": "…ria2c)\n\nWith --downloader aria2c, yt-dlp only emits its overall \"(frag a/b)\" progress at\nthe end of an HLS download, so the bar stayed on \"starting…\" the whole time then\nsnapped to 100%. Switch HLS back to yt-dlp's native --concurrent-fragments 16,\nwhich reports progress continuously -> the bar climbs live. It's just as fast for\nHLS (parallel fragments) and still keeps the folder clean (fragments in a temp\ndir, deleted after). aria2c stays for direct .mp4.",
"is_bot": false,
"headline": "1.6.3 — fix: real-time HLS download progress (native fragments, not a…",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-06T05:45:50Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "0c1ae2ccd80e135053c9594772c9a988fad172e1",
"body": "Downloads\n- HLS uses yt-dlp + aria2c (x16) again for speed, but routes every fragment and\n the .part file to a temp dir (-P temp:) that is deleted afterwards, so the\n Downloads folder only ever holds the final .mp4 (no .part-FragN / .aria2).\n- Progress fraction is driven solely by yt-dlp's overall\n[…]\ny -> the bar\n no longer jumps around.\n\nDownload box\n- Renders full-screen (screen=True), centered: resize reflows cleanly with no\n offset/leftover and it erases on exit. Width-clamped to a tidy box.",
"is_bot": false,
"headline": "1.6.2 — downloads: aria2c speed kept, folder clean, rock-stable bar",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-06T05:32:03Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "1a8b311112dcbdc7f6852efae987219883af529d",
"body": "Downloads\n- HLS uses yt-dlp native --concurrent-fragments instead of aria2c-per-fragment,\n which spammed the folder with *.part-FragN / *.aria2 files and made the\n progress bar jump per fragment. One .part -> one .mp4, stable overall bar.\n- Sweep leftover fragment/temp clutter before and after eac\n[…]\nne\n level) across Anime-Sama, Coflix, French-Stream, French-Manga, GoldenMS,\n GoldenAnime — back out without completing the flow.\n\nLaunch\n- Smooth 0->100% splash sequence instead of an abrupt flash.",
"is_bot": false,
"headline": "1.6.1 — clean downloads (no fragment clutter), back buttons everywhere",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-06T05:19:46Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "be96b4a01c84fa475da0babc2bd841623587e11f",
"body": null,
"is_bot": false,
"headline": "docs: add CHANGELOG.md with full 1.6.0 notes",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-06T04:54:56Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "7b392c86a70e13311ca19aaee34f4d12062aaa09",
"body": "Search / browse\n- Live preview pane (poster + title + genres/metadata) on every source:\n Anime-Sama, Coflix, French-Stream, French-Manga (TMDB thumbs), GoldenMS\n (Cinemeta), GoldenAnime (AniList covers). Shared make_preview() shape.\n- Preview pane perfected: per-URL image cache (no re-download on \n[…]\nll.sh / install-mac.sh.\n\nRobustness\n- Removed Wiflix entirely (handler, scraper, objects).\n- cf_get: 3 retries + system-DNS (no-DoH) fallback; graceful handling for\n network failures in source flows.",
"is_bot": false,
"headline": "Release 1.6.0 — preview pane on all sources, grouped menu, progress bars",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-05T21:46:13Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "88f5e8067844dd07a9c83c319851d6f2a4ca5fb7",
"body": "… spinners\n\nAdd icons.py with two glyph sets (emoji default, Nerd Font opt-in) and a\ncentral iconify() applied in cli_utils (headers, menus, messages, stats,\nabout, update banner) so a single \"Icon Style\" setting flips the whole UI\n— no per-string edits. Menus get a full-width themed selection bar with\ndisplay-column-accurate padding (handles wide emoji, never wraps). Slow\nscraping/loading calls are wrapped in a rich spinner.",
"is_bot": false,
"headline": "feat: emoji/Nerd Font icon system, full-width selection bar, scraping…",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-04T20:19:07Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "e790ca372f980cc6a83124f40757726cbc1b07c4",
"body": "The proxy now counts the bytes streamed to the player (HLS segments +\nMP4). player_manager shows a live \"Data used: X MB\" counter that grows\nas the cache fills, then the total at the end. The player menu labels\nmpv as \"(recommended)\".",
"is_bot": false,
"headline": "feat: live data-usage meter during playback + mpv marked recommended",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-04T20:19:07Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "6426ab1a2e62a263bb85c489f3922685fe67c36b",
"body": "The cover was read from <img id=\"coverOeuvre\">, which is missing on many\ncatalogue pages (One Piece, Frieren…), leaving the poster blank \"when it\nfelt like it\". Read the always-present og:image meta first, fall back to\ncoverOeuvre/data-src, and make it absolute. Also retry the image download\na few times since Anime-Sama covers are on raw.githubusercontent.com,\nwhich rate-limits intermittently.",
"is_bot": false,
"headline": "fix: Anime-Sama poster always shows (og:image + download retry)",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-04T20:19:07Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "9a4e7629840b21f1d00671331ed9221ecf24f08c",
"body": "Show the cover + summary at selection for the movie/series sources, so\nposters now appear on every source. GoldenMS uses the Cinemeta/TMDB\nposter; French-Stream uses the page thumbnail or the search-result\nimage. Fix a French-Stream scraper bug that double-prefixed the site\norigin onto already-absolute TMDB image URLs.",
"is_bot": false,
"headline": "feat: anime/movie posters for GoldenMS and French-Stream too",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-04T17:53:41Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "241a4d95ed56a3bd59c446404ff8de8d3f7ec070",
"body": "When the chosen player can't be resolved at play time, FreeFlix now\noffers to install it (mpv / VLC) via the OS package manager and retries,\ninstead of only showing \"not installed\". setup_assistant.install_media_player\nis OS-aware (dnf/apt/pacman/zypper/apk, brew, winget mpv.net/VideoLAN.VLC)\nand player_manager._resolve_or_install checks presence first so nothing\nalready installed is touched.",
"is_bot": false,
"headline": "feat: install mpv/VLC on demand at playback if missing",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-04T17:53:41Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "a9a26d5d434b666129a4192fb0fd1295300761f0",
"body": "setup_assistant now offers to install chafa via the OS package manager\n(dnf/apt/pacman/zypper/apk/brew/winget) on first launch, and the three\ninstall scripts include chafa. On Windows, first-launch installs mpv.net\nand VLC via winget, and player_manager.get_mpv_path() resolves mpv.net's\nmpvnet.exe (and winget shims) so FreeFlix can actually launch mpv there.",
"is_bot": false,
"headline": "feat: install chafa in setup + scripts; Windows mpv/vlc bootstrap",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-04T15:58:02Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "d677574b801dd91b7078d2b8bbcf9f37b0ed34c1",
"body": "Add terminal_image.py: draws anime cover art inside the terminal via\nchafa (sixel when available, coloured Unicode blocks otherwise), with a\ngraceful no-op fallback when chafa is missing. Posters + a short summary\nare shown when an anime is selected, for French-Manga (TMDB/og:image\ncover), Anime-Sam\n[…]\n: menu option labels are truncated to the terminal width so\nthey never wrap and break the live render; poster size scales with the\nterminal; the splash logo degrades (full / compact / hidden) by size.",
"is_bot": false,
"headline": "feat: anime posters in the terminal (chafa) + responsive UI",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-04T15:58:02Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "3d0eb34f049a49d0697ce82422a125c4369df841",
"body": "Previously --setup only re-ran the dependency assistant, never the\nlanguage choices. check_language_setup/_prompt_anime_language now accept\nforce=True so --setup redoes both the anime content language and the\ninterface language. The choices remain changeable individually from\nSettings.",
"is_bot": false,
"headline": "feat: freeflix --setup re-runs the language wizard (anime + interface)",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-04T15:21:17Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "92b0c54d3b7bf4174b968c4abbd9af5b91e589a8",
"body": "Resuming a French-Manga entry did nothing because handle_resume had no\nbranch for the provider. Add resume_french_manga (Continue / Watch again\n/ Cancel) and wire the dispatch. Also normalise relative series URLs\nstored in older history entries (get_episodes now makes them absolute),\nwhich is what made resume report \"no episodes found\". Factor the play\nloop into a shared _play_episodes helper.",
"is_bot": false,
"headline": "fix: French-Manga resume from history (dispatch + relative URLs)",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-04T15:21:17Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "68577bced4a1702753f5baeb48c244e830bd09fa",
"body": "Add the v1.5.6 changelog, list French-Manga among the sources (drop\nCoflix), fix the position-resume script filename, refresh the French\nsummary, and add an educational-purposes / no-hosting / DMCA disclaimer.",
"is_bot": false,
"headline": "docs: README — French-Manga source, v1.5.6 features, disclaimer",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-04T11:34:24Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "37beed21e3e9d7e5fd476cf3e482397feda8e247",
"body": "…tering & subtitles\n\nOn the very first launch FreeFlix now asks the anime content language\n(English VO/sub vs French VF/VOSTFR) BEFORE the interface language.\nThat choice drives which sources are listed — English shows Anime-Sama,\nGoldenAnime, GoldenMS and Nyaa; French shows Anime-Sama, GoldenAnime,\n[…]\nnAnime/GoldenMS subtitle search now\nfollow the same content language. Adds an \"Update Anime Language\" entry\nin Settings and reorders the source menu (anime top, movies/series\nmiddle, torrents bottom).",
"is_bot": false,
"headline": "feat: anime-language first-launch wizard, content-language source fil…",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-04T11:34:24Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "d69aee80ae0e6dcd20212789dc8d12f53268ae37",
"body": "New scraper + handler for w16.french-manga.net: DLE ajax search,\nnewsId lookup, and manga_episodes_api.php for per-episode VF/VOSTFR\nplayers. Registers vidzy and luluvid (vidhsareup.io) players, which\nthe upstream players_info.jsonc doesn't list, by re-injecting the\nFreeFlix DEFAULT_PLAYERS extras after the remote list loads.",
"is_bot": false,
"headline": "feat: add French-Manga source (anime VF/VOSTFR, vidzy + luluvid)",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-04T10:20:32Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "2326eca590ff436d549feb5d0605a2835fd9fc75",
"body": "Quality selection previously swapped the master playlist URL for a\nsingle video-only variant, which dropped the separate EXT-X-MEDIA\naudio renditions (GoldenAnime/anizone \"video but no sound\"). Revert\nto applying the choice via mpv --hls-bitrate on the untouched master,\nso audio renditions are preserved.",
"is_bot": false,
"headline": "fix: keep audio when selecting quality on anizone/HLS streams",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-04T10:20:22Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "33866d0d6e8beac37c52fca439ef758708b1e9c0",
"body": "…ceful filemoon\n\nCoflix : removed from selectable sources — its player aggregator\n(lecteurvideo.com) is Cloudflare-protected, nothing is playable. Handler\n+ scraper kept (season parsing repaired, Cloudflare message) but not\nregistered.\n\nFrench-Stream / shared extractors (player.py) :\n- uqload : 'lis\n[…]\nruto all return a source again.\n\nplayer_manager : endpoint choice is content-aware — an HLS stream\n(.m3u8/.txt) always uses /stream even under an ext:mp4 config (uqload now\nreturns m3u8 with ext:mp4).",
"is_bot": false,
"headline": "fix: revive providers — drop Coflix, repair uqload/fsvid/anizone, gra…",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-04T09:23:08Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "cabcb5c832b4e2e5bc2f524b7cb1e239184453e9",
"body": "… all players\n\nBuilds on the 1.4.5 quality menu so it triggers for EVERY multi-quality\nsource, not just vidmoly. Four fixes, all in play_video's single probe :\n\n1. Per-host probe headers : the probe fetched the master with the\n generic anime-sama referer, so hosts that check referer (embed4me,\n \n[…]\nd') with a clear 'pick another source' message\n instead of a cryptic mpv failure.\n\nNote: reverted a stream=True peek (curl_cffi early-break could hang) to\na plain GET — HLS playlists are small text.",
"is_bot": false,
"headline": "feat(v1.5.2): universal quality selection — all providers, all hosts,…",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-04T08:10:06Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "efef48c41d05f2c8a0ba9ce7af1e72d7e3d34eee",
"body": "anime-sama.to updated its layout : the series title moved from\n<h4 id='titreOeuvre'> to a plain <h1>, and the genres anchor is gone\non some pages. The copied autoflix get_series did\nsoup.find('h4', {'id':'titreOeuvre'}).text and crashed with\nAttributeError: 'NoneType' on every series now.\n\nMade get_\n[…]\n title falls back h4#titreOeuvre → h1 → URL\nslug ; cover and genres are guarded (empty if missing). Seasons\n(panneauAnime parsing) are unchanged. Verified on Asobi Asobase (was\ncrashing) and Dr Stone.",
"is_bot": false,
"headline": "fix(anime-sama): robust get_series (h4#titreOeuvre dropped for h1)",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-03T20:17:08Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "2fff2a3d450578e63a5bbc41b4f00a1bf5cfba9f",
"body": "Sprint 1 of the v2 roadmap, shipped as 1.5.0 :\n\n- Splash screen : FreeFlix ASCII wordmark at launch, themed + tagline +\n version (new splash.py ; skipped on tiny terminals).\n\n- Colour themes (new themes.py) : Default, Catppuccin Mocha, Dracula,\n Nord. Each maps semantic roles (accent/header/border\n[…]\ns so the genre breakdown populates.\n\n- i18n : all new strings translated FR.\n\nVerified : 4 themes switch colours correctly, splash renders, stats\ndashboard aggregates (incl. genres) and renders in FR.",
"is_bot": false,
"headline": "feat(v1.5): splash screen, colour themes, stats dashboard",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-06-03T19:15:11Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "83e1b2d2a68f6a050c7398fdbac762d5a128de19",
"body": "1. Quality selection : when a resolved stream is a multi-variant HLS\n master (e.g. vidmoly's 1080p+480p '_,n,l,.urlset'), FreeFlix now\n fetches the master, parses the variants, and prompts the user to\n pick a quality before playback. The choice is applied to mpv via\n --hls-bitrate=<bandwidth\n[…]\n value on quit. Also switched script-opts reading to\n get_property_native (cleaner). Verified : pos=12.75 now written on\n quit, and --start=<pos> applied on the next launch of the same\n episode.",
"is_bot": false,
"headline": "feat: HLS quality selection + fix position-resume (lua time-pos bug)",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-05-31T20:58:36Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "d9580fb3f4ec4acfc8ce897b09280a186bac8cda",
"body": "Two user-reported issues :\n\n1. Anime-Sama VF showed fewer sources on FreeFlix than autoflix (notably\n missing embed4me). Root cause : FreeFlix read the animes-sama.fr\n mirror, autoflix reads anime-sama.to (via the anime-sama.pw portal).\n Different mirrors expose different players per episode.\n\n[…]\nct_delay_max=10\n (a single network hiccup could pause up to 10 s). Reverted to a\n light, vanilla-like cache (256 MiB / 30 s readahead, no reconnect\n delay) — matching the fast autoflix behavior.",
"is_bot": false,
"headline": "fix(anime-sama): copy autoflix's scraper wholesale + revert mpv cache",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-05-31T16:45:16Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "fad52055dea614d02a13619e0fb20e8a4f4fdf60",
"body": "…robe\n\nTwo findings from a full autoflix-vs-freeflix repo scan :\n\n1. The tuned mpv.conf was GLOBAL (~/.config/mpv/), so it applied to the\n user's normal 'mpv file.mkv' too — Anime4K shader compile + huge cache\n on every video, not just FreeFlix. autoflix used vanilla mpv, which is\n why it 'fel\n[…]\nplayer.py (HLS extraction) was confirmed byte-identical to autoflix, so\nstream resolution speed was never the difference — the real wins were the\nproxy session reuse (1.4.2) and this config isolation.",
"is_bot": false,
"headline": "perf: isolate mpv config to FreeFlix + parallel anime-sama language p…",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-05-31T16:19:28Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "991bd4668453d6f57cdc77afe90f57b4f38944c7",
"body": "Root cause of 'the buffer never gets ahead even at 320p' : the proxy\ncreated a brand-new curl_cffi session for EVERY segment. Each one re-did\nthe DoH DNS resolution (an HTTPS round-trip to 1.1.1.1) plus a fresh\nTLS handshake to the CDN — ~200-600 ms of pure setup overhead per\nsegment, with zero conn\n[…]\nfreeze, which felt like 'always catching up'. 2s gives short,\ndiscreet micro-pauses instead.\n\nOn a transport error the thread session is reset before retrying so a\ndead keep-alive handle isn't reused.",
"is_bot": false,
"headline": "perf(proxy): reuse session per thread — 2.5× faster segment fetch",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-05-31T15:56:10Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "97ce3b376d2cf8008c3cdb24ef420795a14e3b18",
"body": "v1.4.0's cache-on-disk=yes made the cache fill noticeably slower :\nmpv's on-disk cache has extra bookkeeping overhead vs RAM, even on a\nfast SSD, and the 2h/8GB readahead made the cache bar crawl.\n\nWith 8+ GB RAM there's no reason to use disk. Reverted to RAM cache,\nsized generously :\n cache-on-dis\n[…]\nnd has zero I/O overhead,\nso the buffer fills at full network speed again. Still buffers far\nenough ahead to survive a long connection drop.\n\nLow-RAM users (<8 GB) can lower demuxer-max-bytes to 1GiB.",
"is_bot": false,
"headline": "fix(mpv): switch back to fast RAM cache (4 GiB) instead of disk",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-05-31T15:34:21Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "0da6f81d5ccb289fb0ce9b7eb65d500adb8aa3f7",
"body": "Per user request : instead of a 250 MB RAM cache, mpv now pre-buffers\nas much of the video as the network allows — up to the end of the\nepisode/film — into an on-DISK cache.\n\n- cache-on-disk=yes → cache goes to disk, not RAM\n- cache-dir=~/.cache/mpv\n- demuxer-max-bytes=8GiB → up to a f\n[…]\nin ~/.cache/mpv.\n\nResult : once a video has had a moment to buffer, it plays to the end\neven if the connection dies completely. Combined with cache-pause +\nkeep-open, network drops become a non-issue.",
"is_bot": false,
"headline": "feat(mpv): buffer the whole episode/film to disk cache",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-05-31T15:22:33Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "c103ad9d45a47d7c7af0612f02c382813a99d054",
"body": "The systemd timer used OnBootSec=15min + OnUnitActiveSec=24h, which on\nan already-running machine produced 'Trigger: n/a' / 'NEXT: -' — i.e.\nit fired once and then never scheduled a next run.\n\nSwitched to the robust daily idiom :\n OnCalendar=daily\n Persistent=true (catches up if the machine\n[…]\nescription\nstrings to 'FreeFlix'.\n\nNote for existing users : re-toggle the notification setting (Settings →\nDaily New-Episode Notifications, off then on) to regenerate the timer\nwith the new schedule.",
"is_bot": false,
"headline": "fix(notifications): use OnCalendar=daily so the timer actually re-fires",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-05-30T17:27:30Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "87d09108c1fe50600fcbdec91b18884ab10be874",
"body": "Two bugs surfaced on 'L'Atelier des Sorciers' :\n\n1. parse_episodes_from_js crashed with 'max() iterable argument is\n empty' when a season page had no (or only empty) 'var epsN' player\n arrays. Now skips empty players and returns [] cleanly, so the\n handler shows 'no episodes' instead of a trac\n[…]\nned portal cache (users with a cached .to will\n re-resolve on next launch since the cache is keyed and TTL'd).\n\nVerified : L'Atelier des Sorciers → saison1 → vostfr/vf/va, 27 ep-lang\npairs, no crash.",
"is_bot": false,
"headline": "fix: empty-season crash + point remote config at our own repo",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-05-30T17:13:01Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "9a34d6e95f9f44800661b0069f692b99fd6054ce",
"body": "Each freeflix launch tries to fetch 4 remote JSONC files (portals,\nplayers_info, new_url, kakaflix_players) from PaulExplorer's upstream\nrepo. When GitHub raw is slow or unreachable, the 5 s timeout × 4 was\ndelaying startup by ~20 s and dumping a 4-line curl error per file.\n\nSince the local override\n[…]\nead of 20 s\n- single one-line warning per file (was 4-line curl traceback)\n- format: ' · offline-mode : remote <file> unavailable, ...'\n\nFunctionality unchanged — local defaults remain authoritative.",
"is_bot": false,
"headline": "fix(config-loader): quieter & faster remote fetch failure",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-05-28T10:37:58Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "9056fb67c7b2aa4fe8e2f87abedcf1dff8ea05ce",
"body": "Haruna is removed because :\n- Video track switching never reliably worked through its Qt wrappers\n- input.conf bindings (Anime4K toggle, track cycle) were inconsistently\n picked up between Haruna versions\n- mpv + the freeflix proxy already covers all the same use cases with\n better behavior\n- Main\n[…]\ninstall.sh / install-mac.sh\n- All Haruna mentions in README.md\n\nmpv remains the recommended player and gains the full benefit of the\nNvidia/AMD PRIME offload that was previously split between the two.",
"is_bot": false,
"headline": "refactor: remove Haruna player support",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-05-28T10:34:05Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "f6988cbb67378bc896668830d7b9ff6182f1e781",
"body": "Big quality-of-life release. When freeflix is installed via uv/pip/pipx,\nrunning it for the first time now offers to install everything else :\n\n- Tuned mpv.conf + input.conf + position-resume lua hook\n- Anime4K shaders (Mode A_S + A_VL, downloaded from bloc97/Anime4K)\n- Haruna config mirror (on Linu\n[…]\n wizard at any time\n- freeflix --version print installed version\n- freeflix --help usage\n\nThe wizard remembers if the user declined (setup_declined in tracker)\nso it won't pester on every launch.",
"is_bot": false,
"headline": "feat: first-launch setup wizard + cross-platform + AMD GPU support",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-05-28T10:14:40Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "10684dbfc247bda3190d72c9bfe86187e32e68a0",
"body": "Tuned for the 'leave mpv open, come back later' use case where the\nconnection may drop or thrash in the meantime.\n\nCache : 250 MB / 3 min readahead :\n - cache-secs=180, demuxer-readahead-secs=180\n - demuxer-max-bytes=250M, demuxer-max-back-bytes=80M\n\nGraceful behavior when network dies :\n - cache\n[…]\nose if stream ends\n - network-timeout=120 → tolerate slow segments (was 60s)\n - reconnect_delay_max=10 → softer reconnect cadence\n\nLose Wi-Fi for ~3 minutes mid-episode without losing your place.",
"is_bot": false,
"headline": "feat(mpv): 250 MB cache + survive-connection-drops mode",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-05-28T08:00:59Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "d1dec3630534d5524b68c7c4c09a0d5423dba90e",
"body": "Silences info-level mpv chatter from congested CDNs :\n- 'Audio device underrun detected'\n- 'Error decoding audio' (×100s)\n- 'Invalid audio PTS'\n- 'Audio/Video desynchronisation detected'\n\nvia quiet=yes + msg-level for ad/vd/ao/af modules.\n\nAlso makes the audio pipeline more forgiving :\n- audio-buffer=0.5\n- audio-stream-silence=yes\n- audio-fallback-to-null=yes",
"is_bot": false,
"headline": "fix(mpv): silence terminal spam + harden audio against bad PTS",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-05-28T07:49:38Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "d64ee5030f5c85149b7839f64ce4f7a1b4ffeaa6",
"body": "- Home header now displays 'FreeFlix CLI — Accueil • v1.1.5'\n (or 'v<dev>' when running from a checkout)\n- Settings → 'ℹ About' opens a rich panel with :\n version, GitHub repo, PyPI page, issue tracker\n license (GPL-3.0-or-later)\n author (freedy237)\n credits to PaulExplorer (autoflix-cli) and bloc97 (Anime4K)\n- French labels added to i18n.py",
"is_bot": false,
"headline": "feat: show version in home header + add About panel in Settings",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-05-28T07:35:38Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "39a3ff775987cdf023d0fc343f9b415a82107216",
"body": "Two bugs surfaced after the FreeFlix rebrand :\n\n1. config/freeflix_position.lua still referenced 'autoflix-key' /\n 'autoflix-out' while player_manager.py sends 'freeflix-key' /\n 'freeflix-out'. The position resume has been silently broken\n since v1.0.0. Lua script regenerated with the correct \n[…]\ng/demuxer=fatal'\n but mpv doesn't expose those sub-prefixes — only the bare\n 'ffmpeg' module. The reconnect spam was still going through.\n Now uses 'msg-level=ffmpeg=fatal' which actually works.",
"is_bot": false,
"headline": "fix: silence ffmpeg log spam + repair broken position-resume",
"author_name": "freedy237",
"author_login": "freedy237",
"committed_at": "2026-05-28T07:30:16Z",
"body_truncated": true,
"is_coding_agent": false
}
],
"releases_count": 61,
"commits_last_year": 113,
"latest_release_at": "2026-07-27T17:22:39Z",
"latest_release_tag": "v1.9.3",
"releases_from_tags": false,
"days_since_last_push": 0,
"active_weeks_last_year": 9,
"days_since_latest_release": 0,
"mean_days_between_releases": 2.6
},
"community": {
"has_readme": true,
"has_license": true,
"has_description": true,
"has_contributing": false,
"health_percentage": 42,
"has_issue_template": false,
"has_code_of_conduct": false,
"has_pull_request_template": false
},
"ecosystem": {
"packages": [
{
"name": "freeflix-cli",
"exists": true,
"license": "GPL-3.0-or-later",
"keywords": [
"VF",
"VOSTFR",
"anime",
"anime-sama",
"haruna",
"movies",
"mpv",
"series",
"streaming",
"Development Status :: 5 - Production/Stable",
"Environment :: Console",
"Intended Audience :: End Users/Desktop",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3",
"Topic :: Multimedia :: Video"
],
"ecosystem": "pypi",
"matches_repo": true,
"registry_url": "https://pypi.org/project/freeflix-cli/",
"is_deprecated": false,
"latest_version": "1.9.3",
"repository_url": "https://github.com/freedy237/freeflix-cli.git",
"versions_count": 61,
"total_downloads": null,
"dependents_count": null,
"deprecation_note": null,
"maintainers_count": null,
"monthly_downloads": 2922,
"first_published_at": "2026-05-28T05:26:07.389302Z",
"latest_published_at": "2026-07-27T17:22:32.525926Z",
"latest_version_yanked": null,
"days_since_latest_publish": 0
}
]
},
"popularity": {
"forks": 0,
"stars": 6,
"watchers": 0,
"fork_history": {
"days": [],
"complete": true,
"collected": 0,
"total_forks": 0
},
"star_history": null,
"open_issues_and_prs": 0
},
"ai_readiness": {
"has_nix": false,
"example_dirs": [],
"has_llms_txt": false,
"has_dockerfile": false,
"has_mcp_signal": false,
"bootstrap_files": [],
"api_schema_files": [],
"has_devcontainer": false,
"typecheck_configs": [],
"toolchain_manifests": [],
"largest_source_bytes": 77028,
"source_files_sampled": 73,
"oversized_source_files": 2,
"agent_instruction_files": [],
"agent_instruction_max_bytes": null
},
"dependencies": {
"manifests": [
"pyproject.toml"
],
"advisories": {
"error": null,
"scope": null,
"source": null,
"findings": [],
"collected": false,
"malicious": [],
"truncated": false,
"by_severity": {},
"advisory_count": 0,
"affected_count": 0,
"assessed_count": 0,
"malicious_count": 0,
"assessed_package": null,
"unassessed_count": 0,
"direct_affected_count": 0
},
"ecosystems": [
"pypi"
],
"dependencies": [
{
"name": "beautifulsoup4",
"manifest": "pyproject.toml",
"ecosystem": "pypi",
"version_constraint": ">=4.14.3"
},
{
"name": "curl-cffi",
"manifest": "pyproject.toml",
"ecosystem": "pypi",
"version_constraint": ">=0.13.0"
},
{
"name": "flask",
"manifest": "pyproject.toml",
"ecosystem": "pypi",
"version_constraint": ">=3.1.2"
},
{
"name": "html5lib",
"manifest": "pyproject.toml",
"ecosystem": "pypi",
"version_constraint": ">=1.1"
},
{
"name": "jsbeautifier",
"manifest": "pyproject.toml",
"ecosystem": "pypi",
"version_constraint": ">=1.15.4"
},
{
"name": "m3u8",
"manifest": "pyproject.toml",
"ecosystem": "pypi",
"version_constraint": ">=6.0.0"
},
{
"name": "platformdirs",
"manifest": "pyproject.toml",
"ecosystem": "pypi",
"version_constraint": ">=4.0.0"
},
{
"name": "pycryptodome",
"manifest": "pyproject.toml",
"ecosystem": "pypi",
"version_constraint": ">=3.23.0"
},
{
"name": "readchar",
"manifest": "pyproject.toml",
"ecosystem": "pypi",
"version_constraint": ">=4.2.1"
},
{
"name": "rich",
"manifest": "pyproject.toml",
"ecosystem": "pypi",
"version_constraint": ">=14.2.0"
}
],
"all_dependencies": {
"error": "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
"source": null,
"packages": [],
"collected": false,
"truncated": false,
"total_count": null,
"direct_count": null,
"indirect_count": null
}
},
"maintainership": {
"issues": {
"open_prs": 0,
"merged_prs": 0,
"open_issues": 0,
"closed_ratio": 1,
"closed_issues": 1,
"closed_unmerged_prs": 0
},
"bus_factor": 1,
"bot_contributors": 0,
"top_contributors": [
{
"type": "User",
"login": "freedy237",
"commits": 116,
"avatar_url": "https://avatars.githubusercontent.com/u/205066866?v=4"
}
],
"contributors_sampled": 1,
"top_contributor_share": 1
},
"quality_signals": {
"has_ci": true,
"has_tests": true,
"ci_workflows": [
"ci.yml",
"release.yml"
],
"has_docs_dir": false,
"linter_configs": [],
"has_editorconfig": false,
"has_linter_config": false,
"has_precommit_config": false
},
"security_signals": {
"lockfiles": [
"uv.lock"
],
"scorecard": {
"checks": [
{
"name": "Binary-Artifacts",
"score": 10,
"reason": "no binaries found in the repo",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
},
{
"name": "Branch-Protection",
"score": 0,
"reason": "branch protection not enabled on development/release branches",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
},
{
"name": "CI-Tests",
"score": null,
"reason": "no pull request found",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
},
{
"name": "CII-Best-Practices",
"score": 0,
"reason": "no effort to earn an OpenSSF best practices badge detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
},
{
"name": "Code-Review",
"score": 0,
"reason": "Found 0/30 approved changesets -- score normalized to 0",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
},
{
"name": "Contributors",
"score": 0,
"reason": "project has 0 contributing companies or organizations -- score normalized to 0",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
},
{
"name": "Dangerous-Workflow",
"score": 10,
"reason": "no dangerous workflow patterns detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
},
{
"name": "Dependency-Update-Tool",
"score": 0,
"reason": "no update tool detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
},
{
"name": "Fuzzing",
"score": 0,
"reason": "project is not fuzzed",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
},
{
"name": "License",
"score": 10,
"reason": "license file detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
},
{
"name": "Maintained",
"score": 0,
"reason": "project was created within the last 90 days. Please review its contents carefully",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
},
{
"name": "Packaging",
"score": 10,
"reason": "packaging workflow detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
},
{
"name": "Pinned-Dependencies",
"score": 0,
"reason": "dependency not pinned by hash detected -- score normalized to 0",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
},
{
"name": "SAST",
"score": 0,
"reason": "no SAST tool detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
},
{
"name": "Security-Policy",
"score": 0,
"reason": "security policy file not detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
},
{
"name": "Signed-Releases",
"score": 0,
"reason": "Project has not signed or included provenance with any releases.",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
},
{
"name": "Token-Permissions",
"score": 0,
"reason": "detected GitHub workflow tokens with excessive permissions",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
},
{
"name": "Vulnerabilities",
"score": 8,
"reason": "2 existing vulnerabilities detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
}
],
"commit": "785a9fb2e5b68ff8b6aae756ee152443ba7d9a0e",
"ran_at": "2026-07-27T17:38:35Z",
"aggregate_score": 3,
"scorecard_version": "v5.5.0"
},
"has_codeql_workflow": false,
"has_security_policy": false,
"has_dependabot_config": false
},
"contribution_flow": {
"collected": true,
"ci_last_run_at": "2026-07-27T17:22:43Z",
"oldest_open_prs": [],
"last_merged_pr_at": null,
"ci_last_conclusion": "SUCCESS",
"oldest_open_issues": []
}
},
"config": {
"disabled_metrics": [],
"disabled_categories": [],
"disabled_components": {}
},
"source": {
"url": "https://github.com/freedy237/freeflix-cli",
"host": "github.com",
"name": "freeflix-cli",
"owner": "freedy237"
},
"metrics": {
"overall": {
"key": "overall",
"band": "moderate",
"name": "Overall health",
"note": null,
"notes": [],
"value": 52,
"inputs": {
"security": 30,
"vitality": 72,
"community": 36,
"governance": 47,
"engineering": 66
},
"components": []
},
"categories": [
{
"key": "vitality",
"band": "good",
"name": "Vitality",
"value": 72,
"weight": 0.22,
"metrics": [
{
"key": "development_activity",
"band": "moderate",
"name": "Development activity",
"note": null,
"notes": [],
"value": 60,
"inputs": {
"commits_last_year": 113,
"human_commit_share": 1,
"days_since_last_push": 0,
"active_weeks_last_year": 9
},
"components": [
{
"key": "push_recency",
"name": "Push recency",
"detail": "last push 0 days ago",
"points": 36,
"status": "met",
"details": [
{
"code": "push_recency",
"params": {
"days": 0
}
}
],
"max_points": 36
},
{
"key": "commit_cadence",
"name": "Commit cadence",
"detail": "9/52 weeks with commits",
"points": 6.2,
"status": "partial",
"details": [
{
"code": "commit_cadence_weeks",
"params": {
"weeks": 9
}
}
],
"max_points": 36
},
{
"key": "commit_volume",
"name": "Commit volume",
"detail": "113 commits in the last year",
"points": 18,
"status": "met",
"details": [
{
"code": "commits_last_year",
"params": {
"count": 113
}
}
],
"max_points": 18
},
{
"key": "openssf_scorecard_maintained",
"name": "OpenSSF Scorecard: Maintained",
"detail": "project was created within the last 90 days. Please review its contents carefully",
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
}
]
},
{
"key": "release_discipline",
"band": "excellent",
"name": "Release discipline",
"note": null,
"notes": [],
"value": 90,
"inputs": {
"releases_count": 61,
"latest_release_tag": "v1.9.3",
"releases_from_tags": false,
"days_since_latest_release": 0,
"mean_days_between_releases": 2.6
},
"components": [
{
"key": "ships_releases",
"name": "Ships releases",
"detail": "61 releases published",
"points": 27,
"status": "met",
"details": [
{
"code": "releases_published",
"params": {
"count": 61
}
}
],
"max_points": 27
},
{
"key": "release_recency",
"name": "Release recency",
"detail": "latest release 0 days ago",
"points": 36,
"status": "met",
"details": [
{
"code": "release_recency",
"params": {
"days": 0
}
}
],
"max_points": 36
},
{
"key": "release_cadence",
"name": "Release cadence",
"detail": "a release every ~2.6 days",
"points": 27,
"status": "met",
"details": [
{
"code": "release_cadence",
"params": {
"gap": 2.6
}
}
],
"max_points": 27
},
{
"key": "openssf_scorecard_signed_releases",
"name": "OpenSSF Scorecard: Signed-Releases",
"detail": "Project has not signed or included provenance with any releases.",
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
}
]
},
{
"key": "abandonment",
"band": "excellent",
"name": "Abandonment",
"note": null,
"notes": [],
"value": 100,
"inputs": {
"cap": null,
"state": "unverified",
"guards": [],
"signals": [],
"red_flag": false,
"multiplier_pct": 100,
"declared_reason": null,
"unverified_reason": "repository_too_young",
"unanswered_open_prs": null,
"unanswered_open_issues": null,
"days_since_last_merged_pr": null,
"days_since_last_human_commit": null,
"days_since_last_human_commit_is_floor": false
},
"components": [
{
"key": "project_is_still_maintained",
"name": "Project is still maintained",
"detail": "maintenance record not established from the collected data",
"points": 100,
"status": "met",
"details": [
{
"code": "abandonment_unverified",
"params": {}
}
],
"max_points": 100
}
]
}
],
"description": "Is the project alive — is code being written and are releases shipping?"
},
{
"key": "community",
"band": "at_risk",
"name": "Community & Adoption",
"value": 36,
"weight": 0.18,
"metrics": [
{
"key": "popularity",
"band": "critical",
"name": "Popularity & adoption",
"note": null,
"notes": [],
"value": 11,
"inputs": {
"forks": 0,
"stars": 6,
"watchers": 0,
"growth_state": "unverified",
"growth_factor_pct": 100,
"growth_unverified_reason": "no_history"
},
"components": [
{
"key": "stars",
"name": "Stars",
"detail": "6 stars",
"points": 11.3,
"status": "partial",
"details": [
{
"code": "stars",
"params": {
"count": 6
}
}
],
"max_points": 60
},
{
"key": "forks",
"name": "Forks",
"detail": "0 forks",
"points": 0,
"status": "missed",
"details": [
{
"code": "forks",
"params": {
"count": 0
}
}
],
"max_points": 25
},
{
"key": "watchers",
"name": "Watchers",
"detail": "0 watchers",
"points": 0,
"status": "missed",
"details": [
{
"code": "watchers",
"params": {
"count": 0
}
}
],
"max_points": 15
}
]
},
{
"key": "community_health",
"band": "moderate",
"name": "Community health",
"note": null,
"notes": [],
"value": 50,
"inputs": {
"has_readme": true,
"has_license": true,
"has_contributing": false,
"has_issue_template": false,
"has_code_of_conduct": false,
"has_pull_request_template": false
},
"components": [
{
"key": "readme",
"name": "README",
"detail": null,
"points": 22.5,
"status": "met",
"details": [],
"max_points": 22.5
},
{
"key": "license",
"name": "License",
"detail": "recognized license (GPL-3.0)",
"points": 22.5,
"status": "met",
"details": [
{
"code": "license_standard",
"params": {}
},
{
"code": "license_spdx",
"params": {
"spdx": "GPL-3.0"
}
}
],
"max_points": 22.5
},
{
"key": "contributing_guide",
"name": "CONTRIBUTING guide",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 18
},
{
"key": "code_of_conduct",
"name": "Code of conduct",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 13.5
},
{
"key": "issue_template",
"name": "Issue template",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.2
},
{
"key": "pr_template",
"name": "PR template",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 6.3
}
]
},
{
"key": "ecosystem_adoption",
"band": "moderate",
"name": "Ecosystem adoption (downloads)",
"note": "Excluded from scoring (no data or not applicable): Registry dependents. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"registry_dependents"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 58,
"inputs": {
"packages": [
"freeflix-cli"
],
"dependents": null,
"ecosystems": "pypi",
"total_downloads": null,
"monthly_downloads": 2922
},
"components": [
{
"key": "monthly_downloads",
"name": "Monthly downloads",
"detail": "2,922 downloads/month across pypi",
"points": 46.2,
"status": "partial",
"details": [
{
"code": "downloads_monthly",
"params": {
"count": 2922,
"ecosystems": "pypi"
}
}
],
"max_points": 80
},
{
"key": "registry_dependents",
"name": "Registry dependents",
"detail": "not reported by this ecosystem",
"points": 0,
"status": "excluded",
"details": [
{
"code": "not_reported_by_this_ecosystem",
"params": {}
}
],
"max_points": 20
}
]
}
],
"description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
},
{
"key": "governance",
"band": "at_risk",
"name": "Sustainability & Governance",
"value": 47,
"weight": 0.24,
"metrics": [
{
"key": "maintainer_resilience",
"band": "critical",
"name": "Maintainer resilience (bus factor)",
"note": null,
"notes": [],
"value": 10,
"inputs": {
"bus_factor": 1,
"contributors_sampled": 1,
"top_contributor_share": 1
},
"components": [
{
"key": "bus_factor",
"name": "Bus factor",
"detail": "1 contributor(s) cover half of all commits",
"points": 9,
"status": "partial",
"details": [
{
"code": "bus_factor",
"params": {
"count": 1
}
}
],
"max_points": 54
},
{
"key": "commit_distribution",
"name": "Commit distribution",
"detail": "top contributor authored 100% of commits",
"points": 0,
"status": "missed",
"details": [
{
"code": "top_contributor_share",
"params": {
"share": 100
}
}
],
"max_points": 22.5
},
{
"key": "contributor_breadth",
"name": "Contributor breadth",
"detail": "1 contributors",
"points": 1.4,
"status": "partial",
"details": [
{
"code": "contributors_sampled",
"params": {
"count": 1
}
}
],
"max_points": 13.5
},
{
"key": "openssf_scorecard_contributors",
"name": "OpenSSF Scorecard: Contributors",
"detail": "project has 0 contributing companies or organizations -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
}
]
},
{
"key": "responsiveness",
"band": "good",
"name": "Issue & PR responsiveness",
"note": "Excluded from scoring (no data or not applicable): PR acceptance. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"pr_acceptance"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 76,
"inputs": {
"merged_prs": 0,
"open_issues": 0,
"closed_issues": 1,
"issue_closed_ratio": 1,
"closed_unmerged_prs": 0
},
"components": [
{
"key": "issue_resolution",
"name": "Issue resolution",
"detail": "100% of issues closed",
"points": 46.8,
"status": "met",
"details": [
{
"code": "issues_closed_share",
"params": {
"share": 100
}
}
],
"max_points": 46.75
},
{
"key": "pr_acceptance",
"name": "PR acceptance",
"detail": "no decided pull requests or no data",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_decided_prs_or_data",
"params": {}
}
],
"max_points": 38.25
},
{
"key": "openssf_scorecard_code_review",
"name": "OpenSSF Scorecard: Code-Review",
"detail": "Found 0/30 approved changesets -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 15
}
]
},
{
"key": "stewardship",
"band": "critical",
"name": "Ownership & stewardship",
"note": "Excluded from scoring (no data or not applicable): Verified domain. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"verified_domain"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 21,
"inputs": {
"followers": 0,
"owner_type": "User",
"is_verified": null,
"owner_login": "freedy237",
"public_repos": 3,
"account_age_days": 487
},
"components": [
{
"key": "ownership_backing",
"name": "Ownership backing",
"detail": "personal (user) account",
"points": 10,
"status": "partial",
"details": [
{
"code": "owner_personal",
"params": {}
}
],
"max_points": 30
},
{
"key": "verified_domain",
"name": "Verified domain",
"detail": "not applicable to user accounts",
"points": 0,
"status": "excluded",
"details": [
{
"code": "not_applicable_to_user_accounts",
"params": {}
}
],
"max_points": 20
},
{
"key": "owner_reach",
"name": "Owner reach",
"detail": "0 followers of freedy237",
"points": 0,
"status": "missed",
"details": [
{
"code": "owner_followers",
"params": {
"count": 0,
"login": "freedy237"
}
}
],
"max_points": 25
},
{
"key": "track_record",
"name": "Track record",
"detail": "3 public repos, account ~1 yr old",
"points": 7.1,
"status": "partial",
"details": [
{
"code": "public_repos",
"params": {
"count": 3
}
},
{
"code": "account_age_years",
"params": {
"years": 1
}
}
],
"max_points": 25
}
]
},
{
"key": "package_maintenance",
"band": "excellent",
"name": "Package maintenance",
"note": null,
"notes": [],
"value": 100,
"inputs": {
"packages": [
"freeflix-cli"
],
"ecosystems": "pypi",
"any_deprecated": false,
"min_days_since_publish": 0
},
"components": [
{
"key": "published_resolvable",
"name": "Published & resolvable",
"detail": "1 package(s) on pypi",
"points": 25,
"status": "met",
"details": [
{
"code": "packages_published",
"params": {
"count": 1,
"ecosystems": "pypi"
}
}
],
"max_points": 25
},
{
"key": "publish_recency",
"name": "Publish recency",
"detail": "latest publish 0 days ago",
"points": 35,
"status": "met",
"details": [
{
"code": "publish_recency",
"params": {
"days": 0
}
}
],
"max_points": 35
},
{
"key": "version_history",
"name": "Version history",
"detail": "61 published versions",
"points": 20,
"status": "met",
"details": [
{
"code": "published_versions",
"params": {
"count": 61
}
}
],
"max_points": 20
},
{
"key": "not_deprecated",
"name": "Not deprecated",
"detail": "active, not deprecated or yanked",
"points": 20,
"status": "met",
"details": [
{
"code": "package_not_deprecated",
"params": {}
}
],
"max_points": 20
}
]
}
],
"description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
},
{
"key": "engineering",
"band": "moderate",
"name": "Engineering Quality",
"value": 66,
"weight": 0.2,
"metrics": [
{
"key": "engineering_practices",
"band": "moderate",
"name": "Engineering practices",
"note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: CI-Tests. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"openssf_scorecard_ci_tests"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 60,
"inputs": {
"has_ci": true,
"has_tests": true,
"has_editorconfig": false,
"has_linter_config": false,
"has_precommit_config": false
},
"components": [
{
"key": "ci_workflows",
"name": "CI workflows",
"detail": "2 workflow(s)",
"points": 24,
"status": "met",
"details": [
{
"code": "ci_workflows",
"params": {
"count": 2
}
}
],
"max_points": 24
},
{
"key": "tests_present",
"name": "Tests present",
"detail": null,
"points": 24,
"status": "met",
"details": [],
"max_points": 24
},
{
"key": "linter_config",
"name": "Linter config",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 16
},
{
"key": "pre_commit_hooks",
"name": "Pre-commit hooks",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 9.6
},
{
"key": "editorconfig",
"name": ".editorconfig",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 6.4
},
{
"key": "openssf_scorecard_ci_tests",
"name": "OpenSSF Scorecard: CI-Tests",
"detail": "no pull request found",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"max_points": 20
}
]
},
{
"key": "documentation",
"band": "good",
"name": "Documentation",
"note": null,
"notes": [],
"value": 75,
"inputs": {
"topics": [
"anilist",
"anime",
"anime-sama",
"aria2",
"cli",
"french",
"hls",
"mpv",
"nyaa",
"python",
"streaming",
"terminal",
"vf",
"vostfr",
"yt-dlp",
"anime4k",
"downloader",
"movies",
"series",
"tui"
],
"has_wiki": true,
"homepage": "https://github.com/freedy237/freeflix-cli",
"has_readme": true,
"has_docs_dir": false,
"has_description": true
},
"components": [
{
"key": "readme",
"name": "README",
"detail": null,
"points": 30,
"status": "met",
"details": [],
"max_points": 30
},
{
"key": "documentation_directory",
"name": "Documentation directory",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 25
},
{
"key": "documentation_homepage_site",
"name": "Documentation / homepage site",
"detail": "https://github.com/freedy237/freeflix-cli",
"points": 15,
"status": "met",
"details": [],
"max_points": 15
},
{
"key": "repository_description",
"name": "Repository description",
"detail": null,
"points": 10,
"status": "met",
"details": [],
"max_points": 10
},
{
"key": "topics",
"name": "Topics",
"detail": "20 topics",
"points": 10,
"status": "met",
"details": [
{
"code": "topics_count",
"params": {
"count": 20
}
}
],
"max_points": 10
},
{
"key": "wiki",
"name": "Wiki",
"detail": null,
"points": 10,
"status": "met",
"details": [],
"max_points": 10
}
]
}
],
"description": "Are baseline engineering and documentation practices in place?"
},
{
"key": "security",
"band": "at_risk",
"name": "Security",
"value": 30,
"weight": 0.16,
"metrics": [
{
"key": "security_posture",
"band": "at_risk",
"name": "Security posture",
"note": "Excluded from scoring (no data or not applicable): CI-Tests. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"ci_tests"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 30,
"inputs": {
"source": "openssf_scorecard",
"checks_evaluated": 17,
"scorecard_version": "v5.5.0",
"checks_inconclusive": 1,
"scorecard_aggregate": 3
},
"components": [
{
"key": "binary_artifacts",
"name": "Binary-Artifacts",
"detail": "no binaries found in the repo",
"points": 7.5,
"status": "met",
"details": [],
"max_points": 7.5
},
{
"key": "branch_protection",
"name": "Branch-Protection",
"detail": "branch protection not enabled on development/release branches",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "ci_tests",
"name": "CI-Tests",
"detail": "no pull request found",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"max_points": 2.5
},
{
"key": "cii_best_practices",
"name": "CII-Best-Practices",
"detail": "no effort to earn an OpenSSF best practices badge detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 2.5
},
{
"key": "code_review",
"name": "Code-Review",
"detail": "Found 0/30 approved changesets -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "contributors",
"name": "Contributors",
"detail": "project has 0 contributing companies or organizations -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 2.5
},
{
"key": "dangerous_workflow",
"name": "Dangerous-Workflow",
"detail": "no dangerous workflow patterns detected",
"points": 10,
"status": "met",
"details": [],
"max_points": 10
},
{
"key": "dependency_update_tool",
"name": "Dependency-Update-Tool",
"detail": "no update tool detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "fuzzing",
"name": "Fuzzing",
"detail": "project is not fuzzed",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "license",
"name": "License",
"detail": "license file detected",
"points": 2.5,
"status": "met",
"details": [],
"max_points": 2.5
},
{
"key": "maintained",
"name": "Maintained",
"detail": "project was created within the last 90 days. Please review its contents carefully",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "packaging",
"name": "Packaging",
"detail": "packaging workflow detected",
"points": 5,
"status": "met",
"details": [],
"max_points": 5
},
{
"key": "pinned_dependencies",
"name": "Pinned-Dependencies",
"detail": "dependency not pinned by hash detected -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "sast",
"name": "SAST",
"detail": "no SAST tool detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "security_policy",
"name": "Security-Policy",
"detail": "security policy file not detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "signed_releases",
"name": "Signed-Releases",
"detail": "Project has not signed or included provenance with any releases.",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "token_permissions",
"name": "Token-Permissions",
"detail": "detected GitHub workflow tokens with excessive permissions",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "vulnerabilities",
"name": "Vulnerabilities",
"detail": "2 existing vulnerabilities detected",
"points": 6,
"status": "partial",
"details": [],
"max_points": 7.5
}
]
}
],
"description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
},
{
"key": "ai_readiness",
"band": "at_risk",
"name": "AI Readiness",
"value": 39,
"weight": 0,
"metrics": [
{
"key": "ai_agent_context",
"band": "at_risk",
"name": "Agent context & guidance",
"note": null,
"notes": [],
"value": 40,
"inputs": {
"has_llms_txt": false,
"legible_history_share": 0.77,
"agent_instruction_files": [],
"agent_instruction_max_bytes": null
},
"components": [
{
"key": "agent_instructions",
"name": "Agent instructions",
"detail": "no CLAUDE.md / AGENTS.md / editor rules",
"points": 0,
"status": "missed",
"details": [
{
"code": "no_agent_instructions",
"params": {}
}
],
"max_points": 45
},
{
"key": "machine_readable_docs_llms_txt",
"name": "Machine-readable docs (llms.txt)",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 15
},
{
"key": "legible_commit_history",
"name": "Legible commit history",
"detail": "77 of 100 human commits state their intent (structured subject or explanatory body)",
"points": 40,
"status": "met",
"details": [
{
"code": "legible_history",
"params": {
"legible": 77,
"sampled": 100
}
}
],
"max_points": 40
}
]
},
{
"key": "ai_verify_loop",
"band": "at_risk",
"name": "Verify loop (build / test / typecheck)",
"note": null,
"notes": [],
"value": 32,
"inputs": {
"has_nix": false,
"has_tests": true,
"lockfiles": [
"uv.lock"
],
"has_dockerfile": false,
"typed_language": false,
"bootstrap_files": [],
"has_devcontainer": false,
"has_linter_config": false,
"typecheck_configs": [],
"agent_commit_share": 0,
"toolchain_manifests": [],
"dependency_bot_commit_share": 0
},
"components": [
{
"key": "one_command_bootstrap",
"name": "One-command bootstrap",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 18
},
{
"key": "automated_tests",
"name": "Automated tests",
"detail": null,
"points": 22,
"status": "met",
"details": [],
"max_points": 22
},
{
"key": "lint_format_config",
"name": "Lint / format config",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 11
},
{
"key": "static_type_checking",
"name": "Static type checking",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 11
},
{
"key": "reproducible_environment",
"name": "Reproducible environment",
"detail": "lockfile",
"points": 10,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "lockfile"
}
}
],
"max_points": 10
},
{
"key": "demonstrated_agent_practice",
"name": "Demonstrated agent practice",
"detail": "no agent-authored commits among the last 100",
"points": 0,
"status": "missed",
"details": [
{
"code": "no_agent_authored_commits",
"params": {
"sampled": 100
}
}
],
"max_points": 10
},
{
"key": "automated_maintenance",
"name": "Automated maintenance",
"detail": "no automated dependency updates observed",
"points": 0,
"status": "missed",
"details": [
{
"code": "no_dependency_automation",
"params": {}
}
],
"max_points": 8
},
{
"key": "openssf_scorecard_pinned_dependencies",
"name": "OpenSSF Scorecard: Pinned-Dependencies",
"detail": "dependency not pinned by hash detected -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
}
]
},
{
"key": "ai_code_legibility",
"band": "moderate",
"name": "Code legibility for models",
"note": null,
"notes": [],
"value": 54,
"inputs": {
"primary_language": "Python",
"largest_source_bytes": 77028,
"source_files_sampled": 73,
"oversized_source_files": 2
},
"components": [
{
"key": "type_checkable_code",
"name": "Type-checkable code",
"detail": "Python without a type-check config",
"points": 0,
"status": "missed",
"details": [
{
"code": "no_typecheck_config_language",
"params": {
"language": "Python"
}
}
],
"max_points": 45
},
{
"key": "manageable_file_sizes",
"name": "Manageable file sizes",
"detail": "2/73 source files over 60KB",
"points": 53.5,
"status": "partial",
"details": [
{
"code": "oversized_source_files",
"params": {
"kb": 60,
"sampled": 73,
"oversized": 2
}
}
],
"max_points": 55
}
]
}
],
"description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
}
],
"metrics_version": "1.13.0"
},
"warnings": [
"Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token",
"GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
"deps.dev does not index pypi:freeflix-cli@1.9.3; advisories assessed against the repository dependency graph instead"
],
"report_type": "repository",
"generated_at": "2026-07-27T17:38:41.363179Z",
"schema_version": "0.27.0",
"badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/f/freedy237/freeflix-cli.svg",
"full_name": "freedy237/freeflix-cli",
"license_state": "standard",
"license_spdx": "GPL-3.0"
}