Open-source project
ShokoAnime/ShokoServer avatar
ShokoAnime/ShokoServer

Shoko Server: anime metadata that plugs into Plex, Jellyfin and Kodi

Shoko is a media metadata aggregator that solves all of the annoying edge cases that face anime's differing structure from western media. It integrates directly with media software rather than working around things like nfo files or naming conventions.

779 stars99 forksC#MIT

At a glance

What is it?
Shoko Server is an MIT licensed C# media metadata aggregator that identifies anime series from the files you already have and exposes them to Plex, Jellyfin and Kodi through dedicated plugins, so nothing has to be renamed and no nfo file has to be written. The judgement is that the integration model is the product, and that the operational documentation for the container is unusually precise about what to back up and what to configure before startup.
Who is it for?
Shoko Server fits a collector whose library is already on disk and whose player is Plex, Jellyfin or Kodi, because the identification happens server side and the player integration is a first party plugin, which removes the naming conventions and sidecar metadata that the western media ecosystem assumes.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly C#, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A metadata aggregator that plugs into the player, not the filesystem

Shoko is described as a media metadata aggregator that solves the edge cases anime's structure creates compared with western media, and the important half of that sentence is the last one. It integrates directly with media software rather than working around things like nfo files or naming conventions.

That distinction decides how the tool feels in daily use. The usual approach for a media server is that you rename your files to a pattern the scraper understands, or you write sidecar metadata by hand, and the server reads what it finds. Shoko inverts it. The server identifies the series, works out the episodes, attaches the metadata and then hands the result to the player through a plugin.

The README is clear about the result: no more manual inputting and no renaming, with the collection accessible locally and over the internet with no additional work beyond the initial configuration of Shoko Server and one of the supported media player plugins. Scalability is claimed for both a small collection and a large one, and the database and plugin structure in the container is built for that growth rather than for a fixed catalogue.

The project site is shokoanime.com and the installation documentation is at docs.shokoanime.com, with a getting started guide for installing the server.

Six player integrations and an explicit refusal to add more

The supported player list is the contract with the outside world, and it is a short one.

Plex is covered three ways, through Shoko Relay as a server plugin, through Shoko Relay as a Plex bundle, and through ShokoMetadata, each with its own download and repository. Jellyfin is covered by Shokofin, and Kodi by Nakamori and by Shokodi. Every one of these lives in its own repository with its own release page, which is the usual arrangement for a plugin architecture and is worth noticing when planning an upgrade.

Then comes the sentence that tells you the shape of the project. If you are a developer who wants to integrate Shoko with a new media player, the team invites you to its Discord for guidance and assistance. And at this time, the Shoko team itself has no plans to integrate Shoko with any other media players.

That is an unusual thing to publish, and a useful one. It means the plugin set is a boundary rather than a backlog, so a team that runs Emby, for instance, should plan on writing an integration rather than waiting for one. It also means the plugin maintainers are the community, which is why each of those repositories carries its own version numbers.

The bundled plugins load as system plugins you cannot uninstall

Four first-party plugins ship inside official builds, and the way they are packaged is unusual enough to deserve a close look.

The copies that ship with the server load as system plugins, are enabled by default and cannot be uninstalled. Other plugins go into the plugins folder under SHOKO_HOME. The legacy Plex sync support is built with the server itself, while the other three are released from their own repositories, so a build from source leaves them out unless you ask for them with -p:ShokoBundleReleasedPlugins=true, in which case each is checked against the SHA-256 that its published manifest gives. An offline build can fill the .cache/plugins/ directory itself and add -p:ShokoReleasedPluginsOffline=true, and ReleasedPlugins.targets describes the layout.

The four plugins do four different jobs. The TMDB plugin supplies The Movie Database metadata for the tmdb source, covering shows, seasons, episodes, movies, collections, people, studios and networks with their titles, overviews, images and alternate orderings, and it is configured from tmdb.json in its own configuration folder rather than from the server settings. The WebAOM plugin holds the renamer, which is the default relocation provider; it covers basic file names and is feature-frozen, and the README points to a Lua renamer or a custom provider for a folder structure of your own or several managed folders. The Offline Importer imports releases from file names. The legacy Plex plugin holds the /plex webhook and routes, the Plex account linking and the watched state sync, and for Plex it is Shoko Relay that takes over from it.

The container configuration is a documented contract

The Docker section of the README is the most operationally useful part of the documentation, because every variable is given with a default and a reason.

SHOKO_HOME defaults to /home/shoko/.shoko/Shoko.CLI and is where the settings, the logs and the database live, so it is the directory to mount a volume at. A custom path has to exist already, only the default is created for you, and the home directory is required when the server runs as root with PUID=0.

ENABLE_RESTART defaults to true and lets the web interface restart the server. ENABLE_SHUTDOWN defaults to false, and the reason is specific rather than cautious: a stopped container will not restart itself from the web interface that just stopped it. INSTALL_PACKAGES is unset by default and takes extra apt packages, separated by spaces or commas. EXTRA_GROUPS sets supplementary groups for the server user by name or numeric id.

PUID, PGID, UMASK and NO_CHOWN are honoured as well, and the effective values are printed in the startup banner, which is the detail to check first when a mounted volume has the wrong ownership.

The image is built in two stages, the .NET 10 SDK for the build and the ASP.NET 10 runtime for the result, with MediaInfo, librhash-dev, gosu and apt-utils added, a volume declared at /home/shoko/.shoko/ and a health check with a five minute start period.

SHOKO_HOME is the directory to back up, with two exceptions

The README lists what lives under SHOKO_HOME, and the list is short enough to act on directly.

The SQLite folder holds the server's own database, unless the database settings point somewhere else. The data folder holds the plugins' databases, one folder per plugin id, and the configuration folder holds the configuration files, also one per plugin id. The cache folder holds the plugins' caches and is safe to empty while the server is stopped. The plugins folder holds installed plugins and nothing else, since the bundled plugins live next to the server rather than in there. DatabaseBackup holds copies of the databases taken before an upgrade or a plugin migration, which is a deliberate safety net rather than an accident. And images, logs, themes and transcodes hold the images, the logs, the Web UI themes and the streaming renditions.

The instruction that follows is the one to follow: back up everything except cache and transcodes. Those two are derived, and the rest is not, including the plugin databases and the pre-upgrade snapshots.

The layout also explains how the plugin model scales. One folder per plugin id for data and for configuration means a plugin can be removed without taking another plugin's state with it, and the versioned database copies mean a failed upgrade is recoverable.

INSTALL_PACKAGES exists for the driver that has to be there before startup

One environment variable deserves its own explanation, because the reason behind it is not obvious from the name.

INSTALL_PACKAGES installs extra apt packages before the server starts, and it exists for userspace that the image cannot ship for everyone but that has to be present before startup, GPU drivers for hardware transcoding above all. The reason is stated plainly: the plugins probe the hardware while starting and cache what they find. If the driver is not installed at that moment, the probe fails, the result is cached, and installing the driver later changes nothing until the cache is cleared.

The example in the README shows the shape:

yaml
environment:
  - INSTALL_PACKAGES=libva2 libva-drm2 intel-media-va-driver-non-free ffmpeg

There is a consequence to be aware of. The installed packages live in the container's writable layer, so they survive a restart but not a recreate, and they are reinstalled on the next start when that happens. That is the behaviour you want for a container that is recreated on upgrade, but it also means the packages are not part of the image and have to be reinstalled each time, which is precisely why the variable exists in the first place.

The readme notes that a package which fails to install is a problem the operator has to see, which is why the install happens before startup rather than in the background.

A .NET 10 solution with a plugin set and a lot of test projects

The build shows how the project is put together, and the Docker file is the clearest statement of it.

The builder stage uses the .NET 10 SDK image and compiles Shoko.CLI for linux-x64 and net10.0, passing the version, channel, commit, tag and date through as properties and setting the two plugin bundling switches. The runtime stage uses the ASP.NET 10 image with PUID, PGID and the C.UTF-8 locale set, adds the MediaArea repository for MediaInfo, gosu for the privilege drop and librash-dev, copies the build output and the dockerentry.sh script, declares the volume and the health check. A separate Dockerfile.aarch64 covers the other architecture.

The solution itself is large and well segmented. Shoko.CLI and Shoko.Server hold the application, Shoko.Abstractions holds the shared interfaces that plugins implement, Shoko.QueueProcessor is the separate work queue, and Shoko.TrayService is the desktop tray helper. The plugin packages sit alongside, with Shoko.Plugin.LegacyPlex built in and the rest released separately, and there are test projects for unit tests, integration tests, the queue processor and the build tools, plus Shoko.Benchmarks and Shoko.TestData.

The build tooling has its own directory, Shoko.BuildTools with an analyzers project and a targets project, and the repository also carries BundledPlugins.targets, ReleasedPlugins.targets and MediaInfo.targets to describe those layouts.

The release line is 5.3.x, with 5.3.1 on 2026-02-13, 5.3.2 on 2026-03-22 and 5.3.3 on 2026-03-27, and the last push to the repository was on 2026-10-20.

Editorial conclusion

Shoko Server fits a collector whose library is already on disk and whose player is Plex, Jellyfin or Kodi, because the identification happens server side and the player integration is a first party plugin, which removes the naming conventions and sidecar metadata that the western media ecosystem assumes. It is the wrong choice if you want Shoko to talk to a media player it does not support, because the team states plainly that it has no plans to integrate any others, and it is the wrong choice if you expect the server to rename your files into a tidy folder tree, because the bundled renamer is feature-frozen and covers basic file names only. Before you deploy, mount a volume at SHOKO_HOME and back up everything in it except cache and transcodes, set ENABLE_SHUTDOWN only if your container supervisor can restart it, and install any hardware transcoding driver through INSTALL_PACKAGES so it is present before the plugins probe the hardware.

Frequently asked questions

What does Shoko Server do for an anime collection?

It identifies and organises the series in a collection and serves the metadata, so you do not have to rename files to a pattern or write nfo sidecar files. The result is exposed to a media player through one of the supported plugins.

Which media players does Shoko support?

Plex through Shoko Relay as a server plugin or as a Plex bundle, and through ShokoMetadata, Jellyfin through Shokofin, and Kodi through Nakamori and Shokodi. The team states that it has no plans to integrate any other media players.

What should I back up from a Shoko container?

Everything under SHOKO_HOME except the cache and transcodes folders, which are derived. That includes the SQLite database, the per plugin data and configuration folders, the plugins folder and the DatabaseBackup folder, which holds database copies taken before an upgrade.

Why do I need INSTALL_PACKAGES for hardware transcoding?

The plugins probe the hardware while starting and cache what they find, so a GPU driver has to be present before startup rather than installed later. The packages are installed with apt inside the container's writable layer, so they survive a restart but are reinstalled after a recreate.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. ShokoAnime/ShokoServer on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/shokoanime-shokoserver.svg)](https://hysenlabs.com/projects/shokoanime-shokoserver)

Was this useful?