ani-cli web
Local web UI for a system-wide ani-cli install.
Current version: 0.49.5
What it does
- Search anime in
subordub, with poster-style results shown below the selection panel and the first English alternate title when available - Queue downloads with folder, quality, media type, season, and episode controls
- Choose which download backends queue jobs may use:
ani-cli,anipy-cli, andanimdl - Track shows in a watchlist with
Watching,Planned,Finished, andDroppedcategories - Expose a small JSON summary endpoint for Homepage dashboard widgets
- Refresh watchlist episode counts manually or on a schedule
- Auto-download missing episodes for
Watchingentries after later refreshes, with a per-showSource nameoverride forani-clisearch - Move fully completed libraries into Jellyfin TV or movie folders with tracked background handoff jobs that also appear in the Queue page
- Send optional Discord webhook notifications
- Serve a checked-in
favicon.pngas the site favicon
Pages
/: Search and queue downloads, with poster-card search results below the selection box and alternate English titles under the main name when available/queue: Monitor downloads and Jellyfin handoff jobs, inspect logs, retry failed downloads, avoid duplicate re-queues for the same failed download, clear failed jobs, and remove finished jobs/watchlist: Track shows, refresh them, download all available episodes, and manage auto-download settings such asSource name, libraryName, season, and episode offset/config: Save defaults, choose queue download methods and fallback retries, schedule refreshes, configure Jellyfin and Discord, manually reconcile watchlist download flags against the filesystem, monitor Jellyfin handoff progress, and view runtime info and the changelog
Quick start
Requirements:
ani-cliinstalled and available inPATH- Optional:
anipy-cliand/oranimdlinstalled and available inPATHif you want automatic fallback retries outside Docker - Common runtime tools used by
ani-cli, especiallycurl,ffmpeg,fzf,grep,openssl,sed,aria2c,botan, andyt-dlp
Run locally:
./ani-cli-web
Open:
http://127.0.0.1:8421/
Useful flags and env:
./ani-cli-web --debugANI_CLI_WEB_HOST=0.0.0.0ANI_CLI_WEB_PORT=8421ANI_CLI_WEB_JOB_STDOUT=trueANI_CLI_BIN=/path/to/ani-cliANIPY_CLI_BIN=/path/to/anipy-cliANIMDL_BIN=/path/to/animdl
Docker
Build:
docker build -t ani-cli-web .
Docker builds the app from the current local checkout.
Run:
docker run --rm \
-p 8421:8421 \
-e USER_UID="$(id -u)" \
-e USER_GID="$(id -g)" \
-v "$(pwd)/downloads:/downloads" \
-v "$(pwd)/.ani-cli-web:/app/.ani-cli-web" \
ani-cli-web
Compose:
USER_UID="$(id -u)" USER_GID="$(id -g)" docker compose up --build -d
Docker notes:
- The container serves on
0.0.0.0:8421 - Downloads are written under
/downloads - App state is stored under
/app/.ani-cli-web USER_UIDandUSER_GIDhelp keep mounted files owned by your host userUPDATE_ON_START=truerunsani-cli --updatebefore startupANI_CLI_WEB_JOB_STDOUT=truemirrors download job output to container stdout for log collectors; set it tofalseto keep job output only in the Queue pagebotanis installed inside the container for providers or scripts that need Botan cryptography toolinganipy-cliandanimdlare installed systemwide inside the container at/usr/local/bin, linked from/usr/bin, and included in the runtimePATH;animdlis isolated in a Python 3.11 virtualenv so its pinned dependencies stay executable
Key behavior
Watchlist
- Adding a show tracks it without downloading immediately
- Later manual refreshes or scheduled refreshes can queue missing episodes
Download allqueues every currently available episode for the chosen mode- Successful downloads sync back into the watchlist
- TV entries move to
Finishedwhen the selected downloaded mode reaches the expected episode count - Movie entries can be treated as complete after download and routed to movie storage
Auto-download
- Runs only for entries in
Watching - Uses the per-show language, quality,
Source namesearch override, season, library name, and optional episode offset settings - Can queue backlog episodes that were already available before the show was first tracked
Download fallback
- Optional and configured from
/config - Queue jobs can use any checked combination of
ani-cli,anipy-cli, andanimdl - Checked methods are tried in this order:
ani-cli,anipy-cli, thenanimdl - Selecting one method disables fallback retry; selecting multiple methods makes later methods automatic fallbacks
- Fallback retries keep the queued episode numbers when fallback downloader filenames are renumbered from
1 - Docker images install
anipy-cliandanimdlautomatically; non-Docker installs should provide the selected tools inPATHthemselves
Queue retries
- Adding a download that exactly matches an existing failed queue job reuses that failed entry and sets it back to
pending - This avoids stacking multiple failed rows for the same episode when you queue the same job again
Jellyfin handoff
- Optional and configured from
/config - TV libraries move only after the show is finished and download-complete
- Movie libraries move after download completion
- Manual
Run nowscans the watchlist in a background job and shows live progress for processed entries, moved files, and the current destination path - Manual watchlist filesystem sync rechecks downloaded episode flags against the files currently present under the download library
- Recent Jellyfin handoff jobs survive page reloads and show their latest status after app restarts
Homepage widget API
For Homepage's Custom API widget, use:
http://127.0.0.1:8421/api/watchlist/homepage
Example response:
{
"watchlist": 12,
"planned": 4,
"finished": 31,
"dropped": 2,
"total": 49
}
This endpoint is intentionally small so Homepage can map the returned values directly into its widget fields.
Runtime info
The Config page runtime panel shows:
ani-cli-webversion loaded fromVERSION- Installed
ani-cliversion - Installed
anipy-cliandanimdlversions and dependency status - A
Changelogbutton that opens a scrollable viewer backed byCHANGELOG.md
Remote access
By default the app only serves loopback clients.
To allow LAN or remote access:
ANI_CLI_WEB_ALLOW_REMOTE=1
ANI_CLI_WEB_AUTH_USERNAME=admin
ANI_CLI_WEB_AUTH_PASSWORD=choose-a-long-random-password
Optional remote path restriction:
ANI_CLI_WEB_REMOTE_PATH_ROOTS=/downloads:/srv/jellyfin-tv:/srv/jellyfin-movies
State and storage
Project state is stored in:
ani-cli-web/.ani-cli-web/
Main contents:
config.jsonremote-sessions.jsonstate.sqlite3thumbnails/
Downloaded files are organized like this:
ANI_CLI_DOWNLOAD_DIR/tv/Show Name/Season 01/Show Name - S01E01.mp4
ANI_CLI_DOWNLOAD_DIR/movie/Movie Name/Movie Name.mp4
Configuration
Most users only need these environment variables:
ANI_CLI_BINANIPY_CLI_BINANIMDL_BINANI_CLI_WEB_HOSTANI_CLI_WEB_PORTANI_CLI_WEB_ALLOW_REMOTEANI_CLI_WEB_AUTH_USERNAMEANI_CLI_WEB_AUTH_PASSWORDANI_CLI_WEB_REMOTE_PATH_ROOTSANI_CLI_WEB_DEBUGANI_CLI_WEB_STATE_ROOT
Container-specific variables:
UPDATE_ON_STARTUSER_UIDUSER_GID
Everything else can usually be configured from /config.
Testing
Run the regression suite with:
python3 -m unittest test_app.py