Skip to content
guitaripodPublic

About

A native Plex client for iPhone, iPad and Apple TV

Topics

Resources

Contributing

Stars

3 stars

Watchers

0 watching

Forks

Repository files navigation

Crucible

A fast, native Plex client for iPhone, iPad and Apple TV — offline downloads, Skip Intro, Picture-in-Picture, lock-screen controls and Handoff on iPhone; the same app on iPad with a library sidebar, several windows, a menu bar and keyboard shortcuts; a focus-driven Liquid Glass living-room app on Apple TV. The iPhone app builds and deploys from Arch Linux.

Crucible for Plex on the App Store — free for iPhone and Apple TV, with an optional Crucible Pro (unlimited downloads, full Statistics, the Year in Review poster, Top Shelf; pay once or subscribe yearly, one purchase for both). No server yet? Choose Try the demo on the welcome screen. The source is GPL-3.0, and a build from source is fully unlocked.

Swift Platform tvOS Arch Linux UIKit xtool Plex

No storyboards. Pure programmatic UIKit. The iPhone app is cross-compiled from Linux and deployed over USB with no Xcode and no macOS; the Apple TV app runs on the same shared modules and is built with Xcode, because xtool does not support tvOS.

Screenshots

Stack

Tool
Language Swift 6 with strict concurrency
UI UIKit — programmatic, compositional layouts, diffable data sources, content configurations, Liquid Glass on iOS 26
Playback AVKit / AVFoundation — direct play, HLS transcoding, offline file playback, Picture-in-Picture, lock-screen controls
Downloads Offline HLS engine — background URLSession segment fetch, resumable, Wi-Fi-aware, ActivityKit Live Activity
Build SwiftPM — one multi-module package; the iPhone app is cross-compiled with swift build --swift-sdk arm64-apple-ios
Deploy xtool — cross-platform Xcode replacement, build and deploy iOS apps from Linux; the Apple TV app is an Xcode project generated by XcodeGen (tv/)
Backend Plex Media Server API — OAuth PIN auth, HLS transcoding, timeline reporting
Dev OS Arch Linux

Features

Playback

  • Direct play for natively-supported codecs, automatic HLS transcoding otherwise
  • Skip Intro / Skip Credits from Plex chapter markers
  • Picture-in-Picture and background audio
  • Lock screen & Control Center controls — play/pause, skip ±10s, scrub, next episode
  • Credits-triggered Up Next autoplay between episodes, straight into the next season at a finale, keeping the subtitles and audio you chose; with Autoplay Next Episode on, the countdown runs at the credits and the next episode starts with nobody touching the remote
  • What's next after a movie: when a movie, or the last episode of a show, ends, titles like it wait over the last frame, the ones you have not seen first; pick a movie and it plays in the same player, pick a show and its page opens
  • Skip Intro your way: a glass button with a live progress sweep, automatic skipping with Undo, or off
  • Adjustable playback speed, subtitle and audio track selection
  • Resume from where you left off, progress synced to the server via the timeline API; an episode you finished counts as watched even when you leave at the credits, so it never comes back as something to continue, and one already watched starts from the beginning
  • Keeps your place through anything: a sleeping Apple TV, the app in the background or a server that dropped the stream; the stream is rebuilt at the exact moment you left, and one that stops short is never taken for the end, so the next episode never starts mid-episode
  • Rewind After a Break: coming back after a break, playback backs up a few seconds, more the longer you were away (up to 15)
  • Still watching?: after a few episodes in a row without touching the remote (2, 3 or 5; 3 by default), Up Next asks before playing on, so a season does not run on while you sleep
  • Your skip distances: 5 s to 1 min for each direction, on the Siri Remote and the iPhone's Lock Screen and headphone buttons; on Apple TV, holding either side can scan, jump 1 to 10 minutes, start over or play the next episode
  • A short skip inside a transcode seeks within the stream, and a rebuilt stream keeps your subtitles and audio
  • Languages per show: pick Japanese audio and English subtitles once and every episode of that show starts in them, matched against each episode's own tracks, so a commentary stays a commentary and forced subtitles stay forced
  • Sleep timer: 15 to 90 minutes, or the end of the episode or movie
  • Chapters: jump between a film's chapters from the player menu on iPhone and iPad, and from the system chapter list on Apple TV
  • Stream Info: how the server is playing it (direct play, or a conversion and why), over which connection, at what quality, with the video, audio and subtitle in use
  • Quality at home, away and on cellular, each its own setting, plus subtitle size and how long the Up Next countdown runs
  • Says why a stream will not play: a server that refuses a stream away from home without Plex Pass or a Remote Watch Pass, or one that cannot convert a file, gets a plain message instead of an endless spinner
  • Live from the server: Home, Server Activity and the Server Dashboard listen to the server's own event stream, so a title stopped on another device lands in Continue Watching, new titles show up and a scan's progress moves without pulling to refresh
  • Plex Home profiles: switch to anyone in your Plex Home from the You tab, with their PIN when they have one (the owner's too), and get their Continue Watching, watched state, ratings and watchlist; your own sign-in is never replaced, and a profile the server stops accepting falls back to you

Offline downloads

A proper download engine — not the afterthought the official app ships.

  • Download movies, whole seasons, or single episodes for offline viewing
  • Per-download quality — Original (source quality), High (1080p · 20 Mbps), Medium (720p · 8 Mbps), Low (480p · 3 Mbps), and Data Saver (360p · 0.7 Mbps), with a configurable default in Settings
  • Live Activity — a Lock Screen card and Dynamic Island showing live download progress (percent, current title, "X of Y"), built with ActivityKit + a WidgetKit extension — compiled and signed on Linux by xtool
  • Real offline HLS engine — the transcoded stream saved segment by segment into a local playlist, over a background URLSession that keeps going while the app is suspended; a stalled transcode gets a fresh Plex session, downloads resume from what is on disk, and a notification says when one finishes
  • Real download queue — concurrency limit plus pause / resume / cancel / retry per item and live progress
  • Wi-Fi-only by default — downloads pause when you leave Wi-Fi and resume when it returns; opt into cellular with one toggle
  • Dedicated Downloads tab — a storage summary, the live queue, and downloaded movies and shows grouped as stacks, with one-tap Free up space for watched titles
  • Season download sheet — pick All, Unwatched or the Next 3 episodes, choose the quality, and optionally keep the next episodes downloaded as you watch
  • First-class offline playback — Skip Intro / Skip Credits (markers saved with the download), resume, Picture-in-Picture, background audio, and lock-screen controls, all with no network
  • Storage management — see space used, delete individual downloads or all at once, optional auto-delete of watched downloads; media is stored on-device and excluded from iCloud backup

Remember what you watched

  • Rate What You Watched on Home: what you finished lately (a movie, a show you caught up with), each a tap from half-star ratings, with Not Now to let one go
  • Notifications you choose, each its own switch: a rating reminder after you finish something (press and hold it to rate right in the notification), new episodes of shows you are watching, watchlist arrivals when something you want lands on your server, a quiet weekly recap on Sunday evening and your Year in Review on December 1. They are worked out on the device from your own server in the background; nothing is sent anywhere
  • Remove from Continue Watching from any card's menu, on Home and in every library; the server keeps your progress, and playing it again brings it back
  • Trakt, if you want it: Settings › Integrations › Trakt stays off until you connect it with a code (a QR code on Apple TV). Then what you play is scrobbled as it plays (downloads too, once you're online), what you mark watched, rate or check in to goes to Trakt, and every title shows Trakt's score beside IMDb, Rotten Tomatoes, Metacritic and Letterboxd. If Trakt's own Plex sync already records your plays, Crucible asks which one should, so nothing counts twice. Crucible uses Trakt but is not endorsed or certified by Trakt
  • Requests through Seerr: connect Seerr, Overseerr or Jellyseerr under Settings › Integrations › Seerr (Crucible finds it next to your Plex server and signs in with your Plex account) and a watchlist title your server lacks gets Request, a show missing seasons gets Request More Seasons, and each title shows where it stands: awaiting approval, downloading with its percent and finish time, then Play. Requests also join your Plex watchlist, so Watchlist Arrivals tells you when they land. Whoever approves requests can approve, decline and retry everyone's with Crucible Pro

Browse & discover

  • Home opens on a Resume hero for whatever you were watching, then Continue Watching, Up Next, a This Week watch-time card and Recently Added — and an offline Home built from your downloads when the server can't be reached
  • Out Now on Your Watchlist on Home: a show on your Plex watchlist that your server doesn't have gets a card when a new season premieres or an episode airs, dated by Plex's own catalogue, and a tap opens Request through Seerr; the Watchlist badges the same shows and You counts them, on iPhone, iPad and Apple TV
  • What your server is missing: a show's page lists the seasons and episodes that have aired but aren't on your server, dimmed in their place with when they aired, and a tap asks Seerr for them; Up Next ends with a dimmed card for a show you're caught up on whose next episode is out but not on your server, which opens the show on that season
  • Library poster grids (3-up by default, 2-up on request) with filter chips (All, Unwatched, In Progress, Genre, Sort), unwatched dots and counts, a compact Continue banner, a Recently Watched rail with See All, an A–Z scrubber and the library switcher in the title menu; folder browsing for unindexed content
  • Movie and episode detail with an immersive backdrop, one-tap Resume, audio and subtitle menus, quality badges, Cast & Crew, a details grid and More Like This
  • Your star rating on every title, in half-star steps (a sheet on iPhone, a popover on iPad, a row of focusable half stars on Apple TV), saved to Plex with /:/rate and sortable in the library as Your Rating
  • Collections of each library, from a chip in the library header or the Part of link on a title, and playlists under You: build them from any title's menu, reorder, remove or delete them
  • Cast filmography — tap a cast member to see everything of theirs in your libraries
  • Playlists as a queue — Play and Shuffle on a playlist, or Play from Here on any entry; the Up Next card carries the queue from one title to the next
  • Trailers & Extras on a movie's detail screen, played without touching your watch history
  • More filters in the library: decade, age rating and resolution, next to genre
  • Subtitle search — look for subtitles online from the subtitle menu, pick a language and download one to the title
  • Watchlist — your Plex watchlist under You, and Add to Watchlist in a title's menu
  • Show detail with a season picker, episode rows that track watched and in-progress state, swipe actions, and a download ring on every episode
  • Search on the system search tab: recents, genre tiles, and results grouped by type with a Top Result
  • You tab: profile and live server status, a Year in Review card, Watch History grouped by day with posters, Statistics, Settings and Server & Connection
  • Statistics — a Year-in-Review dashboard: watch time, streaks, activity heatmap and top shows built from your Plex history, with a Story or Square share poster you preview before sending
  • Share Card — turn a movie, an episode, a whole season or a whole show into an image to post: the poster, the facts, when you watched it (and how fast for a season), your star rating (saved to Plex as you set it) and a few words of your own, as a 4:5 card, a 9:16 story or a square in four looks (colours from the artwork, Ember, Paper, Noir); from a title's menu, an episode's long press, Rate What You Watched, Watch History and the end of a movie or series
  • Choose your libraries — Settings › Libraries, or the filter in Statistics, picks which libraries appear on Home and count toward your statistics; libraries Plex hides from Home start switched off
  • Handoff & Spotlight — hand a title between devices, find recently-viewed media in iOS search
  • Surprise Me random picker

Settings that find themselves

  • Search every setting by what it does ("captions", "cellular", "skip"), then land on it, highlighted, in its category
  • Categories (Playback, Skip Buttons or Remote, Home & Libraries, Downloads, Notifications, Integrations, Appearance, Connection, Privacy, Help) each list their current values at a glance (Back 10 s · Ahead 30 s), and a category you changed offers Restore Defaults for just its own settings
  • Home Rows: turn each Home row on or off and put them in your order, on iPhone, iPad and Apple TV

For server owners

Shown only when the signed-in account owns the server, since the server refuses them to everyone else, and the same on iPhone, iPad and Apple TV (a title's Manage menu is a long press on Apple TV, and the dashboard is a row under You):

  • Manage in every title's menu: refresh the metadata, analyze the files, Fix Match (search the agents by title and year), Unmatch, Edit Details (title, sort title, original title, year, summary; saved fields are locked so a refresh keeps them), choose the poster or background from everything the agents offer, and delete from the server
  • Manage in a library's menu: scan the library files, refresh all metadata, analyze, empty the trash
  • Stop a stream from Server Activity with a reason the viewer sees
  • Server Dashboard: the server's CPU and memory, its background tasks with a swipe to cancel, and server updates with their release notes and Install
  • Show Settings in a show's Manage menu: the server's own settings for that show (episode order, seasons shown or hidden, audio and subtitle languages for everyone, what happens to watched episodes), in the server's words
  • Remove a play from Watch History, which takes it out of the server's history and statistics too

iPad

Crucible on iPad: Home with the library sidebar, a library grid, a movie and the player with Skip Intro

The iPhone app is universal, and every screen lays out by the room its window has, so Split View, Slide Over, a small window and a full 13-inch screen each get a layout made for them.

  • Sidebar — Home, Downloads, You, Search and each Plex library on its own row; the tab bar keeps a single Library tab in narrow windows
  • Large-screen layouts — bigger rails and posters, grids that add columns as the window grows, 16:9 detail artwork with a readable column of text and controls, centred lists, and a Statistics dashboard with four tiles a row
  • Windows — open any title in a new window from its menu or by dragging its card to the edge of the screen; each window keeps its own tab and title across launches, is named after what it shows, and stops its own player when it closes
  • Magic Keyboard — a full menu bar and shortcuts (Command-1 to 4 for tabs, Command-F, Space to play, S to skip the intro, N for the next episode), with arrow and Tab keys through every grid and list
  • Pointer — posters and cards lift under the trackpad and Apple Pencil hover, rows and chips highlight, right-click opens every context menu

Apple TV

Crucible on Apple TV: Home, the player, context menus, library, detail and Statistics

The same engine in a layout built for the couch and the Siri Remote. Everything that is not presentation — networking, playback, statistics, every screen's rules — is shared with the iPhone app; the Apple TV screens only render it.

  • Top tab bar — Home, one tab per Plex library, Search and You; libraries you switch off in Settings leave Home and Statistics but keep their tab
  • Cinematic Home — a full-screen backdrop that follows focus, a hero with title, metadata and synopsis, then Continue Watching, Up Next, Recently Added and more; Select opens, Play/Pause plays, long press opens the context menu
  • Library poster grid with filter chips, a Recently Watched shelf, an A–Z rail, folder browsing for unindexed content and See All grids
  • Detail for movies, shows and episodes: season chips, episode rows that track watched and in-progress state, Cast & Crew and related titles
  • Rate What You Watched and Remove from Continue Watching on Home, Home Rows, searchable Settings categories, Stream Info and chapters in the player, a sleep timer, languages remembered per show, titles like a movie when it ends, live updates from the server, Plex Home profiles, and every owner tool (Manage, Show Settings, Fix Match, Edit Details, artwork, Stop Stream, the Server Dashboard, Remove from History)
  • Rate, collect, queue — rate any title in half stars with the remote's swipe, open a library's Collections or a title's own collection, add titles to playlists from a long press or the detail screen, play or shuffle a playlist, watch trailers and extras, filter a library by decade, rating or resolution, search for subtitles, keep a watchlist, and open a cast member's titles
  • Search, Watch History, Statistics (heatmap, patterns, binges, taste) and a Year in Review card on the You tab, plus Settings and Server & Connection
  • Player on the system player — Skip Intro and Skip Credits as native actions, an Up Next card that offers Play Now or Watch Credits with a countdown (or Still watching? after a run nobody touched the remote in), audio and subtitle menus, resume where you left off through sleep, the screen saver and a dropped stream, Rewind After a Break, progress reported through the timeline API
  • Top Shelf — Continue Watching, Up Next and new arrivals on the Apple TV Home screen, each with its details, badges and cast, playing the scene where you stopped or the trailer
  • Sign in from your phone — a short code for plex.tv/link plus a QR code
  • Liquid Glass controls on tvOS 26 (Apple TV 4K 2nd generation or later); older systems and boxes get the classic look with the same layout

Built different

  • Liquid Glass materials on iOS 26, with one design system underneath: tokens for colour, type, spacing and radii, one ember accent, and Light and Dark appearances
  • Accessible — Dynamic Type everywhere, VoiceOver labels, Reduce Motion fallbacks, 44pt targets and contrast-checked colour pairs
  • Server & Connection screen with per-route latency (Local, Tailscale, Relay), Prefer Local and Allow Relay switches, and add-by-address
  • Automatic best-connection server discovery (prefers local, non-relay, HTTPS) that also finds a server on your Tailscale network by itself, verifies it by its Plex machine identifier, and can search the tailnet's device list when the names do not match
  • Live watched/progress refresh across Home, Library, and detail screens — never stale on return
  • On-device file logger for diagnostics without a Mac attached, shareable from Settings
  • Plex OAuth sign-in, token stored in the Keychain

Building

Requires Swift 6+ via swift-bin (AUR) and the iOS cross-compilation SDK.

swift build --swift-sdk arm64-apple-ios --build-system native

Apple TV

The Apple TV app needs a Mac with Xcode 26 or newer and XcodeGen. The manifest only declares the tvOS targets when it is evaluated on macOS, so the Linux and xtool build above is unaffected.

cd tv && CRUCIBLE_PACKAGE_NAME=$(basename "$(cd .. && pwd)" | tr '[:upper:]' '[:lower:]') xcodegen generate && open CrucibleTV.xcodeproj

tv/README.md covers the simulator workflow (build, run, UI tests and screenshots against a mock Plex server, driven from Linux over ssh) and the real-device one: ./scripts/install-tv.sh builds and signs on the Mac and installs on a paired Apple TV with devicectl.

Episode-flow benchmark

scripts/mac.sh bench runs Sources/CrucibleBench (declared only with CRUCIBLE_BENCH=1, so no app build ever sees it) on the macOS host. It scores going from one episode to the next and keeping watched state in step: 26 probes against canned Plex responses, ending in a crucible-bench 26/26 100% line.

Deploying

New to this? INSTALL.md walks through putting Crucible on your own iPhone, step by step.

Requires xtool and a USB-connected iPhone.

./scripts/install-ios.sh

The script checks your setup, builds a release configuration and installs it with xtool dev run -c release --usb. Run it with --check to verify without building.

Marketing screenshots

The README and landing-page images are real captures of the app running in the iOS Simulator against a mock Plex server with generated, fictional artwork — no real library or copyrighted posters. marketing/mock/ is the server and art generator, marketing/shots/ drives the app and takes the screenshots (run.sh), and compose.sh frames them with the frames CLI (Apple device bezels) for the README banner and the gallery. marketing/tv/ does the same for Apple TV: it frames 4K simulator captures with a slim TV bezel through the frames CLI and lays them out as a share collage (collage.sh).

Architecture

One SwiftPM package: five shared modules, two apps and their extensions. Dependencies only point downward; CrucibleCore has no UIKit, so its logic is tested on the macOS host without a simulator.

Sources/
├── CrucibleCore/        # Networking, models, sessions, preferences, logging, formatting, and the rules of every screen (Features/*)
├── CrucibleMedia/       # PlaybackSession: stream resolution, resume, self-healing after absences, timeline reporting, skip markers, Up Next (AVFoundation)
├── CrucibleStats/       # GRDB-backed watch-history mirror, sync, queries, Year in Review
├── CrucibleDesign/      # Theme tokens, Glass, haptics, image pipeline, brand atoms
├── CrucibleStatsUI/     # Charts and stats components shared by both apps
├── Crucible/            # The iPhone app: screens, downloads engine, Live Activity glue
├── CrucibleActivity/    # Shared ActivityAttributes (compiled into app + widget)
├── CrucibleWidgets/     # WidgetKit extension — download Live Activity (Lock Screen + Dynamic Island)
├── CrucibleTV/          # The Apple TV app: screens, focus-driven design system, player
└── CrucibleTopShelf/    # Top Shelf content built from the snapshot the app writes to the App Group
tv/                      # XcodeGen project, Top Shelf extension, UI tests and simulator scripts
Tests/CrucibleCoreTests/ # Swift Testing suites for Core and Stats (swift test with CRUCIBLE_CORE_ONLY=1 on macOS)

docs/ARCHITECTURE.md has the module graph, the rules (access control, platform seams, feature slices), what lives where and how to add a feature.

The widget extension is built and signed entirely on Linux via xtool's extensions: mechanism — Live Activities with no Xcode.

One third-party dependency, GRDB, for the statistics store. Everything else is Apple frameworks: Foundation, UIKit, AVKit/AVFoundation, MediaPlayer, Network, BackgroundTasks, ActivityKit, WidgetKit, UserNotifications, CoreSpotlight, WebKit, Security, TVServices.

About

A native Plex client for iPhone, iPad and Apple TV

Topics

Resources

Contributing

Stars

3 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages