npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@emby-utils/cli

v0.2.0

Published

Semantic command-line interface for the Emby REST API.

Readme

@emby-utils/cli

Semantic command-line interface for the Emby REST API. Built on commander on top of @emby-utils/client.

Install

Install globally from npm:

npm install -g @emby-utils/cli

The binary is named emby. Run emby --help to confirm the install:

emby --version
emby --help

Or, without a global install, run ad-hoc via npx:

npx -p @emby-utils/cli emby --help

From source

For local development or to try an unreleased build:

git clone https://github.com/vromero/emby-utils-cli.git
cd emby-utils-cli
npm install
npm run build
node dist/bin.js --help

npm install runs the prepare script which builds dist/ automatically.

Configure

Set credentials via env vars or flags:

export EMBY_HOST=http://emby.local:8096
export EMBY_API_KEY=your-api-key

A local .env file in the working directory is auto-loaded if present. Set EMBY_ENV_FILE=/custom/path/.env to point elsewhere.

Usage

emby --help

# System
emby system info
emby system public-info
emby system ping

# Users
emby users list
emby users get <userId>

# Items
emby items list --user-id <id> --limit 20
emby items search "matrix"
emby items get <itemId> --user-id <userId>

# Sessions / libraries / plugins
emby sessions list
emby libraries list
emby plugins list
emby plugins install Trakt --plugin-version 1.2.3 --update-class Beta
emby plugins uninstall Trakt

# Emby Premiere (supporter) key
emby premiere status
emby premiere set MB-XXXX-XXXX-XXXX

# Login (prints an access token)
export EMBY_API_KEY=$(emby login --username alice --password ...)

Initialize a fresh Emby server

emby init walks a just-installed Emby through its first-run wizard and adds the libraries you specify. It reads its inputs from a JSON config file (via --config) rather than per-flag options so that the full desired state of your server lives in one reviewable artefact.

Idempotency

Re-running emby init against an already-initialized server is safe:

  • The first-run wizard is skipped (detected via /Startup/Configuration returning 401 to unauthenticated requests).
  • Libraries already present with a matching name, path, and collection type are left untouched and reported under librariesSkipped.
  • Only libraries missing from Emby are created.

If the wizard was completed earlier but the admin password in your config does not match what was set then, init fails fast with InitAuthMismatchError (HTTP 401 on the login step) rather than silently half-applying state.

If a library in your config shares its name with an existing library but has a different path or collection type, init refuses to reconcile automatically and raises InitLibraryDriftError before any mutation. Rename the library in your config or delete the drifted one in Emby's UI, then rerun. Updating paths or collection types of existing libraries is out of scope for init.

emby init --host http://emby.local:8096 --config ./emby.init.json

Example emby.init.json:

{
  "adminUsername": "admin",
  "adminPassword": "${EMBY_ADMIN_PW}",
  "uiCulture": "en-US",
  "metadataCountry": "US",
  "metadataLanguage": "en",
  "libraries": [
    { "name": "Movies", "path": "/data/movies", "collectionType": "movies" },
    { "name": "TV Shows", "path": "/data/tv", "collectionType": "tvshows" },
    { "name": "Music", "path": "/data/music", "collectionType": "music" }
  ],
  "apiKeys": ["home-assistant", "mcp-server"],
  "premiereKey": "${EMBY_PREMIERE_KEY}",
  "plugins": [
    { "name": "Trakt" },
    { "name": "TVHeadEnd", "version": "1.2.3", "updateClass": "Release" }
  ],
  "restartAfterPlugins": true,
  "requireFresh": false,
  "refreshLibraries": false
}

Each entry in apiKeys is the Emby "App" label used to identify the key. On re-runs, keys with a matching label are reused (their existing token is returned) rather than duplicated.

premiereKey is optional. When present, init registers the key via POST /Registrations/RegKey. It is idempotent: the current ServerConfiguration.SupporterKey is read first and the registration request is skipped when the server already reports the same value. An invalid key causes the Emby registration endpoint to return 4xx and the error propagates — init does not silently treat a rejected key as success.

plugins is optional. Each entry names an Emby catalog package; init calls POST /Packages/Installed/{Name} and then polls /Plugins until the plugin appears (or, for an upgrade, until the installed Version matches the requested one). Idempotency rules:

  • If no plugin with that name is installed, it is installed fresh (status: "installed").
  • If a plugin with that name is installed and either version is omitted or matches, it is left alone (status: "skipped").
  • If a plugin with that name is installed but its version differs from the requested one, init re-POSTs to /Packages/Installed/{Name} with the new version and waits for the upgrade to be reflected in /Plugins (status: "upgraded").

The optional version, updateClass (Release, Beta, Dev), and assemblyGuid fields are forwarded to Emby's package endpoint as-is. Polling defaults can be tuned via pluginInstallTimeoutMs (default 120 000) and pluginInstallPollIntervalMs (default 2 000); a plugin that never appears within the timeout raises PluginInstallTimeoutError.

Most plugins require a server restart to become active. Set "restartAfterPlugins": true to have init issue POST /System/Restart at the end of a run — but only when at least one plugin was newly installed or upgraded. A pure-skip run is a no-op and never restarts. Plugin-repository configuration (ServerConfiguration.PluginRepositories) is out of scope; use Emby's UI to add custom repos.

Environment-variable placeholders are expanded at load time:

  • ${VAR} — expands to the value of VAR; errors if unset or empty.
  • ${VAR:-default} — expands to the default when VAR is unset or empty.
  • $$ — escape for a literal $.

Missing variables fail the run rather than silently using an empty string, so an unset ${EMBY_ADMIN_PW} won't quietly provision a blank password.

The config schema is validated before any network calls are made. Unknown top-level fields and malformed library entries produce precise errors (e.g. libraries.0.path: library path must not be empty).

Output (JSON):

{
  "wizardRan": true,
  "accessToken": "abc123...",
  "librariesCreated": ["Movies", "TV Shows", "Music"],
  "librariesSkipped": [],
  "apiKeysCreated": [
    { "app": "home-assistant", "token": "..." },
    { "app": "mcp-server", "token": "..." }
  ],
  "apiKeysSkipped": [],
  "premiereKey": { "requested": true, "updated": true, "skipped": false },
  "plugins": [
    { "name": "Trakt", "version": "1.0.0", "id": "plugin-1", "status": "installed" },
    { "name": "TVHeadEnd", "version": "1.2.3", "id": "plugin-2", "status": "installed" }
  ],
  "serverRestarted": true
}

When no premiereKey is configured, the field is { "requested": false }. On a re-run where the key is already registered, it reads { "requested": true, "updated": false, "skipped": true }.

Capture the token into an env var:

export EMBY_API_KEY=$(emby init --config ./emby.init.json | jq -r .accessToken)

Install and uninstall plugins directly

For already-initialized servers, plugins can be installed one at a time without running emby init:

# Install latest release. Waits for the plugin to show up in /Plugins.
emby plugins install Trakt

# Install an exact version from the Beta channel.
emby plugins install Trakt --plugin-version 1.2.3 --update-class Beta

# Skip the wait after POSTing to /Packages/Installed/{Name}.
emby plugins install Trakt --no-wait

# Tune the wait loop.
emby plugins install Trakt --timeout-ms 60000 --poll-interval-ms 1000

# Remove a plugin by Name or Id.
emby plugins uninstall Trakt
emby plugins uninstall 00000000-0000-0000-0000-000000000001

# A missing plugin is an error by default; --if-present makes it a no-op.
emby plugins uninstall Trakt --if-present

install is idempotent: status in the output is installed on a fresh install, upgraded when the installed Version didn't match --plugin-version, or skipped when the plugin was already present at an acceptable version. The option is spelled --plugin-version rather than --version to avoid colliding with the program's top-level --version flag. uninstall accepts either an Emby plugin Id or the plugin Name; Names are resolved against GET /Plugins before deletion.

Plugin installs are asynchronous on Emby's side and most plugins require a server restart to be picked up. emby plugins install never restarts the server — restart it yourself via the Emby UI when you're ready. emby init can optionally restart once at the end of a run via "restartAfterPlugins": true.

Manage the Emby Premiere key directly

For already-initialized servers, the key can be installed or rotated without running emby init:

emby premiere status
# { "supporterKey": "MB-...", "registered": true }

emby premiere set MB-XXXX-XXXX-XXXX
# { "supporterKey": "MB-XXXX-XXXX-XXXX", "updated": true, "skipped": false }

# A second call with the same key short-circuits without hitting
# /Registrations/RegKey:
emby premiere set MB-XXXX-XXXX-XXXX
# { "supporterKey": "MB-XXXX-XXXX-XXXX", "updated": false, "skipped": true }

Both subcommands need the usual admin credentials (--api-key or EMBY_API_KEY) because the underlying /System/Configuration and /Registrations/RegKey endpoints are admin-only.

Output formats

emby users list --format json          # default
emby users list --format yaml
emby users list --format table
emby users list --format table --columns Id,Name

Host / key overrides

emby --host http://other:8096 --api-key ABC users list

License

MIT