# Project pack: Jellyfin @ c7ce6a1

Facts about **Jellyfin** for an AI following the [BespokeAI handover guide](https://handoff.bespokeai.software/guide/v1.md). This pack is pinned to one version and never changes after publication.

> Jellyfin turns a folder of films, TV series, music and home videos into a streaming service for your household. It finds posters, descriptions and cast details for you, remembers where everyone stopped watching, and plays on phones, smart TVs, games consoles and web browsers. It is completely free, with no paid tier, no adverts and no account with a company.

## Version and source
- Repository: https://github.com/jellyfin/jellyfin
- Pinned commit: `c7ce6a1b56ee7dcc1896250df0f2f9deaa828a81`. Use exactly this version.
- Get it: `git clone https://github.com/jellyfin/jellyfin jellyfin && cd jellyfin && git checkout c7ce6a1b56ee7dcc1896250df0f2f9deaa828a81`
- Or download a zip: https://github.com/jellyfin/jellyfin/archive/c7ce6a1b56ee7dcc1896250df0f2f9deaa828a81.zip
- Official docs: https://jellyfin.org/docs/
- Live demo: https://demo.jellyfin.org/stable. Official shared demo linked from jellyfin.org. The login details are shown on its login page.
- Licence: **GPL-2.0-only**. Free to use and change. If you give copies of the program (changed or not) to other people, you must share the source code under the same licence. Running it for your household, or for friends over the internet, has no extra obligations. (The repository's LICENSE is GPL version 2; some library packages are labelled GPL-3.0.)

## Running it
- Easiest:

  ```sh
  docker run -d --name jellyfin -p 8096:8096/tcp -p 7359:7359/udp -v jellyfin-config:/config -v jellyfin-cache:/cache --mount type=bind,source=/path/to/media,target=/media --restart=unless-stopped jellyfin/jellyfin # then open http://localhost:8096 and follow the setup wizard (language, admin account, media folders)
  ```

- Needs: Docker on Linux (the docs recommend native installers on Windows and macOS), or the native packages, Enough CPU or a supported GPU if you need to convert video on the fly, For server development, the .NET 10 SDK and jellyfin-ffmpeg, plus a build of jellyfin-web
- Develop: `dotnet run --project Jellyfin.Server --webdir /absolute/path/to/jellyfin-web/dist   # http://localhost:8096; or use --nowebclient and run jellyfin-web separately`
- Test: `dotnet test Jellyfin.sln`
- Check/lint: `dotnet format --verify-no-changes --verbosity minimal`
- Build: `dotnet build`
- Stack: csharp (.NET 10, ASP.NET Core, Entity Framework Core, FFmpeg). Difficulty for a non-developer with an AI: **advanced**. This repository is only the server: a large .NET solution (about 2,600 files) covering the API, library scanning, metadata and FFmpeg transcoding. The web interface people see is a separate project, jellyfin/jellyfin-web (JavaScript/TypeScript), and the TV and phone apps are separate again. Most personal changes are settings, custom CSS, web config or plugins; real code changes need .NET skills and usually the web client too.

## The project's own AI instructions
Read these in the repository before changing code: `.github/pull_request_template.md`.

## Customisation points (settings → extend → code)
- **branding-and-css** [settings]: Change colours, hide parts of the screen or add a welcome message, with no rebuild. → `Dashboard → Branding (login disclaimer, custom CSS); per user Settings → Display (docs/general/clients/css-customization.md on jellyfin.org)`
- **users-and-parental** [settings]: Give each person their own profile, limit children to suitable ratings and set viewing hours. → `Dashboard → Users (library access, parental ratings, tags to block, access schedules)`
- **libraries-and-metadata** [settings]: Which folders appear as Films, TV, Music or Home Videos, and where details and posters come from. → `Dashboard → Libraries (metadata sources, languages, image fetchers per library)`
- **playback-and-transcoding** [settings]: Use a graphics card to convert video, and cap quality when watching away from home. → `Dashboard → Playback (hardware acceleration, bitrate limits)`
- **web-config** [extend]: Add links to other family services in the menu and change web client defaults. → `config.json in the jellyfin-web folder (docs/general/clients/web-config.md on jellyfin.org), e.g. custom menu links`
- **plugins** [extend]: Install community plugins or write your own (subtitles, Trakt, intro skipping, OpenID login…). → `Dashboard → Plugins; plugin API in MediaBrowser.Common/Plugins/; built-in examples in MediaBrowser.Providers/Plugins/`
- **rest-api** [extend]: Scripts, home automation ("pause the film when the doorbell rings") or a custom remote. → `REST API with API keys (Dashboard → API Keys), docs at /api-docs/swagger on your server, controllers in Jellyfin.Api/Controllers/`
- **server-code** [code]: New API endpoints, scanning or naming rules. Screen changes belong in the jellyfin/jellyfin-web repository. → `Jellyfin.Api/Controllers/, Emby.Server.Implementations/, MediaBrowser.Controller/, Emby.Naming/ (file-name parsing)`

## Must keep working
- Media files. Never let a change rename, move or delete media without a backup.
- Watch history and user accounts in /config. Back up before upgrades or code changes.
- Parental controls and per-user library access.
- The API used by every client app (TV, phone, web). Don't change existing endpoints or responses.

## Staying updatable
Settings, custom CSS, web config and plugins cover nearly every household need without a fork, and plugins survive upgrades. Jellyfin's LLM policy (jellyfin.org/docs/general/contributing/llm-policies) rejects "vibe-coded" pull requests and forbids AI-written PR text; the PR template asks you to disclose code assistance. Keep AI-assisted changes in your own copy or plugin unless you fully understand and can explain them.

## Data, costs and safety
- Personal data: **yes**. Stored in: Your media files stay where they are (mounted read-only is fine). Users, watch history, settings and the library database live in the config and data folders (/config in Docker); artwork and transcodes in /cache. Back up the /config volume. Recent versions include a built-in backup and restore (Dashboard → Backups, Jellyfin.Server.Implementations/FullSystemBackup/). Media files are never changed unless you allow it.
- Service: Metadata sources (TheMovieDb, OMDb, MusicBrainz, TheAudioDB) (optional, free): Posters, descriptions, cast and album details. Titles of your media are looked up online; you can turn sources off per library.
- Service: Plugin repository (repo.jellyfin.org) (optional, free): Install extra plugins such as subtitles downloaders, Trakt sync or OpenID login from the dashboard.
- Service: Live TV tuner or IPTV (optional, varies): Watch and record live television with an HDHomeRun or M3U playlist.
- Setting `JELLYFIN_DATA_DIR`: Where the database and library data are kept.
- Setting `JELLYFIN_CONFIG_DIR`: Where settings and user data are kept (the /config volume in Docker).
- Setting `JELLYFIN_CACHE_DIR`: Where images and transcoding scratch files go (the /cache volume in Docker).
- Setting `JELLYFIN_LOG_DIR`: Where log files are written.
- Setting `JELLYFIN_WEB_DIR`: Folder of the jellyfin-web files the server should host.
- Setting `JELLYFIN_NOWEBCONTENT`: Set to true to stop the server hosting the web client (for front-end development).
- Don't forward port 8096 straight to the internet. Use a VPN (e.g. Tailscale) or an HTTPS reverse proxy, and strong passwords.
- Mount media folders read-only unless you need Jellyfin to write artwork next to them.
- API keys have admin-level power. Never paste them into an AI chat.
- Sharing films and series beyond your household may break copyright law.

---

# Customising Jellyfin

Jellyfin is several projects. **This catalogue entry pins the server** (`jellyfin/jellyfin`, C#/.NET). The web interface is a separate repository, **`jellyfin/jellyfin-web`** (JavaScript/TypeScript), and the TV and phone apps are separate again. Nearly every household need is a setting, custom CSS, web config or a plugin. Use levels 1 and 2 first.

## Level 1: Settings (no code)
- **Look:** Dashboard → Branding.
  - *Login disclaimer* (a welcome message on the login page) and *Custom CSS* for everyone.
  - Each person can add their own CSS under Settings → Display.
  - CSS only affects apps built on Jellyfin Web (browser, desktop and some TV apps).
- **People:** Dashboard → Users.
  - Which libraries each person sees, and maximum parental rating.
  - Blocked tags and access schedules (viewing hours).
  - Whether they may download or delete.
- **Libraries:** Dashboard → Libraries. Content type (Films, Shows, Music, Home Videos…), metadata language, which sources fetch details and posters.
- **Playback:** Dashboard → Playback. Hardware acceleration (see the transcoding docs) and bitrate limits for remote viewing.
- **Networking:** Dashboard → Networking. Published server address, remote access, allowed networks.
- **Backups:** Dashboard → Backups (recent versions) makes a full backup archive you can restore.

## Level 2: Extend (no fork)
- **Web config:** `config.json` in the jellyfin-web folder. In Docker, mount it to `/jellyfin/jellyfin-web/config.json`. Use it for custom menu links and web-client defaults (see "Jellyfin Web Configuration" in the docs).
- **Plugins:** Dashboard → Plugins → Catalogue installs official and third-party plugins (subtitles, Trakt, OpenID, intro skipping…). Plugins survive upgrades.
- **Write a plugin:** the plugin API is in `MediaBrowser.Common/Plugins/`. The built-in metadata providers in `MediaBrowser.Providers/Plugins/` (TMDb, OMDb, MusicBrainz…) are good examples, and upstream keeps a plugin template repository.
- **REST API:** create a key in Dashboard → API Keys. Browse every endpoint at `/api-docs/swagger/index.html` on your server.

## Level 3: Code
Read Jellyfin's contributing guide and LLM policy on jellyfin.org first.

| Change | Where |
|---|---|
| Anything you see on screen in the browser | Separate repository: `jellyfin/jellyfin-web` |
| API endpoint | `Jellyfin.Api/Controllers/*Controller.cs` |
| Library scanning and server logic | `Emby.Server.Implementations/` (e.g. `Library/`, `ScheduledTasks/`) |
| Interfaces shared with plugins | `MediaBrowser.Controller/`, `MediaBrowser.Model/` |
| How file and folder names are understood | `Emby.Naming/` |
| Metadata providers | `MediaBrowser.Providers/` |
| Database | `src/Jellyfin.Database/` (Entity Framework Core) |
| Server text (notifications, library names) | `Emby.Server.Implementations/Localization/Core/en-US.json` |

## Running locally
- **Just use it:**
  1. `docker run -d -p 8096:8096 -p 7359:7359/udp -v jellyfin-config:/config -v jellyfin-cache:/cache --mount type=bind,source=/path/to/media,target=/media jellyfin/jellyfin`
  2. Open http://localhost:8096 and follow the setup wizard.
  - On Windows and macOS, the docs recommend the native installer rather than Docker.
- **Develop the server:**
  1. Install the .NET 10 SDK and jellyfin-ffmpeg.
  2. Get a built copy of jellyfin-web.
  3. Run `dotnet run --project Jellyfin.Server --webdir /absolute/path/to/jellyfin-web/dist` and open http://localhost:8096.
- **Develop the web client:** start the server with `--nowebclient` (or `JELLYFIN_NOWEBCONTENT=true`) and follow the jellyfin-web README. The setup wizard can't run when the web client is hosted separately.
- **Check:** `dotnet test Jellyfin.sln` and `dotnet format --verify-no-changes`.

## Pitfalls
- Most "make it look different" requests are web-client changes. Try custom CSS first, then `jellyfin-web`, not this server repository.
- Every client app depends on the API. Never change existing endpoints or response shapes.
- Back up `/config` before upgrades. Database migrations run on start and are one-way.
- Hardware transcoding in Docker only works on Linux hosts with the right device passed through.
- Upstream rejects pull requests that are mostly AI-written. Keep such changes in your own copy, or turn them into a plugin.

---
Machine-readable: [bespoke.yaml](https://handoff.bespokeai.software/p/jellyfin/c7ce6a1/bespoke.yaml) · Agent skill: [SKILL.md](https://handoff.bespokeai.software/p/jellyfin/c7ce6a1/SKILL.md)
