GitHub

Rust License Platform GitHub release GitHub stars Stay Amazing

A fast terminal browser for discovering and managing movies and TV series. Pulls top-rated and popular lists from TMDB, keeps your own wish and dump lists, renders posters inline. Rust feature port of IMDB-terminal, built on crust and glow.

"Cut down the time spent searching in favor of time spent watching and cuddling."

Screenshot

Screenshot

Movie browser with genre filter, wishlist/dump pane, and poster preview.

Install

# Prebuilt binaries (Linux x86_64/aarch64, macOS Intel/Apple Silicon):
# https://github.com/isene/watchit/releases
# Or build from source:
git clone https://github.com/isene/watchit
cd watchit
cargo build --release
./target/release/watchit

Recommended companions

  • kitty, wezterm, foot, or iTerm2 for inline poster rendering (via glow)
  • ImageMagick + w3m-img if your terminal only supports w3m-style images
  • No Ruby, no node, no pip. One static binary.

First Run

watchit requires a free TMDB API key. Get one at https://www.themoviedb.org/settings/api (signup → "Create" under API → choose "Developer" → fill in the form, any plausible app description works). Save the v3 key.

Then either:

  1. Launch watchit and press K to enter the key (or R to set the streaming region, ISO code like US, NO, GB).
  2. Or edit ~/.watchit/config.yml directly:
    tmdb_key: "your-v3-api-key-here"
    region: "US"

Press I to fetch the top-rated movies and TV from TMDB. Press L to additionally pull the popular-now lists.

Migrating from IMDB-terminal

If you used the Ruby IMDB-terminal gem, watchit auto-imports its config and cached posters:

  • ~/.imdb.yml~/.watchit/config.yml
  • ~/.imdb/data/list.json, details.json, tt*.jpg posters → ~/.watchit/data/

The imported rows are keyed by IMDB tconst (tt1234567), while everything else here — details, posters, the phone app — is keyed by TMDB id. Press M once to fix that for good: TMDB's /find endpoint resolves each tconst to its TMDB record exactly, and the details cache, the cached poster, the wish and dump lists and your rating all follow the title to its new id. A few hundred titles take a couple of minutes; it is safe to interrupt and re-run, and it only touches rows that are still tconst-keyed.

Without it, cross-referencing rests on matching titles — and titles disagree. TMDB calls it "Arcane"; the import called it "Arcane: League of Legends", so a rating made on the phone never reaches the imported row.

Features

  • Top-rated and popular lists for movies and series, pulled from TMDB
  • Load additional lists — popular movies and TV (press L)
  • Per-title details: plot, cast, directors, runtime, genres, release date, seasons/episodes for series, content rating
  • Streaming info — shows where each title is available in your region (TMDB watch/providers)
  • Five panes: list, genre filter, wish, dump, detail with poster
  • Focus-based borders — the active pane highlights itself
  • Poster display inline in the detail pane (kitty/sixel/w3m via glow)
  • Genre filtering: include (+), exclude (-), or clear (Space) on the highlighted genre
  • My own ratings — score any title 1-10 with a single keypress, sorted and synced
  • Claude recommendations (c) grounded in what you rated, scoped to the current view and genre filter, and picked from: ENTER adds a title to the list, w adds it and wishlists it
  • A conversation about what to watch (C), seeded with the same taste profile
  • Rating / year filters, sort by TMDB rating, alphabetical, or my rating
  • Wish and dump lists separate for movies and series
  • Multi-search (/) across TMDB movies and TV: pick from the hits with the highlighted one's description under the list, filed by what it actually is
  • Background threads for fetch — UI never blocks
  • Fetch all missing (v) — one parallel sweep for every detail and poster still absent; Refetch (f) — re-pull current item
  • Duplicate removal (D) across all lists

Keys

Key Action
TAB / S-TAB Cycle focus between list / genres / wish / dump
UP / DOWN, j / k Move within focused pane
PgUP / PgDOWN Page
HOME / END First / last
+ Add to Wish (list) / Include genre (genres)
- Dump (list) / Exclude genre / Remove (wish+dump)
Space Clear genre filter on highlighted genre
1-9 Rate the highlighted title 1-9
0 Rate it 10
DEL Clear my rating
m Show only titles I have rated, best first
c Ask Claude what to watch next, then pick: ENTER adds, w adds + wishlists
C Discuss recommendations with Claude (same scope)
l Toggle Movies / Series view
o Cycle sort (TMDB rating / alphabetical / my rating)
r Set minimum rating
y / Y Set min / max year
/ Search TMDB — pick from the hits, with each one's blurb below the list
I Fetch top-rated movies + TV (background)
i Incremental fetch of missing details
f Re-fetch current item
v Fetch every missing detail and poster in one parallel sweep
L Load popular movies + TV (background, no duplicates)
D Remove duplicates — same id, and the same title imported twice
M Migrate legacy IMDB ids to TMDB ids (one-off)
K Set TMDB v3 API key
R Set streaming region (ISO code)
W Save config now
? / q Help / Quit

Configuration

~/.watchit/config.yml (auto-created / auto-imported on first run):

tmdb_key: ""
region: US
rating_min: 7.5
year_min: 0           # 0 = no filter
year_max: 0
sort: rating          # "rating" or "alpha"
view: movies          # "movies" or "series"
show_posters: true
movie_limit: 250
series_limit: 250
wish_movies: []
wish_series: []
dump_movies: []
dump_series: []
genres_include: []
genres_exclude: []

TMDB region for streaming providers

A TMDB API key is required (see "First Run" above). After the key is set, pick the region for streaming-availability lookups:

  1. Press R and enter an ISO country code (e.g. US, GB, NO)
  2. Press i to refetch details; streaming providers appear in the detail pane for titles available in that region

File Layout

~/.watchit/
├── config.yml           # Your preferences (incl. tmdb_key, region)
├── data/
│   ├── list.json        # Movie + series metadata (title, rating, year, genres)
│   ├── details.json     # Per-title details cache
│   └── *.jpg            # Poster images (TMDB IDs)
└── sync/
    ├── ratings-*.json   # My ratings, one file per device (shared with the phone)
    ├── catalog-*.json   # The list itself, one file per device
    └── tmdb_key.txt     # So the phone never needs the key typed in

The phone

Press a digit and the highlighted title carries your score. Everything shared with the nomad watchit app lives in ~/.watchit/sync/, one file per device — share that folder with the nomad watchit app over Syncthing and both ends see every rating. Each device only ever writes its own file, so there is nothing for Syncthing to conflict over; per title, the newest rating wins. Clearing a rating is itself a timestamped event, so a clear on one device sticks on the other.

The catalog travels the same way, but as a union: each device adds titles separately and neither ever means "delete what I do not have", so nothing is dropped and empty fields (year, genres, poster) are backfilled from whichever device did the fetch. It is written when titles are added and once on quit — the phone is not watching in real time.

The TMDB key is published here too, so the phone picks it up instead of having it typed in on a phone keyboard. A device that already has a key keeps it.

Each rating carries its title and year as well as its id, because the two ends do not share an id space — a catalog imported from IMDB-terminal still holds tt… ids while the phone keys everything by TMDB id. The title bridges them, so the same film is one rating on both devices either way.

Data Sources

All data comes from a single backbone:

  • Lists: TMDB top-rated and popular endpoints (/movie/top_rated, /tv/top_rated, /movie/popular, /tv/popular)
  • Per-title details: TMDB /{movie|tv}/{id} with append_to_response=credits,external_ids,watch/providers,release_dates — one request returns plot, cast, crew, streaming providers, region-specific content rating, and IMDB cross-reference id
  • Search: TMDB /search/multi (movies + TV in one query)

The detail pane shows two click-through links per title: TMDB (the data source) and IMDB (when TMDB has the external id on file — most films from the last ~50 years).

Why TMDB and not IMDB scraping: IMDB now sits behind a CloudFront WAF that serves a JavaScript challenge to plain HTTP, so the old JSON-LD scrape returns nothing. TMDB has a free, well-documented REST API and the same metadata for the same titles.

Part of the Rust Terminal Suite (Fe2O3)

See the Fe₂O₃ suite overview and the landing page for the full list of projects.

All Fe2O3 tools share crust for the TUI and are installed as single static binaries. Fast startup, no runtime dependencies.

License

Unlicense (public domain). Borrow or steal whatever you want.

Read the original on github.com ↗