anime-sh
Watch anime from your terminal.
Type a title — it finds a source, picks a mirror that works, and plays it in mpv.
Providers, mirrors and resolvers are internal details you never have to think about.
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser # if you don't have Scoop
Invoke-RestMethod -Uri https://get.scoop.sh | Invoke-Expression
scoop bucket add extras
scoop bucket add anime-sh https://github.com/Anime123450/scoop-anime-sh
scoop install anime-sh
From nothing. No Python, no setup — mpv is installed with it.
📖 Contents
Install · What you get · Themes · Cover art · Keys · First run · Commands · How it behaves · Troubleshooting · Develop
⚡ Install
Windows — one command
Nothing to set up first. Both of these install mpv alongside it, which is what actually plays the video.
Scoop — available now:
# Only if you don't have Scoop yet — these two lines are Scoop's own quickstart.
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
Invoke-RestMethod -Uri https://get.scoop.sh | Invoke-Expression
# mpv lives in Scoop's `extras` bucket, and a fresh Scoop only has `main`.
scoop bucket add extras
scoop bucket add anime-sh https://github.com/Anime123450/scoop-anime-sh
scoop install anime-sh
Run these in a normal PowerShell, not an administrator one — Scoop installs per-user and refuses to run elevated.
The first line is what stops Windows refusing the second with a message about running scripts being disabled. It applies to your account only, and
RemoteSignedstill requires anything downloaded to be signed — it is the setting Microsoft ships on Windows Server. AnswerYwhen it asks.
WinGet — pending review; winget already ships with Windows 10 and 11:
winget install AnimeshSharma.anime-sh
animenot recognised straight after a winget install? It worked — winget changed yourPATHand this terminal still has the old copy. Open a new one. Scoop needs no restart.
Chocolatey — pending moderation:
choco install anime-sh
mpv comes with it. For downloads, add ffmpeg:
choco install ffmpeg.
Any OS — with Python
uv is a single standalone binary that brings its own Python, so this works on
a machine with no Python at all.
# Windows
winget install astral-sh.uv ; winget install shinchiro.mpv
# macOS
brew install uv mpv
# Linux
curl -LsSf https://astral.sh/uv/install.sh | sh && sudo apt install mpv
uv tool install "anime-sh[tui]"
anime doctor
Other ways in — a single file, no terminal, or from source
Just the executable. Every release
carries anime-sh-<version>-windows-x64.exe — about 21 MB, with Python and every
library inside it. Download and run; there is no install step. You still need
mpv on your PATH.
No terminal at all. Download this repo as a ZIP, unzip, and double-click
run-anime.bat. It installs whatever is missing and starts the app.
Already have Python? pipx install "anime-sh[tui]" works — though pipx is
itself a Python package, so it cannot be the first thing you install on a
clean machine.
From source:
git clone https://github.com/Anime123450/anime-sh.git && cd anime-sh
uv sync --extra tui
uv run anime
What you need alongside it
| Why | Required? | |
|---|---|---|
| mpv | plays the video | yes — installed for you by scoop/winget/choco |
| ffmpeg | saves downloads | only for anime download |
| Python 3.11+ | runs the app | only for the PyPI and source installs |
Not sure? Run anime doctor — it checks every one of these and prints the
exact command to install whatever is missing, for the package manager you
actually have.
🎬 What you get
| 🔎 Forgiving search | atack on titan, dont toy with me — it finds them anyway |
| 🎥 Plays in mpv | driven over JSON IPC, with your own mpv config respected |
| ⏭️ Skips intros and outros | and rolls straight into the next episode |
| 📚 Remembers everything | resume position, history, favourites — in a local database |
| 🔄 AniList two-way sync | finish an episode here, your phone knows |
| 🧩 Multiple providers | fanned out with circuit breakers; one site dying is not an outage |
| 🖼️ Cover art in the terminal | unicode block sextants — no special terminal required |
| 🎨 Nine themes | previewed live as you arrow through them |
| ⬇️ Downloads | ffmpeg-backed, resumable, and played back offline automatically |
| 🔌 Plugin providers | a provider is an entry point; adding one needs no fork |
🎨 Themes
Press t. Moving the cursor applies each theme to the whole app immediately,
so you choose by looking at anime-sh rather than at a list of names —
Enter keeps it, Esc puts back the one you arrived with.
Three are anime-sh's own:
| Theme | Palette | |
|---|---|---|
| midnight | the default — deep blue-black and teal, with a warm amber focus marker | |
| ember | warm and dark, with a cool accent | |
| paper | the light one, for daylight |
Background · surface · panel · primary · accent — the three background tiers are where the screen gets its depth, and the accent is only ever "the keyboard is here".
Plus tokyo-night, nord, gruvbox, dracula, catppuccin-mocha and solarized-light.
anime themes # list them, marking the one in use
anime themes --set ember # or set it without opening the app
🖼️ Cover art, in a terminal
The panel on the right follows your cursor. Posters render as unicode block sextants — 2×3 pixels per character cell — so they work in any truecolor terminal with nothing installed. Where a real graphics protocol is available (Sixel, kitty, iTerm2) it uses that instead and comes out sharper, as above.
Underneath: what the show is, how far into the episode you are, when the next one airs, a few lines of synopsis, and exactly what Enter will do.
⌨️ Keys
| Key | Does |
|---|---|
| ↑ ↓ / j k | move within a list |
| g / G | first / last row |
| Tab / Shift+Tab | next / previous section |
| Enter | open a show, or play the highlighted episode |
| / | search |
| Esc | clear the search, or go back |
| l | your AniList list |
| t | theme picker |
| v | view — home density, or episode layout on a show |
| n | next season (on a show) |
| ? | every key, any time |
| q | quit |
🚀 First run
anime # the TUI: Continue Watching, Airing This Season, Trending
The right-hand panel follows your cursor — poster, what the show is, how far into the episode you are, when the next one airs, and what Enter will do. Below it, everything you are waiting on, grouped by day.
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.
📋 Command reference
Every command — watch, discover, library, downloads, housekeeping
# Watch
anime # launch the TUI
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
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
anime trending
anime seasonal # this season (or: --season fall --year 2025)
anime calendar --days 7 # what airs next, and when
anime random # picked from what's trending
anime recommend "Frieren" # shows for people who liked it
anime related "Attack on Titan" # prequels, sequels, side stories, movies
# Library & tracking
anime mark "Frieren" -e 12 # mark eps 1–12 watched; sets AniList progress to 12
anime mark "Frieren" -e 12 --single # just that episode, locally, no AniList
anime unmark "Frieren" # clear local progress for a show
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
# Downloads
anime download "Frieren" -e 1-12 # save a range (ffmpeg); resumes, skips done
anime download "Frieren" -e 1,3,5 # or a list; also: anime downloads
anime play "Frieren" -e 1 # plays your download if you have it
anime play "Frieren" -e 1 --stream # ignore the local copy, fetch it anyway
# Appearance
anime themes # list themes, marking the current one
anime themes --set ember # change it without opening the TUI
# 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
anime config path | validate
anime providers ls # installed providers, and which are switched off
anime providers disable anizone # stop using one without uninstalling it
anime cache info # how much is cached, how much of it is stale
anime cache prune # drop only expired entries — always safe
anime cache clear # wipe it entirely (asks first; -y to skip)
Add --json to search, trending, play, continue, history, themes
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. When its strict search comes up empty, anime-sh retries with apostrophes restored and the query's distinctive words, then fuzzy-ranks what comes back against what you typed.
Multiple providers, merged. anime-sh fans out across 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.
Streaming providers break and get Cloudflare-gated constantly — that is the normal operating state, not a bug. The Providers badge above is a nightly probe of the real sites; it going red means a site blocked us, not that the build broke. When a provider is unreachable anime-sh degrades cleanly, and metadata and your library keep working.
Offline-friendly. Your library lives in its own anime.db, separate from a
disposable cache.db of AniList responses. Recently-seen pages still render with
no network, and nothing you own lives in the cache — cache prune drops what
expired, cache clear empties it and hands the disk space back.
🩺 Troubleshooting
| Symptom | What's happening |
|---|---|
anime not recognised right after installing |
The install worked; your shell has a stale PATH. Open a new terminal (winget), or run uv tool update-shell (uv). |
doctor says mpv not found |
Nothing plays without it. doctor prints the exact command for your package manager — or scoop install mpv / winget install shinchiro.mpv / choco install mpvio. |
| A show won't play — "trying next…" on every source | Providers get Cloudflare-gated or geo-blocked. Try later, or another title; search and your library are unaffected. |
pipx / pip "not recognised" |
The wrong starting point on a clean machine — both are Python packages. Use scoop/winget, or the uv block above. |
| Windows: blocked 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), then anime sync pull. |
Updating and removing:
scoop update anime-sh # or: uv tool upgrade anime-sh
scoop uninstall anime-sh # or: uv tool uninstall anime-sh
Your library and settings live outside the install (anime config path), so
upgrading never touches them.
🛠️ 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 # unit + contract suite (no network)
uv run lint-imports # architecture contracts (must stay green)
ANIME_SH_LIVE=1 runs the gated live-provider tests.
Architecture. 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 means attaching a
source to a known identity, not fuzzy-matching titles.
📄 Architecture · Writing a plugin · Engineering standards · Contributing · Packaging
The engineering standards are worth reading even if you never contribute — each rule names the bug that caused it.
⚖️ 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.
mpv and ffmpeg are declared as dependencies, never redistributed — both are GPL-licensed, and shipping their binaries inside an MIT release would carry obligations that depending on them does not.
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.76.tar.gz.
File metadata
- Download URL: anime_sh-0.2.76.tar.gz
- Upload date:
- Size: 176.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 |
824244ef879b91d3a3054f09f3a67d3b01d7c11259cb4a92528bd8b7406448ee
|
|
| MD5 |
ff3483bd9b558be308303a6e67dbdfa7
|
|
| BLAKE2b-256 |
5fa9b42de92887abd6c7f4567befe912e691ed4a27d4d09b133baf9d7ff31d89
|
Provenance
The following attestation bundles were made for anime_sh-0.2.76.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.76.tar.gz -
Subject digest:
824244ef879b91d3a3054f09f3a67d3b01d7c11259cb4a92528bd8b7406448ee - Sigstore transparency entry: 2736207974
- Sigstore integration time:
-
Permalink:
Anime123450/anime-sh@dc67677a598f5f1a7b5e1b9bfbaaac659f2a3c7f -
Branch / Tag:
refs/tags/v0.2.76 - Owner: https://github.com/Anime123450
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@dc67677a598f5f1a7b5e1b9bfbaaac659f2a3c7f -
Trigger Event:
push
-
Statement type:
File details
Details for the file anime_sh-0.2.76-py3-none-any.whl.
File metadata
- Download URL: anime_sh-0.2.76-py3-none-any.whl
- Upload date:
- Size: 219.3 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 |
57823b71ac15a3c069d868de5fa5938fe66427a22388f3450f3c1adb9458720e
|
|
| MD5 |
7d8eab2f6ef52bb3cfbbed250037906c
|
|
| BLAKE2b-256 |
16ad01298834ededd49bb515cf0053b76668c0f89ae6a58ee6def2611d6896ee
|
Provenance
The following attestation bundles were made for anime_sh-0.2.76-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.76-py3-none-any.whl -
Subject digest:
57823b71ac15a3c069d868de5fa5938fe66427a22388f3450f3c1adb9458720e - Sigstore transparency entry: 2736208057
- Sigstore integration time:
-
Permalink:
Anime123450/anime-sh@dc67677a598f5f1a7b5e1b9bfbaaac659f2a3c7f -
Branch / Tag:
refs/tags/v0.2.76 - Owner: https://github.com/Anime123450
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@dc67677a598f5f1a7b5e1b9bfbaaac659f2a3c7f -
Trigger Event:
push
-
Statement type: