anime-sh
The terminal-native anime client. You type a title; it plays. Providers, mirrors, and resolvers are internal details you never have to think about.
anime "Frieren"
The Providers badge is a nightly liveness probe of the real streaming sites. It goes red when a site blocks us, which happens routinely and is not a build failure — see How it behaves.
Under the hood: AniList metadata, live streaming providers fanned out with
circuit breakers, stream resolvers, mpv driven over JSON IPC, auto-skip of
intros/outros, auto-advance to the next episode, a persistent offline library
(resume / history / favorites), AniList two-way sync, and ffmpeg downloads —
all behind a keyboard-driven Textual app.
Contents
- Requirements
- Install — PyPI (recommended) · from source
- First run
- Sync across devices (AniList)
- Command reference
- How it behaves
- Updating & uninstalling
- Troubleshooting
- Develop · Design · Legal
Requirements
| What | Why | Needed |
|---|---|---|
| Python 3.11+ | runs the app | always |
| mpv | plays the video | for playback |
| ffmpeg | saves downloads, fallback player | for download |
Install the two media tools with your OS package manager:
# Windows (scoop) # Windows (winget)
scoop install mpv ffmpeg winget install mpv.mpv ; winget install Gyan.FFmpeg
# macOS (Homebrew) # Debian/Ubuntu
brew install mpv ffmpeg sudo apt install mpv ffmpeg
After installing anime-sh, run anime doctor — it checks Python, mpv,
ffmpeg, the database, and the provider plugins, and tells you exactly what (if
anything) is missing.
Install
Easiest on Windows — one file, no terminal
Download this repo (green Code button → Download ZIP), unzip it, and
double-click run-anime.bat.
It installs what's missing and starts the app. You do not need Python — it uses uv, a single standalone program that brings its own. Running the file again later just launches anime-sh.
Prefer typing commands, or not on Windows? Use Method A.
Method A — from PyPI (recommended)
You do not need Python installed. uv is a single standalone binary that
fetches its own Python, so this works from a clean machine. Copy the block for
your OS:
Windows
winget install astral-sh.uv # the installer (no Python needed)
winget install shinchiro.mpv # the video player
uv tool install "anime-sh[tui]" # anime-sh itself
anime doctor # check everything was found
macOS
brew install uv mpv
uv tool install "anime-sh[tui]"
anime doctor
Linux
curl -LsSf https://astral.sh/uv/install.sh | sh # if you don't have uv
sudo apt install mpv # or your package manager
uv tool install "anime-sh[tui]"
anime doctor
Then run anime to launch it.
animenot recognised after installing? The install worked; your shell just hasn't picked up the new folder. Runuv tool update-shell, then close and reopen the terminal.
Already have Python? pipx install "anime-sh[tui]" works too — but note
that pipx is itself a Python package, so it can't be the first thing you
install on a machine without Python.
The [tui] extra pulls in the interactive terminal UI and cover-art rendering.
ffmpeg is optional and only needed for anime download.
Method B — from GitHub (source)
Use this to run the very latest code, hack on it, or if you don't want PyPI.
Just want the latest build, installed as a tool:
uv tool install "anime-sh[tui] @ git+https://github.com/Anime123450/anime-sh.git"
Want the source to edit / develop:
git clone https://github.com/Anime123450/anime-sh.git
cd anime-sh
uv sync --extra dev --extra tui # create the venv + install everything
uv run anime doctor
uv run anime # launch the TUI (prefix commands with `uv run`)
On this checkout, run the app as
uv run anime …. Theuv tool installmethods above put a plainanimecommand on your PATH instead.
First run
anime # opens the TUI: Continue Watching, Airing This Season, Trending
- Type to search as you go (or press
/to focus the search box). - Arrow keys move, Enter opens a show, Enter on an episode plays it.
- Press
?any time for the full key list,qto quit.
Prefer one-shot commands? anime "Frieren" searches, picks the best match, and
plays episode 1. anime play "Frieren" -e 18 --dub -q 1080p is fully explicit.
Turn on shell tab-completion once: anime --install-completion.
Sync across devices (AniList)
anime-sh keeps your progress in a local database and can sync it with AniList, so what you watch here lines up with what you watch anywhere else that tracks to AniList (phone apps, the website, etc.).
Link your account once — no password involved:
- Create a free API client at
anilist.co/settings/developer with
redirect URL
https://anilist.co/api/v2/oauth/pin. - Run
anime auth loginand paste the token it points you to.
Then:
anime sync pull # import your AniList list (watching/planning/…) into anime-sh
anime sync push # send your local watch history up to AniList
anime list --status watching # view your AniList list by status
After linking, finishing an episode automatically bumps your AniList
progress. Run anime sync pull whenever you want to pull in progress you made
on another device.
Command reference
# Watch
anime # launch the keyboard-driven TUI (needs [tui] extra)
anime "Frieren" # search + best match + play episode 1
anime play "Frieren" -e 18 # a specific episode (add --dub, -q 1080p)
anime continue # episodes you started but didn't finish
anime resume # jump back into the most recent one
anime next "Mob Psycho 100" # find + play the next season (sequel)
anime sources "Frieren" # every provider entry that matches, before playing
# Discover
anime search "frieren" # AniList search (instant; no providers touched)
anime search --genre action --year 2024 --sort score # browse with filters
anime trending
anime seasonal # this season (or: --season fall --year 2025)
anime calendar --days 7 # what airs next, and when
anime random # surprise me, picked from what's trending
anime recommend "Frieren" # shows for people who liked it (AniList)
anime related "Attack on Titan" # prequels, sequels, side stories, movies
# Library & tracking
anime mark "Frieren" -e 12 # mark eps 1–12 watched (syncs to AniList)
anime unmark "Frieren" # clear local progress for a show (undo a mark)
anime history # what you've watched
anime favorite add "Frieren" # ★ (also: favorite ls / rm)
anime stats # episodes, hours, top genres & providers
anime rate "Frieren" 9 # set a score; anime status "X" completed
# AniList
anime auth login # link AniList (one-time); status / logout
anime sync pull | push # import your list / send yours up
anime list --status watching # your AniList list (also planning/completed…)
# Downloads
anime download "Frieren" -e 1-12 # save a range to disk (ffmpeg); resumes, skips done
anime download "Frieren" -e 1,3,5 # or a list; also: anime downloads
# Housekeeping
anime doctor # player, ffmpeg, config, database, plugins
anime --version
anime config get # dump settings; config get playback.quality
anime config set playback.quality 1080p # also: audio dub, ui.theme nord …
anime config path | validate
anime providers ls
anime cache clear # wipe the disposable metadata cache (or: cache purge)
Add --json to search, trending, play, continue, history, and
favorite ls for machine-readable output (play --json resolves the stream
without launching a player).
How it behaves
Forgiving search. You don't have to spell titles the way AniList stores
them — dont toy with me, dukes son claims he wont love me, even
atack on titan all find the right show. When AniList's strict search comes up
empty, anime-sh retries with apostrophes restored and the query's distinctive
words, then fuzzy-ranks the results against what you typed.
Multiple providers, merged. anime-sh fans out across streaming providers (currently anikoto + AniZone) and falls through to whichever one actually has your show — so a title missing from one source still plays from another, with no action from you. AniZone serves a clean, un-obfuscated HLS stream with soft English subs, so it plays where Cloudflare-gated sites can't.
Streaming providers break and get Cloudflare-gated constantly — that's the normal operating state, not a bug. When a provider is unreachable, anime-sh degrades cleanly instead of crashing; metadata and your library keep working.
Offline-friendly. Your library (progress, history, favorites) lives in its
own anime.db, separate from a disposable cache.db of AniList responses.
Recently-seen pages still render with no network, and anime cache clear is
always safe — nothing user-owned lives in the cache.
Updating & uninstalling
uv tool upgrade anime-sh # or: pipx upgrade anime-sh
uv tool uninstall anime-sh # or: pipx uninstall anime-sh
Your library and settings live outside the install (see anime config path), so
upgrading never touches them.
Troubleshooting
pipx/pip"not recognised", or you don't have Python — that's the wrong starting point on a clean machine: pipx and pip are Python packages. Use theuvblock under Install instead; uv is a standalone binary and brings its own Python.animenot recognised right after installing — the install succeeded, your shell just hasn't picked up the new folder.uv tool update-shell, then reopen the terminal.anime doctorsays mpv/ffmpeg not found — install them (see Requirements) and make sure they're on your PATH.- A show won't play / "trying next…" on every source — providers get Cloudflare-gated or geo-blocked; try again later or a different title. Your library and search keep working regardless.
- Windows:
animeblocked by Smart App Control — invoke it as a module:python -m anime_sh <command>. - Nothing in Continue Watching from your phone — link AniList
(
anime auth login) and runanime sync pull; see Sync across devices.
Develop
git clone https://github.com/Anime123450/anime-sh.git && cd anime-sh
uv sync --extra dev --extra tui
uv run python -m pytest -q # fast unit + contract suite (no network)
uv run lint-imports # architecture contracts (must stay green)
Add ANIME_SH_LIVE=1 to run the gated live-provider tests. See
docs/plugins.md to add a provider or resolver,
CONTRIBUTING.md before sending a change, and
docs/ENGINEERING_STANDARDS.md for the rules
this project learned the hard way — each one names the bug that caused it.
Design
anime-sh is layered cli/tui → app → domain, with infra, providers, and
resolvers as swappable adapters behind ports. Dependencies point downward only
and that is enforced in CI. Identity comes from AniList (every show is keyed by
its AniList id), so adding a provider is attaching a source to a known identity,
not fuzzy-matching titles. Full write-up: docs/architecture.md.
Legal
anime-sh is a client, not a content library. It bundles no media, mirrors nothing, and bypasses no DRM. Providers read public pages and are expected to break; a broken provider is a degraded experience, not an outage. Provider plugins are separable from the core so the project survives any single one.
Project
- Changelog — every release, written for users
- Releases — tagged builds with notes
- Contributing · Engineering standards · Architecture · Writing a plugin
- Security policy · Code of conduct
License
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file anime_sh-0.2.43.tar.gz.
File metadata
- Download URL: anime_sh-0.2.43.tar.gz
- Upload date:
- Size: 121.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5e808ebbdb2a982d0b6538e704147f089a11ebda5f6d5ac142a212e31e4ce654
|
|
| MD5 |
12a6dacbd3552e14d1b5a3f644847fd6
|
|
| BLAKE2b-256 |
23b0c17d8b55dcf4275bce316c7cc9b969b3b2e1a7e091c94278ecb16a9edcad
|
Provenance
The following attestation bundles were made for anime_sh-0.2.43.tar.gz:
Publisher:
release.yml on Anime123450/anime-sh
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
anime_sh-0.2.43.tar.gz -
Subject digest:
5e808ebbdb2a982d0b6538e704147f089a11ebda5f6d5ac142a212e31e4ce654 - Sigstore transparency entry: 2583641611
- Sigstore integration time:
-
Permalink:
Anime123450/anime-sh@2517c6ab9bc6625b5ae32ae62fd464dc4270da60 -
Branch / Tag:
refs/tags/v0.2.43 - Owner: https://github.com/Anime123450
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@2517c6ab9bc6625b5ae32ae62fd464dc4270da60 -
Trigger Event:
push
-
Statement type:
File details
Details for the file anime_sh-0.2.43-py3-none-any.whl.
File metadata
- Download URL: anime_sh-0.2.43-py3-none-any.whl
- Upload date:
- Size: 158.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c208543f5d4ec99cbbf75de5941ff54c8f93a1a327a02bc0a865e68b554b138e
|
|
| MD5 |
e17164e925df36855d5e595211f78be4
|
|
| BLAKE2b-256 |
5e28a725f53b16c02e32be1803c81cea89ef23948fa2c78bae3ebff9bd7b685a
|
Provenance
The following attestation bundles were made for anime_sh-0.2.43-py3-none-any.whl:
Publisher:
release.yml on Anime123450/anime-sh
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
anime_sh-0.2.43-py3-none-any.whl -
Subject digest:
c208543f5d4ec99cbbf75de5941ff54c8f93a1a327a02bc0a865e68b554b138e - Sigstore transparency entry: 2583641678
- Sigstore integration time:
-
Permalink:
Anime123450/anime-sh@2517c6ab9bc6625b5ae32ae62fd464dc4270da60 -
Branch / Tag:
refs/tags/v0.2.43 - Owner: https://github.com/Anime123450
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@2517c6ab9bc6625b5ae32ae62fd464dc4270da60 -
Trigger Event:
push
-
Statement type: