---
name: black-mirror-app
description: BLACK MIRROR. — a native macOS studio app for generating archival-collage videos from the Internet Archive in the Black Mirror local style. Drop your own footage in STUDIO, search a vibe in HUNT, or hit SURPRISE for a fully Claude-curated random combo. Two-pass title-aware picker via Claude Code CLI, in-app inline player, drag-to-export, optional Telegram push. Built in SwiftUI for macOS 14+, ships with bundled Python+ffmpeg edit pipeline. v1.0.0.
---


# BLACK MIRROR. — Archive Studio (macOS app)

A native SwiftUI desktop app that wraps the `black-mirror` skill into a full studio. Hunt vibes, drop sources, render multi-panel archive videos, play inline, push to Telegram.

This package contains BOTH a **prebuilt** debug binary (instant try) AND the **full Xcode source** (clone, hack, rebuild).

## What you need

- macOS 14+ (built and tested on macOS 26 / Apple Silicon)
- Homebrew with `ffmpeg` and `node` installed
- Claude Code CLI installed: `npm i -g @anthropic-ai/claude-code` and `claude login`
- Python 3 (system `/usr/bin/python3` works fine)

## Quick start (try the prebuilt app)

```bash
# From this skill's root after install:
cp -R prebuilt/BLACK\ MIRROR.app ~/Applications/
open ~/Applications/BLACK\ MIRROR.app
```

That launches the v1.0.0 debug build. First launch may need a Gatekeeper override:
right-click → Open → Open. The app is unsigned (debug).

## Build from source

```bash
cd src
xcodebuild -project BlackMirror.xcodeproj \
           -scheme "BLACK MIRROR" \
           -configuration Debug \
           -derivedDataPath build
cp -R "build/Build/Products/Debug/BLACK MIRROR.app" ~/Applications/
open ~/Applications/BLACK\ MIRROR.app
```

Release build: same command with `-configuration Release`.

## What the app does

Three tabs:

- **HUNT** — discovery. Tap a curated cloud (MENTAL HYGIENE, CIVIL DEFENSE, NIGHT CITY, …) to pull 2 random IA items from that vein, OR type a vibe ("punk concerts 90s") and Claude does a two-pass title-aware curation. Sources stage into STUDIO automatically.
- **STUDIO** — the renderer. Drop any video format ffmpeg can read (MP4/MOV/MKV/AVI/WEBM/etc.). Pick STYLE + LAYOUT + DURATION + RESOLUTION (1080p / 720p / 540p / 360p). Hit RENDER. Inline AVPlayerView when done. Drag the player anywhere, save-as, reveal in Finder, or push to Telegram.
- **SURPRISE** — one big STAGE button. Claude picks a random combo (cloud + style + layout + duration) and stages everything in STUDIO for you to render.

CONSOLE (gear icon, top right) — five SYSTEM modes (LIGHT / DARK / BARE / TINT / MEDIA), default duration / style / layout / resolution, prompt backend status, telegram availability, storage size + clear cache.

## Architecture

- **`Models/`** — RenderEngine (Python+ffmpeg subprocess), PromptEngine (Claude CLI two-pass), ArchiveItem (IA download URLs), AppStorage (`~/Library/Application Support/BLACK MIRROR/` paths), TelegramClient (direct HTTPS to bot API), CloudHistory (recent/frequent vein tracking), AppDefaults.
- **`Views/`** — HuntView / StudioView / SurpriseView, plus `Components/InlinePlayer.swift` (AppKit AVPlayerView wrapper that bypasses the SwiftUI VideoPlayer crash on macOS 26), RenderStatusPanel (live SYSTEM-V2 parameter rows), SystemProgressBar, OutputPanel, TokenSelector, SourceChip, etc.
- **`Theme/`** — SystemV2 (the chrome — gear popover, modes, sound engine), SystemTheme (palette helpers).
- **`Resources/Scripts/`** — bundled `ia_find_video.py` + `black_mirror_split_edit.py` (the python edit engine, renders panel grids via ffmpeg filter graphs).
- **`Resources/archive-veins.md`** — search-cloud reference.

## Where everything lives at runtime

```
~/Library/Application Support/BLACK MIRROR/
├── sources/   ← IA download cache (reused across renders)
├── renders/   ← finished MP4s, organized by timestamp + style slug
└── work/      ← intermediate 720p renders before final scale (auto-cleaned)
```

CONSOLE → **STORAGE** row shows current size, **CLEAR CACHE** wipes `sources/`.

## Two-pass curation flow (HUNT prompt / SURPRISE)

1. **Plan** — Claude CLI translates your prompt into an IA query (with era extraction: "1960s" → `date:[1960 TO 1969]`, etc.) and a style/layout/duration combo.
2. **Search** — IA `advancedsearch.php` with `sort=random` (no decade bias) returns 30 candidates.
3. **Rank** — Claude CLI gets the 30 titles + dates + your original prompt, picks the strongest 5 by judgment. Skips slideshows, off-topic, watermarked stock.
4. **Download** — engine pulls the top 2 (skips 404s, falls back through ranked list, tolerant up to 30 candidates).
5. **Render** — STUDIO. Python edit script → ffmpeg final scale. Auto-retries with simpler combo if filter graph chokes.

Tap-to-cook canonical clouds skip the rank step (they're intentional curated experiences).

## Telegram

Reads `~/.claude/telegram/config` (the same file the `assistant` skill writes — single source of truth). Direct HTTPS multipart upload to `api.telegram.org/bot<TOKEN>/sendVideo`. Doesn't shell out — works under hardened-runtime sandbox.

CONSOLE → AUTO-PING TELEGRAM toggle, plus PING TELEGRAM pill on every OutputPanel.

## Known sharp edges

- Heavy filter combinations (3+ styles) sometimes fail ffmpeg. Engine auto-retries with the first style+layout — you'll see `retrying with simpler combo: …` in the LATEST log row.
- Render time scales nonlinearly with style/layout complexity. Expect 60-300s for an 18s output. ETA recalibrates after 10% progress.
- macOS 26 SwiftUI `VideoPlayer` aborts; we use `AVPlayerView` via `NSViewRepresentable` instead. If you fork on an older OS, the original SwiftUI player will work fine too.

## Credits

- Built by **Gualo Hawes** on top of the `black-mirror` skill (by `30wontjam`/Glo).
- Internet Archive is the source of all archival footage — public-domain / Creative Commons items only by default.
- ffmpeg + Python do the heavy editing; Claude does the curation.

---

v1.0.0 · April 2026
