An agent-optimized CLI tool for interacting with the Jellyfin API.
Package Manager: Development uses Bun. Published package execution supports both
bunxandnpx.
- Node.js 22.13 or newer for installed/npm execution
- Bun 1.3.11 or newer for source builds and contributor workflows
# Install Bun if you haven't already
curl -fsSL https://bun.sh/install | bash
# Install the CLI globally
bun install -g jellyfin-cli
# Run directly with bunx (no install)
bunx jellyfin-cli --help
# Run directly with npx (no install)
npx jellyfin-cli --help
# Or clone and build from source
git clone https://github.com/unbraind/jellyfin-cli.git
cd jellyfin-cli
bun install
bun run buildInstalled executable names: jf, jellyfin-cli, and jf-cli.
# Quick setup with server URL and API key
jf setup --server http://your-server:8096 --api-key YOUR_API_KEY
# Or use username/password authentication
JELLYFIN_USERNAME=your-user JELLYFIN_PASSWORD='your-password' jf users me
# Test connection
jf config test
# Run diagnostics (connectivity/auth/OpenAPI checks)
jf config doctor
# Enforce non-destructive mode for all following commands
JELLYFIN_READ_ONLY=1
# List libraries
jf library list
# Search for content
jf items search "matrix"
# Control playback
jf sessions list
jf sessions play SESSION_ID ITEM_ID- Broad Jellyfin API Coverage: Major endpoint families are implemented; use
jf schema researchand the operation-ID coverage roadmap for exact-version gap analysis - Agent-Optimized: Designed for LLM/AI agent integration with structured output
- Official TOON Format: Default output uses
@toon-format/toonfor compact, lossless agent data - Multiple Output Formats: Toon, JSON, table, raw, YAML, and Markdown
- Secure: Credentials stored in user config directory, never committed
- Type-Safe: Full TypeScript implementation
- Bun-Powered: Fast package management and builds with Bun
- Setup Wizard: Interactive configuration wizard
- Startup Diagnostics:
jf setup startupreports startup wizard state in structured output - Startup Wizard Configuration:
jf setup update-configurationupdates/Startup/Configuration - Diagnostics:
jf config doctorfor agent-safe health checks - Read-Only Guard: global
--read-onlyorJELLYFIN_READ_ONLY=1blocks mutating commands and known state-changing pluginGETcontracts - Bounded API Batches: preflight and execute ordered read-only operation manifests in one process
- Real-Time Events: bounded WebSocket watches with filters, read subscriptions, TOON aggregates, and opt-in NDJSON streaming
- Explain Mode: global
--explainorJELLYFIN_EXPLAIN=1prints redacted request metadata tostderr - Release Guardrails: built-in file length + secret scanning checks for safe releases
- Plugin Management: List, configure, and manage plugins
- Device Management: View and manage connected devices
- Statistics: View library statistics and item counts
- Collections: Manage box sets and collections
- Favorites: Quick access to favorite items
- Streaming URLs: Get direct URLs for video, audio, and subtitles
| Variable | Description |
|---|---|
JELLYFIN_SERVER_URL |
Server URL |
JELLYFIN_API_KEY |
API key |
JELLYFIN_USERNAME |
Username for authentication |
JELLYFIN_PASSWORD |
Password for authentication |
JELLYFIN_USER_ID |
User ID |
JELLYFIN_TIMEOUT |
Request timeout (ms) |
JELLYFIN_OUTPUT_FORMAT |
Output format (toon, json, table, raw, yaml, markdown) |
JELLYFIN_READ_ONLY |
1/true/on/yes blocks mutating commands globally |
JELLYFIN_EXPLAIN |
1/true/on/yes emits redacted request metadata to stderr |
Short aliases are also supported:
JF_SERVER_URLJF_API_KEYJF_USERJF_PASSWORDJF_USER_IDJF_TIMEOUTJF_FORMAT
Settings are stored in ~/.jellyfin-cli/settings.json.
# View current configuration
jf config get
# Show config file path
jf config path
# List all configured servers
jf config list
# Set configuration
jf config set --server URL --api-key KEYThe CLI supports multiple output formats optimized for different use cases:
The default format is encoded by the official
@toon-format/toon implementation:
type: items
data[2]{id,name,type,year,rating}:
abc123,The Matrix,Movie,1999,8.7
def456,The Matrix Reloaded,Movie,2003,7.2
TOON and YAML are separate output formats. TOON uses explicit array lengths and tabular field headers and should be decoded with the official TOON decoder.
Standard JSON output for programmatic processing:
jf items list --format jsonHuman-readable table format:
jf users list --format tableRaw output without formatting:
jf system info --format rawjf setup- Interactive setup wizardjf setup wizard- Explicit alias for setup wizard workflowsjf setup status- Check setup statusjf setup validate- Validate setup readiness (config/connectivity/auth/OpenAPI/output-format checks)jf setup env- Show/export environment variables (--shell, structured--format json, or--write-file <path>)jf setup startup- Inspect Jellyfin startup wizard state (read-only)jf setup configuration- Alias ofsetup startupfor endpoint-aligned diagnosticsjf setup update-configuration- Update startup wizard configuration valuesjf config set- Set configuration valuesjf config get- Display current configurationjf config path- Show configuration file pathjf config list- List all configured serversjf config use <name> [--format <format>]- Switch to a named server configurationjf config delete <name> --force [--format <format>]- Delete a server configurationjf config reset --force [--format <format>]- Reset all configurationjf config test- Test connection to serverjf config doctor- Check config/auth/connectivity/OpenAPI diagnosticsjf setup validate --require-all --validate-formats --format json- Setup wizard readiness gate for CI/agentsjf config doctor --require-connected --require-auth --require-openapi --require-valid-formats --validate-formats- Enforce machine-checkable release gatesjf schema openapi- Summarize live server OpenAPI capabilities for agent discoveryjf schema research- Emit consolidated OpenAPI + full/read-only coverage snapshot for API researchjf schema versions- Discover and validate the current official stable and preview API contractsjf schema tools- Export command tool schemas for LLM function-calling, with optional live OpenAPI endpoint matchesjf schema coverage- Estimate API coverage, list unmatched OpenAPI operations, and suggest command namesjf schema suggest- Generate candidate CLI command patterns from OpenAPI intent matches or coverage gapsjf schema compatibility- Compare exact or current official API versions, or audit live/plugin driftjf api inspect <operationId>- Inspect typed inputs, bodies, responses, security, and an argv templatejf api get <operationId>- Execute a semantically read-only OpenAPI operationjf api batch --file <manifest.json>- Preflight and execute a bounded read-only operation batchjf api mutate <operationId> --confirm- Execute a validated mutation (blocked by--read-only)jf events types- List the Jellyfin 10.11 WebSocket event and subscription catalogjf events watch --count 10 --duration 30- Collect a bounded real-time event windowjf events watch --stream --format json- Emit one NDJSON event per line plus a summary
bun run validate:releaseThis enforces the version and generated-changelog policies, then runs typecheck, lint, tests, build, dist smoke checks, TypeScript code-length enforcement (<=300 lines excluding comments), tracked-file and history secret scans, npm packaging, and exact local npx/Bun smoke runs.
GitHub Actions workflows are configured for professional release management:
CI(.github/workflows/ci.yml): PR/push quality gatesCodeQL(.github/workflows/codeql.yml): static security analysisSecret Scan(.github/workflows/secret-scan.yml): tracked-file + git-history + Gitleaks checksCommit Quality(.github/workflows/commit-quality.yml): PR title + commit subject professionalism checksAuto Release(.github/workflows/auto-release.yml): scheduled/manual change detection, pm-generated changelog, release gates, and atomic release commit/tagRelease(.github/workflows/release.yml): tag-driven npm provenance publish, exact npm/npx/Bun verification, artifacts, and GitHub Release
See Automated Releases for setup, changelog ownership, secrets, dry runs, registry semantics, and recovery.
Contributor and governance standards:
- Version format is mandatory:
YYYY.M.DorYYYY.M.D-<N> - Example (first release of day):
2026.3.4 - Example (third release on same day):
2026.3.4-3 - Date uses UTC day
Nis the release index for that UTC day-1is not allowed (useYYYY.M.Dwithout suffix)- Auto Release selects the next registry-safe version; use
bun run version:nextto preview it
Use read-only mode for safe agent workflows against production libraries:
# one command
jf --read-only items list --limit 5
# entire shell session
export JELLYFIN_READ_ONLY=1
jf library list
# inspect API request mapping for a command
jf --explain system infoMutating operations are blocked with a structured Toon error while read operations continue to work.
jf system info- Get system informationjf system health- Check server healthjf system restart- Restart the serverjf system shutdown- Shutdown the serverjf system activity- Get activity log
jf users list- List all usersjf users get <userId>- Get user by IDjf users me- Get current user infojf users by-name <username>- Get user by usernamejf users create <username>- Create a new userjf users update-password <userId>- Update user passwordjf users delete <userId> --force- Delete a userjf users policy <userId>- Get user policyjf users update-policy <userId>- Update user policy (admin rights, permissions)jf users config <userId>- Get user configurationjf users update-config <userId>- Update user configuration (preferences)
jf items list- List itemsjf items get <itemId>- Get item by IDjf items collections <itemId>- List collections containing an item (Jellyfin 12+)jf items latest- Get latest itemsjf items resume- Get resume itemsjf items search <term>- Search for itemsjf items similar <itemId>- Get similar itemsjf items intros <itemId>- Get intro videosjf items chapters <itemId>- Get chaptersjf items special-features <itemId>- Get special featuresjf items trailers <itemId>- Get local trailersjf items ancestors <itemId>- Get parent itemsjf items parts <itemId>- Get additional partsjf items playback-info <itemId>- Get playback infojf items stream-url <itemId>- Get video stream URLjf items audio-url <itemId>- Get audio stream URLjf items image-url <itemId>- Get image URLjf items subtitle-url <itemId> <mediaSourceId> <streamIndex>- Get subtitle URLjf items refresh <itemId>- Refresh item metadatajf items update <itemId>- Update item metadata (name, overview, genres, etc.)jf items delete <itemId>- Delete an item
jf sessions list- List active sessions with explicit playback state and current item detailsjf sessions get <sessionId>- Get session by IDjf sessions play <sessionId> <itemIds...>- Play itemsjf sessions pause <sessionId>- Pause playbackjf sessions unpause <sessionId>- Resume playbackjf sessions stop <sessionId>- Stop playbackjf sessions next <sessionId>- Next trackjf sessions previous <sessionId>- Previous trackjf sessions seek <sessionId> <ticks>- Seek to positionjf sessions mute <sessionId>- Mute audiojf sessions unmute <sessionId>- Unmute audiojf sessions volume <sessionId> <level>- Set volume leveljf sessions message <sessionId>- Send message
jf library list- List all librariesjf library refresh- Refresh all librariesjf library genres- List all genresjf library studios- List all studiosjf library persons- List all personsjf library artists- List all artistsjf library album-artists- List all album artistsjf library get-genre <name>- Get a genre by namejf library get-person <name>- Get a person by namejf library get-studio <name>- Get a studio by name
jf userdata favorite <itemId>- Mark as favoritejf userdata unfavorite <itemId>- Remove from favoritesjf userdata played <itemId>- Mark as playedjf userdata unplayed <itemId>- Mark as unplayedjf userdata like <itemId>- Like an itemjf userdata dislike <itemId>- Dislike an itemjf userdata unrate <itemId>- Remove rating
jf favorites list- List favorite itemsjf favorites add <itemId>- Add to favoritesjf favorites remove <itemId>- Remove from favorites
jf collections list- List all collectionsjf collections get <collectionId>- Get collection detailsjf collections items <collectionId>- List items in collectionjf collections create <name>- Create a new collectionjf collections add <collectionId> <itemIds...>- Add items to collectionjf collections remove <collectionId> <itemIds...>- Remove items from collection
jf tasks list- List all scheduled tasksjf tasks get <taskId>- Get task by IDjf tasks run <taskId>- Start a taskjf tasks running <taskId>- Alias oftasks runjf tasks stop <taskId>- Stop a running taskjf tasks triggers <taskId>- List task triggersjf tasks add-trigger <taskId>- Add a task triggerjf tasks delete-trigger <taskId> <triggerId>- Delete a task trigger
jf playlists create <name>- Create a playlistjf playlists add <playlistId> <itemIds...> [--position <index>]- Add or position itemsjf playlists remove <playlistId> <entryIds...>- Remove itemsjf playlists items <playlistId>- List playlist itemsjf playlists delete <playlistId>- Delete a playlist
jf livetv info- Get Live TV infojf livetv channels- List channelsjf livetv channel <channelId>- Get channel by IDjf livetv programs- List programsjf livetv program <programId>- Get program by IDjf livetv recordings- List recordingsjf livetv timers- List timersjf livetv timer <timerId>- Get timer by IDjf livetv create-timer- Create a timerjf livetv delete-timer <timerId>- Delete a timerjf livetv series-timers- List series timersjf livetv series-timer <id>- Get series timer by IDjf livetv delete-series-timer <id>- Delete a series timerjf livetv schedules-direct-countries- List Schedules Direct countries
jf discover recommendations- Get recommendationsjf discover mix <itemId>- Get instant mix
jf plugins list- List all pluginsjf plugins get <pluginId>- Get plugin detailsjf plugins config <pluginId>- Get plugin configurationjf plugins uninstall <pluginId>- Uninstall a plugin
jf devices list- List all devicesjf devices info- Get current device infojf devices get <deviceId>- Get device detailsjf devices rename <deviceId> <name>- Rename devicejf devices delete <deviceId>- Delete device
jf branding get- Get branding configuration
jf stats counts- Get library item counts
jf apikeys list- List all API keysjf apikeys create <app>- Create new API keyjf apikeys delete <key>- Delete API key
jf notifications types- List optional notification types or report structured unavailabilityjf notifications list- List user notifications when the optional route is installedjf notifications send- Send an admin notification when the optional route is installed
Jellyfin 10.11.11 does not expose notification routes in its core OpenAPI document. These commands are retained as an optional compatibility surface and support all global output formats.
jf syncplay list- List SyncPlay groupsjf syncplay groups- Alias ofsyncplay listjf syncplay create [--name <name>]- Create a groupjf syncplay new [--name <name>]- Alias ofsyncplay createjf syncplay join <groupId>- Join a groupjf syncplay leave- Leave groupjf syncplay pause- Pause group playbackjf syncplay unpause- Resume group playbackjf syncplay stop- Stop group playback
jf quickconnect status- Check if Quick Connect is enabledjf quickconnect init- Initialize Quick Connectjf quickconnect check <secret>- Check connection statusjf quickconnect authorize <code>- Authorize request
jf auth providers- List authentication providersjf auth password-reset-providers- List password reset providersjf auth keys- List API keys (read-only alias)
jf backup list- List backupsjf backup create- Create a backupjf backup restore <path>- Restore from backupjf backup delete <path>- Delete backup
jf subtitles search <itemId> <language>- Search remote subtitlesjf subtitles download <itemId> <subtitleId>- Download subtitlejf subtitles delete <itemId> <index>- Delete subtitle trackjf subtitles providers- List subtitle providers
jf media segments <itemId>- Get media segmentsjf media lyrics <itemId>- Get lyricsjf media theme-songs <itemId>- Get theme songsjf media theme-videos <itemId>- Get theme videosjf media external-ids <itemId>- Get external IDsjf media external-id-infos <itemId>- Alias for external IDsjf media remote-images <itemId>- Get remote imagesjf media download-image <itemId>- Download remote imagejf media hls-url <itemId>- Get HLS playlist URLjf media video-stream-url <itemId>- Get direct video stream URLjf media audio-stream-url <itemId>- Get direct audio stream/universal URLjf media hls-legacy-url <itemId> <playlistId>- Get legacy HLS playlist URLjf media hls-audio-segment-url <itemId> <segmentId>- Get legacy HLS audio segment URLjf media item-file-url <itemId>- Get direct item file URLjf media kodi-strm-url <type> <id>- Get Kodi.strmURLjf media branding-css-url- Get static branding CSS URL
jf dashboard pages [--main-menu true|false]- List dashboard configuration pagesjf dashboard page <name>- Get dashboard configuration page source
jf localization options- Get localization optionsjf localization countries- Get countriesjf localization cultures- Get cultures/languagesjf localization ratings- Get rating systems
jf environment drives- Get available drivesjf environment logs- Get log filesjf environment log <name>- Get log file contentjf environment storage- Get storage info
jf tvshows episodes <seriesId>- Get episodes for a seriesjf tvshows seasons <seriesId>- Get seasons for a seriesjf tvshows next-up- Get next up episodesjf tvshows upcoming- Get upcoming episodesjf tvshows similar <itemId>- Get similar shows for a series/episode
jf packages list- List available packagesjf packages get <packageId>- Get package detailsjf packages install <packageId>- Install a packagejf packages cancel <installationId>- Cancel installationjf packages installing- List installing packagesjf packages repositories- List plugin repositories
jf images list <itemId>- List item imagesjf images url <itemId> <type>- Get image URLjf images artist-url <artistName> <type>- Get artist image URL by namejf images genre-url <genreName> <type>- Get genre image URL by namejf images music-genre-url <genreName> <type>- Get music genre image URL by namejf images person-url <personName> <type>- Get person image URL by namejf images studio-url <studioName> <type>- Get studio image URL by namejf images delete <itemId> <type>- Delete imagejf images user <userId>- Get user profile image URL
jf suggestions get- Get content suggestions
jf years list- List all yearsjf years get <year>- Get items for a year
jf music-genres list- List all music genresjf music-genres get <name>- Get music genre by name
jf trickplay hls-url <itemId> <width>- Get trickplay HLS playlist URLjf trickplay tile-url <itemId> <width> <index>- Get trickplay tile image URL
jf channels list- List all channelsjf channels features [channelId]- Get channel featuresjf channels items <channelId>- Get channel itemsjf channels latest <channelId>- Get latest channel items
jf schema- Output JSON schema for all Toon format typesjf schema <type>- Output JSON schema for a specific typejf schema list- List all available output typesjf schema validate [type] [--from auto|json|yaml|toon] [--input <payload>]- Validate output payloads against CLI schemas (stdin or inline)jf schema openapi [--include-paths --limit 50] [--method GET] [--tag Users] [--path-prefix /Users] [--search text] [--read-only-ops] [--endpoint /api-docs/openapi.json] [--for-command "items list"]- Fetch/summarize/filter OpenAPI and infer likely endpoints for a CLI intentjf schema research [--method GET] [--tag Users] [--path-prefix /Users] [--endpoint /api-docs/openapi.json] [--command-prefix items] [--min-score 3] [--require-coverage 100] [--include-unmatched] [--limit 20]- Generate one consolidated OpenAPI + full/read-only coverage snapshotjf schema versions [--name <server>]- Discover current official releases, validate their OpenAPI artifacts, compare the public server version, and emit compatibility argvjf schema tools [--command <prefix> --limit <n> --openapi-match --name <server>]- Export tool schemas with input schema, read-only metadata, and optional live OpenAPI endpoint matches per commandjf schema coverage [--method GET] [--tag Users] [--path-prefix /Users] [--read-only-ops] [--endpoint /api-docs/openapi.json] [--command-prefix items] [--min-score 3] [--require-coverage 100] [--suggest-commands] [--limit 50]- Estimate intent-based OpenAPI coverage for current CLI command set and optionally generate candidate CLI names for unmapped endpointsjf schema suggest [--for-command "users list"] [--method GET] [--tag Users] [--path-prefix /Users] [--search text] [--read-only-ops] [--endpoint /api-docs/openapi.json] [--min-score 3] [--limit 20]- Generate structured CLI command suggestions from live OpenAPI (intent mode with--for-command, or uncovered operation mode without it)jf schema compatibility [--baseline official|live] [--target-version <exact|latest-stable|latest-preview> --allow-prerelease] [--fail-on-breaking] [--limit 50]- Classify deterministic operation, parameter, body, response, and component-schema drift between trusted API contracts
Official-to-official comparison is the default, using the configured server's API version as the
baseline and target. This avoids misclassifying plugin endpoints as core Jellyfin removals. Use
--baseline live to audit server/plugin drift explicitly. Alpha, beta, and RC artifacts require
--allow-prerelease; use latest-preview to avoid hard-coding a stale release candidate. Artifact
identity is reported separately from the document API version.
--fail-on-breaking emits the complete structured report before returning a nonzero status.
Typed commands remain the preferred interface. The api fallback gives agents deterministic access
to every operation ID exposed by the configured Jellyfin server:
# Discover the operation and its exact path/query/body contract
jf api inspect GetUserById
# Execute a read-only operation; undeclared or missing parameters are rejected
jf api get GetUserById --path-param userId=USER_ID
# Repeated query values are preserved
jf api get GetItems --query userId=USER_ID --query genres=Drama --query genres=Comedy
# Preflight an entire read plan without executing any API operations
jf api batch --file reads.json --dry-run
# Execute the same plan with per-response and aggregate byte ceilings
jf api batch --file reads.json --max-bytes 1048576 --max-total-bytes 10485760
# Mutations require both the mutation-specific command and explicit confirmation
jf api mutate UpdateDeviceOptions --path-param deviceId=DEVICE_ID \
--body-json '{"CustomName":"Living room"}' --confirmJELLYFIN_READ_ONLY=1 or --read-only blocks api mutate before network execution. Request bodies
support JSON (--body-json), text (--body-text), and file-backed binary/text payloads
(--body-file plus --content-type). Response buffering is bounded by --max-bytes; binary
responses use base64 so TOON/JSON/YAML/Markdown/table output stays structurally valid. Exact
operation IDs come from the configured server OpenAPI document, with the existing exact-version
official fallback when a local schema is unavailable.
api inspect is side-effect free and returns a bounded invocation contract: merged path- and
operation-level parameters with types, formats, descriptions, enums, defaults, examples, and
constraints; request-body schemas by content type; response status/content-type summaries; security
alternatives; and a deterministic argv_template. Placeholders are never populated from live data.
Batch manifests are strict JSON objects with version: 1 and a non-empty requests array:
{
"version": 1,
"requests": [
{
"id": "server",
"operation_id": "GetPublicSystemInfo"
},
{
"id": "user",
"operation_id": "GetUserById",
"path_params": { "userId": "USER_ID" }
}
]
}Every request is resolved and validated before the first target-operation request. Batch execution accepts
only semantically read-only operations, preserves manifest order and caller IDs, reuses one authenticated
client, returns structured per-request failures, and exits nonzero if any request fails. Use
--stdin for pipelines; exactly one of --file or --stdin is required. Manifests are limited to
25 requests by default (configurable up to 100) and one MiB of input.
This CLI is designed to be easily used by AI agents and LLMs:
- Structured Output: The default
toonformat provides compact, lossless official TOON output - Type Information: Every output includes a
typefield indicating the data structure - Stable Envelope: Output always includes a top-level
typeand structureddata - Error Handling: Errors are returned in a consistent format
- No Interactive Prompts: All inputs are via command-line arguments
import { decode } from '@toon-format/toon';
// Execute command and parse output
const result = await exec('jf items search "matrix" --format toon');
const data = decode(result);
if (data.type === 'search_result') {
for (const hint of data.data.hints) {
console.log(`${hint.name} (${hint.type})`);
}
}import json
import subprocess
def get_items(search_term):
result = subprocess.run(
['jf', 'items', 'search', search_term, '--format', 'json'],
capture_output=True,
check=True,
text=True,
)
data = json.loads(result.stdout)
return data.get('SearchHints', [])This project uses Bun for package management, testing, and building.
# Install dependencies
bun install
# Build
bun run build
# Run in development mode
bun run dev
# Run tests
bun test
# Run tests with coverage
bun run test:coverage
# Type check
bun run typecheck
# Lint
bun run lint- API Reference - Full command documentation
- Toon Output Format - Output format specification
MIT