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 (recommended)
./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 tohttp://127.0.0.1:8080/requests/…. - Black (mpv) — mpv is driven straight to the DRM console (no X) over SSH JSON
IPC; the
commandstemplates 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_showsscansMEDIA_ROOTS(default~/media) forSxxEyyfiles.- 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(TSVsize⇥mtime⇥path), fetched byLibraryIndexvia one SSHcat; rebuilt withnice/ionicebecause black seeds 200+ torrents. - Registry: black's
.registry.mddump →recommender/registry.md.
Verification after changes
- App:
./build-install.sh, relaunch, confirm the build stamp updated. - governor/mcp:
bun run typecheckin each package. - recommender: run an
enrichfor a known title and confirm JSON output.