Built-in Plugins
Built-in plugins are part of AB. They are in module/plugins/builtin/. They use the same SDK as third-party plugins, so you can use them as a reference. Enable, disable and configure them in Settings → Plugins.
| id | Default | Purpose |
|---|---|---|
rename | Enabled | The rename strategies pn, advance and template |
ingest-filters | Enabled | The include filter (torrent.filter) |
media-server-refresh | Enabled | Refresh Jellyfin / Emby / Plex after organizing (it does nothing until you set the address and key) |
hardlink | Disabled | Hard-link organized files into the media library |
rename
The host has only none (keep the name). pn names a file with the title that AB parsed from the file name. advance uses the series folder name. Their output is byte-identical to 3.x. template renders the file name stem with a sandboxed Jinja2 template.
Enter the template in Settings → Plugins → rename, for example {{ title }} - S{{ season|pad(2) }}E{{ episode|pad(2) }}. Variables: title, bangumi_name, season, episode, episode_type, group, kind, language. The filter pad(n) pads with zeros and keeps the fraction of a half episode. AB renders the template one time when you save. An invalid template is refused (HTTP 422). If rendering fails at run time, or the result is empty or has a path separator, the file keeps its name and AB sends a notification. AB does not fall back to pn.
ingest-filters
Adds an include filter. The rule already has an exclude filter. Set a list of regular expressions (case-insensitive). AB then downloads only torrents whose name matches at least one. An empty list means no filter. An invalid regular expression is matched as literal text.
media-server-refresh
Subscribes to torrent.organized and to hardlink.linked, which hardlink publishes when it places new files in the library. After the first event, it waits delay seconds. The events in this time share one refresh request. An event that arrives after the request is sent causes one more refresh.
| Option | Description |
|---|---|
server | jellyfin, emby or plex |
url | The server address, for example http://192.168.1.10:8096 (Plex default port 32400). Empty means no refresh |
api_key | The API key of Jellyfin / Emby, or the X-Plex-Token of Plex |
delay | The delay in seconds. Default 30 |
hardlink
Subscribes to torrent.organized and links media files and subtitles into the media library directory. The download directory stays as it is and the torrent keeps seeding.
| Option | Description |
|---|---|
source_root | The download root (an AB local path). The library keeps the same structure: library_root / (file path relative to source_root) |
library_root | The media library directory (an AB local path). It must not be inside source_root |
path_map | [{downloader, from, to}]: replaces the downloader path prefix from with the AB local path to. downloader defaults to default. The longest prefix wins. A path with no match is used as it is |
cross_device | When a hard link crosses file systems (EXDEV): copy (default), symlink or skip (skip and notify) |
- At first enable,
source_rootandlibrary_rootare empty and the plugin shows a load failure. The settings form is already visible. After you fill the fields and save, the plugin reloads. - The plugin writes the link or copy to a temporary file next to the target, then renames it atomically. An interrupted copy leaves no half file.
- If the library has a file with the same name that this plugin did not create, the plugin skips it, does not overwrite it, and sends a
hardlink.failednotification. - A link that this plugin made for the same episode is replaced atomically after a version upgrade (a new version replaces the old torrent and the canonical name stays the same). The new link points to the new file.
- When the plugin receives an event for a file that is already linked, it does nothing. It records the targets that it created in its own key-value store. If the user deletes a file that the plugin placed, a new event does not create it again. Only a backfill creates it again.
- Deleting a torrent does not delete the links in the library.
- AB does not process files that were downloaded before you enabled the plugin. Click "Link existing files" in the settings section of the plugin, or call
POST /api/v1/plugins/hardlink/backfill. It walks.mp4/.mkv/.ass/.srtfiles undersource_rootand returns the counts{"linked", "exists", "conflict", "failed"}.
Docker
A hard link cannot cross file systems. In Docker, put the download directory and the media library on the same disk. Map them into the AB container with one mount point (for example, mount /mnt/media as /media and keep both directories under it). Two separate mounts count as different file systems, even on the same disk. Then the link falls back to the cross_device behavior. If the downloader runs in another container and sees different paths, use path_map.