Self-hosted TV channel schedule manager for Plex and Tunarr.
Build, manage, and push programming schedules for your personal TV network — complete with an AI advisor, EPG generation, and a real-time schedule editor.
Features • Quick Start • Screenshots • Stack • API Docs • Contributing
Actively maintained — Linearr follows a monthly release cycle. See the Releases page for the latest version and changelogs.
Linearr does not provide, host, stream, or distribute any media content. It is a schedule management tool that organizes metadata (titles, thumbnails, time slots) from your own Plex Media Server. All media files remain on your server and are never copied, transcoded, or redistributed by Linearr. You are solely responsible for ensuring that the content on your Plex server complies with applicable copyright laws in your jurisdiction.
| Feature | Description | |
|---|---|---|
| Channels | Channel Manager | Manage your full lineup with tier, vibe, and genre metadata |
| Content | Plex Content Browser | Browse libraries, search, and assign movies/shows via a poster grid |
| Schedule | Schedule Blocks | Drag-and-drop time blocks — morning, primetime, late night |
| AI | AI Advisor | Content recommendations, network analysis, auto-generated schedules |
| Tunarr | Tunarr Integration | Link channels, sync collections, push schedules in one click |
| 24/7 | 24/7 Channel Builder | Analyze your library and generate standalone loop channels |
| Backup | Backup & Restore | One-click database download/upload from the Settings UI |
| PWA | Installable App | Mobile-first responsive layout, installable as a PWA |
| Logs | Unified Logging | App + AI operation logs with level filtering in Settings |
| API | REST API + Swagger | Full OpenAPI docs at /docs, health check at /api/health |
Requirements: Docker + Docker Compose, a running Plex Media Server, and optionally Tunarr.
mkdir linearr && cd linearrcurl -O https://raw.githubusercontent.com/isaiasgv/linearr/main/docker-compose.yml
curl -O https://raw.githubusercontent.com/isaiasgv/linearr/main/.env.exampleOr create docker-compose.yml manually:
services:
linearr:
image: ghcr.io/isaiasgv/linearr:latest
container_name: linearr
ports:
- "8777:8888"
volumes:
- ./data:/app/data
env_file:
- path: .env
required: false
networks:
- plex_default
restart: unless-stopped
networks:
plex_default:
external: truecp .env.example .envEdit .env and set at minimum:
APP_USERNAME=admin
APP_PASSWORD=your-secure-password
APP_SECRET=generate-a-random-string-here
PLEX_URL=http://plex:32400
PLEX_TOKEN=your-plex-tokenNote: Use
http://plex:32400if Linearr and Plex are on the same Docker network (plex_default). Otherwise use your Plex server's IP/hostname.
docker compose up -dNavigate to http://localhost:8777 and log in with the credentials from your .env.
Pull the latest image and recreate the container:
docker compose pull
docker compose up -dTo pin a specific version instead of latest:
image: ghcr.io/isaiasgv/linearr:0.0.2Environment variables
| Variable | Required | Description |
|---|---|---|
APP_USERNAME |
Yes | Login username |
APP_PASSWORD |
Yes | Login password |
APP_SECRET |
Yes | Random string for session signing |
PLEX_URL |
Yes | Plex server URL (http://plex:32400) |
PLEX_TOKEN |
Yes | Plex authentication token |
OPENAI_API_KEY |
No | For AI features (OpenAI-compatible) |
ANTHROPIC_API_KEY |
No | For AI features (Anthropic) |
TUNARR_URL |
No | Tunarr server URL (also configurable in UI) |
See .env.example for a full template.
Your Plex Library Linearr Tunarr
┌──────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ Movies │───>│ 1. Assign content│───>│ IPTV streams │
│ TV Shows │ │ 2. Build schedule│ │ EPG guide data │
│ Collections │ │ 3. Push to Tunarr│ │ M3U playlists │
└──────────────┘ └──────────────────┘ └─────────────────┘
│
┌──────┴──────┐
│ AI Advisor │
│ suggestions │
└─────────────┘
- Assign content — Browse your Plex libraries and assign movies, shows, and collections to channels
- Build your schedule — Create time blocks (Morning, Primetime, Late Night) and fill slots with content. Use AI to auto-generate a full day
- Push to Tunarr — Link channels and push the schedule. Tunarr handles the IPTV stream and EPG
| Layer | Technology |
|---|---|
| Frontend | React 18, Vite, TypeScript |
| State | Zustand (UI) + TanStack React Query (server) |
| Styling | Tailwind CSS v3 |
| Backend | Python 3.12, FastAPI, uvicorn |
| Database | SQLite (persisted via Docker volume) |
| Linting | ESLint 9, Prettier |
| CI/CD | GitHub Actions (lint, typecheck, build, Docker publish) |
| Container | Multi-stage Docker (Node 20 + Python 3.12) |
The frontend uses a vertical slice architecture — code organized by feature domain (channels/, blocks/, tunarr/, ai/, etc.) rather than technical layer.
# Set up git hooks (conventional commits enforced)
cd frontend && npm run setup
# Terminal 1 — backend
pip install -r requirements.txt
uvicorn main:app --reload --port 8888
# Terminal 2 — frontend (hot reload, proxies /api → :8888)
cd frontend
npm install
npm run dev
# → http://localhost:5173| Script | Description |
|---|---|
npm run dev |
Vite dev server |
npm run build |
Type-check + production build |
npm run lint |
ESLint |
npm run format |
Prettier |
npm run typecheck |
TypeScript type checking |
npm run release |
Bump version + generate CHANGELOG |
npm run setup |
Configure git hooks |
To build and run the Docker image from source instead of pulling from GHCR:
docker compose -f docker-compose.yml -f docker-compose.dev.yml up --build -dFastAPI auto-generates interactive docs:
- Swagger UI:
http://localhost:8777/docs - OpenAPI JSON:
http://localhost:8777/openapi.json
Key endpoints
| Endpoint | Description |
|---|---|
GET /api/health |
Health check (no auth) |
GET /api/channels |
List all channels |
GET /api/assignments |
All content assignments |
GET /api/backup |
Download SQLite database |
POST /api/restore |
Upload database to restore |
GET /api/plex/thumb?path= |
Proxy Plex thumbnail |
GET /api/ai-logs |
AI operation logs |
GET /api/app-logs |
Application logs |
docker compose up -d
docker compose logs -f linearrThe container includes a HEALTHCHECK on /api/health. Persistent data lives in ./data/.
To build locally from source instead of pulling from GHCR:
git clone https://github.com/isaiasgv/linearr.git
cd linearr
docker compose up --build -dLinearr listens on port 8888 internally, mapped to 8777 on the host.
Nginx Proxy Manager
Point to your Docker host IP, port 8777. Enable WebSocket support if available.
Cloudflare
- Proxy to port 8777 (host port), not 8888
- After deployments, purge cache: Caching → Purge Everything
- SSL mode: Full or Full (strict)
Traefik
labels:
- "traefik.enable=true"
- "traefik.http.routers.linearr.rule=Host(`channels.yourdomain.com`)"
- "traefik.http.services.linearr.loadbalancer.server.port=8888"Download or restore from Settings → System in the UI, or via CLI:
# Backup
curl -b "session=TOKEN" http://localhost:8777/api/backup -o linearr-backup.db
# Restore
curl -X POST -b "session=TOKEN" --data-binary @linearr-backup.db http://localhost:8777/api/restoreLinearr follows a monthly release cycle:
- Stable releases land on
mainat the start of each month - Release candidates (
0.x.y-rc.N) are published fromrelease/*branches for testing - Docker tags:
latestalways points to the most recent stable release;rcpoints to the latest candidate
To test a release candidate before it goes stable:
image: ghcr.io/isaiasgv/linearr:rcSee CONTRIBUTING.md for development setup, code style, and PR guidelines.
We use Conventional Commits — enforced by git hooks.
Linearr is a schedule management and metadata organization tool. It does not:
- Provide, host, stream, or distribute any media content
- Include or bundle any copyrighted material
- Bypass any DRM or copy protection
- Function as a media server or streaming service
Linearr reads metadata (titles, thumbnails, durations) from your Plex Media Server to build programming schedules. All media files remain on your own server and are accessed exclusively through your existing Plex and Tunarr installations.
You are solely responsible for ensuring that the content on your Plex server is legally obtained and that your use complies with all applicable laws in your jurisdiction.
GPL-3.0 — free and open source, same as the rest of the *arr stack.
Built with Plex, Tunarr, React, FastAPI, and a love for television.