ani-cli web

A local web UI for a system-wide ani-cli install.

Current version: 0.12.0

Project Layout

ani-cli-web/
  app.py          Web server, runtime wiring, request handlers, and CLI entrypoint.
  web_templates.py Shared Search, Config, and Watchlist page markup plus page-shell helpers.
  ani-cli-web     Launcher script.
  test_app.py     Regression tests with isolated temp-state setup.
  VERSION         Project version.
  CHANGELOG.md    Change history.
  README.md       Project documentation.

Run

Start the web app with:

./ani-cli-web

For thumbnail debugging, run:

./ani-cli-web --debug

The launcher also accepts ---debug. You can also enable debug logging with ANI_CLI_WEB_DEBUG=1.

Then open:

http://127.0.0.1:8421/

By default the server binds to 127.0.0.1:8421.

Overview

ani-cli-web keeps search and download management on /, saved defaults on /config, and the watchlist on /watchlist, all with the same sidebar navigation layout and a Tsuki-inspired visual style.

The app currently includes:

  • Search against AllAnime with sub or dub mode selection.
  • Episode loading for the selected result.
  • Queueing downloads with editable library name, season, episode range, quality, and target folder.
  • A dedicated Config page for saved default folder, mode, and quality settings.
  • A paged SQLite-backed download queue with retry, cancel, remove, retry-failed, and clear-finished actions.
  • A paged SQLite-backed watchlist with summary cards, per-show refresh, bulk refresh, source links, and thumbnail tools.
  • Background Refresh All execution with status polling instead of a long blocking HTTP request.
  • Persistent watchlist refresh history that survives restarts and marks interrupted bulk refresh jobs clearly.
  • Local thumbnail caching plus manual thumbnail upload when automatic cover lookup fails.
  • A refreshed glassy dark UI inspired by the Tsuki frontend design language.
  • Shared page templates moved out of app.py plus broader regression tests for higher-risk queue, watchlist, and handler flows.
  • Project-local runtime state under .ani-cli-web/.

Search Page

The main page at / is where you search and queue downloads.

Workflow:

  1. Search by anime title or keyword.
  2. Pick a result to load available episodes.
  3. Adjust library name, season, episode range, quality, and download folder.
  4. Add the selected show either to the watchlist or directly to the queue.

The page also includes:

  • A live queue view that refreshes automatically.

Config Page

The Config page at /config is where saved defaults now live.

Use it to:

  1. Set the default download folder.
  2. Choose the default sub or dub search mode.
  3. Choose the default search quality used to prefill the Search page.

Those saved defaults are written into the project-local config.json and loaded automatically when the Search page opens.

The Config page also shows the current app version plus dependency status in a compact centered layout.

Access Guard

By default, ani-cli-web only serves loopback clients such as 127.0.0.1 and ::1.

If you intentionally want LAN or remote access, set:

ANI_CLI_WEB_ALLOW_REMOTE=1

This keeps the queue, config, and watchlist mutation APIs safer by default when the app is rebound away from localhost.

Download Queue

The queue is stored in SQLite and shown 10 jobs at a time.

Queue actions currently available:

  • Retry for finished or failed jobs.
  • Cancel for pending or running jobs.
  • Remove for completed or failed jobs.
  • Retry failed for all failed jobs.
  • Remove finished for completed jobs.

Downloads are staged inside the project-local app state first. After ani-cli finishes, files are moved into a Plex/Jellyfin-friendly layout:

ANI_CLI_DOWNLOAD_DIR/anime_name/Season 01/anime_name - S01E01.mp4

Watchlist

The watchlist stores one row per show in SQLite and keeps separate sub and dub episode counts.

You can add entries in two ways:

  1. From the Search page with Add to watchlist.
  2. Manually on /watchlist with a title and AllAnime show_id.

Watchlist features:

  1. Refresh updates one tracked show.
  2. Refresh All runs in the background, rejects duplicate queueing while a refresh is already pending or running, and preserves interrupted job status across restarts.
  3. Open jumps back to the Search page with the title pre-filled.
  4. Clicking the anime title opens the AllManga source page at bangumi/<show_id> in a new tab.
  5. Remove deletes the watchlist entry and clears its cached poster file.
  6. Poster cards use a compact multi-column grid with pagination at 30 cards per page.
  7. Summary cards show tracked shows plus total sub and dub episode counts.

Thumbnail Behavior

Watchlist thumbnails use the local /api/watchlist/thumb/... route, not direct remote image URLs.

Current thumbnail behavior:

  • Cached thumbnails render from the local project cache when available.
  • The page adds a fresh nonce to thumbnail URLs to avoid stale browser-cached misses.
  • Missing visible covers are warmed up in small batches instead of one request per card all at once.
  • Thumbnail image tags only hit the local route for already-cached files, so opening the watchlist no longer triggers a per-card remote lookup burst.
  • AnimeSchedule is tried first for cover lookup.
  • If a season-labeled title fails as-is, lookup retries with simplified base-title queries.
  • AniDB is used as a fallback when AnimeSchedule does not resolve a cover.
  • Failed fetch attempts no longer refresh the retry window, so a bad lookup does not get stuck in an immediate repeat-404 state.

Per-card thumbnail tools:

  1. Reload forces a fresh redownload attempt for that show's poster.
  2. Upload appears when no thumbnail is currently available and lets you assign a local image manually.
  3. Hovering the poster tile or card shows the current thumbnail source hint.

Manual uploads are saved into the same local thumbnail cache used by automatic cover downloads.

Runtime State

All runtime state is stored under:

ani-cli-web/.ani-cli-web/

That folder currently holds:

  • config.json
  • state.sqlite3
  • legacy queue.json migration input when present
  • legacy watchlist.json migration input when present
  • thumbnails/
  • AniDB title cache data
  • staging files for active downloads

Legacy files from ~/.config/ani-cli-web/ and ~/.local/state/ani-cli-web/ are migrated into the project-local folder automatically on startup. The earlier project-local queue.sqlite3 filename is also migrated automatically into state.sqlite3.

Configuration

Environment variables:

  • ANI_CLI_BIN: path or command name for ani-cli; defaults to ani-cli from PATH.
  • ANI_CLI_DOWNLOAD_DIR: initial default download folder.
  • ANI_CLI_MODE: initial mode, sub or dub.
  • ANI_CLI_QUALITY: initial quality such as best, 1080, or 720.
  • ANI_CLI_WEB_HOST: server host, default 127.0.0.1.
  • ANI_CLI_WEB_PORT: server port, default 8421.
  • ANI_CLI_WEB_ALLOW_REMOTE: allow non-loopback clients when set to 1, true, yes, or on.
  • ANI_CLI_WEB_DEBUG: enable debug logging when set to 1, true, yes, or on.
  • ANI_CLI_WEB_STATE_ROOT: override the project-local state directory path; useful for isolated test runs or custom storage locations.

Saved defaults from the UI are written into the project-local config.json.

Notes

  • Importing app.py no longer boots the runtime worker threads automatically; runtime setup is deferred until startup or first use.
  • Watchlist and queue data are stored in the same project-local SQLite database file, state.sqlite3.
  • Runtime folders such as .ani-cli-web/, downloads/, and Python bytecode cache directories at any depth are ignored by git.
  • Focused regression tests live in test_app.py, run against an isolated temporary state root, and can be started with python3 -m unittest test_app.py.
S
Description
No description provided
Readme
530 KiB
Languages
Python 99.4%
Dockerfile 0.4%
Shell 0.2%