A local-first Plex + Seerr companion for finding what to watch.
Moodarr reads your Plex library and Seerr/Jellyseerr request state, ranks natural-language matches, and only creates requests after explicit confirmation.
MoodRank turns fuzzy mood and feel language into an indexed recommendation layer for the arr stack: hybrid retrieval, deterministic scoring, feedback learning, and optional constrained AI reranking over your real Plex and Seerr catalog.
Public alpha: Moodarr is early software for inspection and trial use. APIs, configuration, packaging, recommendation behavior, and admin flows may change before beta.
- React + Vite client.
- Fastify TypeScript API.
- Local SQLite cache.
- Persistent server-side config for container installs.
- Admin screen for connection settings, sync controls, and runtime status.
- Optional Plex sign-in for non-admin Finder access and local user visibility.
- Fixture mode for contributors without Plex or Seerr.
- Plex read APIs only.
- Seerr/Jellyseerr read APIs plus explicit confirmed request creation.
- Optional server-side OpenAI brief parsing, embeddings, reranking, explanations, and refinement options when
OPENAI_API_KEYexists.
Moodarr is in public alpha. The core fixture-mode, Plex/Seerr sync, natural-language discovery, admin settings, request preview, request creation, Docker, and Unraid packaging paths exist.
Known limitations:
- Setup and configuration are still changing.
- The project is designed for LAN/VPN or trusted container-network deployment, not direct public internet exposure.
- Plex app deep links use Plex metadata keys and may still need compatibility checks across Plex clients.
- There is no GitHub release object yet; immutable alpha tags and GHCR images are available.
Prerequisites: Node.js 24 or newer.
node --version # requires Node 24+
npm install
cp .env.example .env
npm run devOpen the Vite URL printed by the dev server. Fixture mode is enabled by default, so the app works without private media servers.
docker pull ghcr.io/jremick/moodarr:v0.1.0-alpha.11
docker run --rm -p 4401:4401 \
-v moodarr-data:/data \
-e MOODARR_ADMIN_TOKEN="replace-with-a-long-random-token" \
-e MOODARR_ADMIN_AUTO_SESSION=true \
ghcr.io/jremick/moodarr:v0.1.0-alpha.11Open http://127.0.0.1:4401, then configure Plex and Seerr. The bundled Web UI receives an HTTP-only admin session from the container-side admin token. See docs/UNRAID.md for Unraid notes and the template in unraid/moodarr.xml.
Moodarr is intended to run as a container where it can reach your Plex and Seerr/Jellyseerr services. For most home media setups, that means running it on the same LAN, VPN, or trusted container network rather than exposing media-server APIs to a public host.
Set these values in .env for real integrations:
MOODARR_ADMIN_TOKENPLEX_BASE_URLPLEX_TOKENSEERR_BASE_URLSEERR_API_KEYMOODARR_PLEX_AUTH_ENABLED=trueto let Plex users access Finder routes without the admin token.MOODARR_PLEX_AUTH_ALLOW_NEW_USERS=trueto create local users on first Plex sign-in when the account has access to the configured server.AI_PROVIDER=openaiOPENAI_API_KEYOPENAI_MODELdefaults togpt-5.5OPENAI_EMBEDDING_MODELdefaults totext-embedding-3-largeOPENAI_REASONING_EFFORTdefaults tolowforgpt-5.5
Tokens are read by the backend only. They are not returned by API routes, embedded in the client bundle, placed in poster URLs, or logged without redaction.
Optional Plex Watchlist actions store the signed-in user's Plex access token server-side so Moodarr can call Plex Discover on that user's behalf. That token stays in the private SQLite database and is not returned to clients.
Container installs can also save integration settings through the Admin screen. They are written to MOODARR_CONFIG_PATH, which defaults to /data/config.json in the Docker image. Environment variables still take precedence on restart.
When admin auth is enabled, private catalog reads, search, poster proxying, request previews, and request creation require either the admin token/session or a Plex user session when Plex sign-in is enabled. Admin writes, diagnostics, sync controls, and user management still require the admin token/session. Keep Moodarr LAN/VPN-only unless another authentication layer protects it.
Native clients can request a user-session token during Plex auth completion by sending nativeSession: true to POST /api/auth/plex/complete. The response includes a non-admin sessionToken and sessionExpiresAt; native clients should store that token in the platform secure store and send it as Authorization: Bearer <sessionToken> for Finder routes. That token does not grant admin access.
Search responses include sessionId when recommendation-run logging succeeds. Native clients should include that id on POST /api/feel-feedback so swipes and pairwise choices attach to the displayed slate. Mobile retry queues should also send a unique clientEventId; duplicate retries return the original feedback event instead of applying learning twice.
GET /api/healthGET /api/config/statusGET /api/auth/sessionPOST /api/auth/plex/startPOST /api/auth/plex/completePOST /api/auth/logoutPOST /api/plex/testPOST /api/plex/watchlistPOST /api/seerr/testPOST /api/library/syncPOST /api/seerr/syncGET /api/library/statsPOST /api/searchGET /api/items/:idGET /api/items/:id/posterPOST /api/requests/previewPOST /api/requests/createGET /api/admin/settingsPUT /api/admin/settingsGET /api/admin/usersPATCH /api/admin/users/:idGET /api/admin/sync/statusPOST /api/admin/sync/runGET /api/admin/recommendations/diagnosticsGET /api/admin/feel-profilesGET /api/admin/feel-profiles/exportDELETE /api/admin/feel-profilesPOST /api/admin/feel-profiles/rollbackGET /api/admin/support-bundle
npm run verifyThe verification suite runs linting, typechecking, API tests, a production client build, and a secret scan against generated client assets.
For release packaging work, run:
npm run verify:releaseThat adds recommendation evals, Compose/Unraid packaging checks, and a Docker smoke test.
Mood/Feel algorithm work also has focused evals:
npm run eval:recommendations
npm run eval:profile-replay
npm run eval:profile-journeysOptional local-only external seed validation, when you have an ignored MovieLens dataset directory:
npm run validate:movielens-tag-genome -- --dir /path/to/ml-25m --threshold 0.7- Release readiness - local and CI gates for alpha packaging.
- Unraid deployment - container defaults and Unraid template notes.
- Production plan - current baseline and hardening backlog.
- Recommendation engine - ranking and retrieval behavior.
- MoodRank current algorithms - living map of stages, feedback, and eval metrics.
- Mood/Feel profile goal - public research-backed product direction.
- Mood/Feel robustness V2 - synthetic journey, drift, rollback, and external seed hardening.
- Mood/Feel controlled usage - first real-signal readiness loop before mobile collection.
- Mood feature index - local mood taxonomy and feature mapping.
- Seerr auth alignment - Plex user-management alignment notes.
- Issues - bugs and concrete feature requests.
- Contributing - local development, verification, and safety expectations.
- Security policy - private vulnerability reporting and deployment boundaries.
POST /api/requests/preview returns the exact media type, TMDB media ID, title, and TV seasons that would be requested. POST /api/requests/create requires both confirmed: true and the preview confirmation phrase. Search and AI output cannot create a request directly.
Fixture mode seeds a small mixed Plex and Seerr catalog with available, requestable, already requested, and partially available examples. It is intended for local development and CI without private server access.
Moodarr is licensed under the Apache License 2.0.


