tv-anarchy/docs/operations.md
Natalie 5b47531b5c docs(@applications): 📝 update architecture and data model docs
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-06-08 22:07:16 -07:00

4.4 KiB

Operations

How to build, install, configure, and run every component. Schemas referenced here are detailed in data-model.md.

The app

./build-install.sh

Stamps build identity (git SHA / time → BuildStamp.swift), runs xcodegen, builds Release, and copies TVAnarchy.app to ~/Applications. The one irreducible manual step is quit + relaunch — a running native app can't be hot-swapped. The sidebar build stamp (v<ver> · <sha> · <time>) makes a stale copy obvious.

Build manually / in Xcode

brew install xcodegen          # if needed
xcodegen generate              # project.yml → TVAnarchy.xcodeproj (generated, git-ignored)
xcodebuild -scheme TVAnarchy -destination 'platform=macOS' build
# or open TVAnarchy.xcodeproj and Run

project.yml is the source of truth; the .xcodeproj is generated. Local dev is unsigned (no sandbox/hardened runtime — the app needs Process/ssh and localhost+overlay networking).

Config & state locations

File Purpose
~/.config/tv-anarchy/hosts.json Playback targets (migrates from ~/.config/plumtv/hosts.json)
~/.config/portable-net-tv/config.json Governor config and the VLC HTTP password source
~/.local/state/plum-control-mcp/watched.jsonl Shared watch log
~/.local/state/tv-anarchy/library.json Cached library snapshot
~/.local/state/tv-anarchy/meta/ Metadata sidecars (path-digest keyed)
$VLC_HTTP_PASSWORD Alternate VLC password source

Playback targets

  • Plum VLC — enable VLC's HTTP/Lua interface (Preferences → All → Interface → Main interfaces → Lua), set the password (read from the governor config or $VLC_HTTP_PASSWORD). App talks to http://127.0.0.1:8080/requests/….
  • Black (mpv) — mpv is driven straight to the DRM console (no X) over SSH JSON IPC; the commands templates delegate launch/library/stats/teardown to /usr/local/bin/black-tv. Endpoints try LAN (10.0.0.11) then the WG overlay (10.9.0.4) because the LAN address flaps.
  • QuickTime — local, zero-install; no setup.

Hosts are editable in-app (Hosts tab: add/edit/delete, make-active, reload, reset, reveal hosts.json).

governor (portable-net-tv)

TypeScript/Bun standalone daemon on plum.

cd governor
bun install
portable-net-tv watch     # daemon: follow VLC, log watches, prefetch next N eps
portable-net-tv next      # print per-show progress

Runs as a launchd background agent (Apple Events to VLC are blocked there, which is why it reads VLC over HTTP, not AppleScript). Config: see data-model.md.

mcp (plum-control-mcp)

TypeScript/Bun. Serves both an MCP stdio server (for Claude) and the CLI bridge the app shells out to.

cd mcp
bun install
bun run typecheck
claude mcp add plum-control       # register the MCP server with Claude Code

Requirements/constraints:

  • macOS only (NSScreen via osascript-jxa; reads org.videolan.vlc.plist).
  • VLC must be running with the Web interface enabled.
  • Torrent search needs FlareSolverr on localhost:8191 (TPB/Nyaa/1337x).
  • media_list_shows scans MEDIA_ROOTS (default ~/media) for SxxEyy files.
  • Black-TV watch state is black-local (/usr/local/share/black-tv/), read over SSH, never written to plum/NFS.

recommender

Python (managed with uv). Invoked by the app's EnrichService during indexing/enrichment; not on the playback path.

cd recommender
uv run python -m media_rec.enrich "<title>" [year] [--category <cat>]
uv run python recommend_local.py     # keyless local recommendations (preferred)
uv run python recommend.py           # TMDB-backed (needs an API key)

Provider routing by category: anime → AniList, tv/cartoons → TVmaze, fallback → TMDB; degrades gracefully on missing keys/failures. registry.md is a generated snapshot of black's library used as the offline title source.

Black-side artifacts

  • Prebuilt index: /bigdisk/_/media/_tools/index.tsv (TSV size⇥mtime⇥path), fetched by LibraryIndex via one SSH cat; rebuilt with nice/ionice because black seeds 200+ torrents.
  • Registry: black's .registry.md dump → recommender/registry.md.

Verification after changes

  • App: ./build-install.sh, relaunch, confirm the build stamp updated.
  • governor/mcp: bun run typecheck in each package.
  • recommender: run an enrich for a known title and confirm JSON output.