Status checked: 2026-10-25. BookshelfNG
0.4.21.71was the previous public release. The owner authorized one final security-maintenance release,0.4.21.72; this does not approve migration or cutover. Issue #144 is closed, while the migration and channel-acceptance gates remain open. Keep BookshelfNG in service until those gates close.The current schema-v4 audit compares BookshelfNG source 7ee2917974cf2d66b3c6daa3cf5827873689ee3b with ChaptarrNG target 0be2fe09fc8301db8a064ded4f36c5b961e06b37: 1,151 paths, 89 reviewed mappings, 753 dispositions (175 retained, 143 equivalent, 259 ported, 176 repository-only retirements), and 398 open paths (265 semantic review, 130 unmapped, two source-deleted, one identical). ChaptarrNG's Build, CodeQL, Semgrep, Trivy, and dependency-submission runs for 0be2fe09 are queued; the security analysis passed. The asset URL guard is mapped and dispositioned. Path decisions remain separate from behavior, migration, and operator acceptance.
Populated SQLite conversion and database rollback passed on a disposable copy. Representative feature/provider acceptance, installed rollback, production media behavior, and channel handoff remain open. Keep BookshelfNG in service and do not start ChaptarrNG against BookshelfNG appdata. See the migration guide.
Historical validation notes below retain their original snapshot dates.
Exact-head artifact repeat (2026-10-19): the Linux artifact from PR #131 Build 39316535744 passed the checked-in SeerrNG Compose smoke with synthetic migrated audiobook and ebook records. Using SeerrNG rebuilt from
22f3bbc5874752b50a3b1206ca0bd3ebe0309f95, it verified restricted-key access, administrative/unrelated command denial, and pending import create/poll/cancel. The candidate app artifact ran in a temporary image based on public.977; this did not validate candidate image packaging, successful acquisition, operator data, installed rollback, or channel handoff. Full details are in the migration guide. Migration decision: keep BookshelfNG in service. Do not apply the converter or start ChaptarrNG against BookshelfNG appdata; normal ChaptarrNG startup converts a supported source database automatically. A passing preview is not cutover approval. See the migration guide. BookshelfNG PR #154 improved empty-database selection in sourcemain, but the fix is not in the published.71helper. The.71helper may print a zero-bytereadarr.dbas selected beside a populatedaudioarr.db; ChaptarrNG.977independently ignores empty legacy files when choosing its migration source. See the migration guide for the version-specific behavior. A local AUR candidate passed isolated pacman upgrade/downgrade, package-level preview/conversion/restore, and an active systemd service upgrade and rollback against a synthetic populated migration-158 database. Real operator data and host-specific service settings remain open. The network-online wait was masked only inside the network-isolated test container. A Fedora 44 RPM transaction upgraded the published.71package to a local.977bridge candidate and downgraded back with config/data canaries. The run usedrpm --nodepsand a mockedsystemctl; it did not run a real service or migrate a database. The currentslskdn/bookshelfngCOPR repository has no package entries for Fedora 43, 44, 45, or Rawhide, so live COPR/DNF acceptance remains open.Prior ChaptarrNG PR #131 application-code validation: snapshot
0612cb4c90b75818e5349eb868cc0638825de02apassed exact-head Build 39239940373: Linux, macOS, and Windows tests, PostgreSQL migration smoke, native-runner receipt reconciliation, and release-note contract passed. CodeQL 39239934583, security 39239940344, NuGet submission 39239932165, and dependency review 39239940313 passed. Disposable-fork validation 39239940512 was skipped by its external-fork gate. SeerrNG's adapter and request-route suite at source commitb810153cpassed 4 files / 283 tests. The Linux artifact also passed the earlier empty-library API and authorization smoke. A populated source-build smoke on later code is recorded in the migration guide. Populated synthetic migration-to-SeerrNG smoke (2026-10-19): ChaptarrNG candidate12f290bdbuilt through its checked-inDockerfile.build, converted a disposable migration-158 database during normal startup, retained the source backup, and persistedHardcoverEnabled=trueforHARDCOVER=true. SeerrNGReadarrAPIat commitfdc439aa9read both migrated audiobook and ebook records and their Hardcover identities. Capability discovery, restricted-key authorization, and pending add/poll/cancel passed; the ChaptarrNG importer suite passed 43/43. The.m4b/.epubplaceholders do not exercise media processing. A separate real-tool importer check passed all six synthetic multipart M4B cases on candidate12f290bd; Linux CI now runs it in a pinned tool image. Synthetic embedded-chapter tests now pass on the later candidate; representative audiobooks and restart/resume remain unverified. This is not operator-data, installed rollback, or channel acceptance. At the time of this smoke PR #131 was draft; it merged on 2026-10-20. Issue #144 and all release gates remain open, and no release or alias bridge was published. See the migration guide.Historical candidate CI: PR #131 head
38be9422a0390c0b3d4d1c453ec14b25d3aa99a4added portable BookshelfNG BKSENC01.encbackup import/export, cross-checked against BookshelfNG's source implementation. Its exact-head Build 39267876585 passed Linux, macOS, Windows, PostgreSQL migration, release-note, and native-runner receipt checks. CodeQL 118112421054, security analysis 39267876503, and dependency review 39267876754 passed; disposable-fork validation was skipped by its external-fork gate. The merged source and latest exact-head validation are recorded above. The release freeze and retirement gates remain in force.
M4B validation update (2026-10-19): ChaptarrNG PR #131 commit
c4fa8125095f583ad9eee534f70328e8eef1b44cfixes Move-mode cleanup after a successful profile-based multipart merge. Embedded-chapter tests first exposed that source tracks remained; fixture isolation alone did not resolve it. Exact-head Build 39288736177 passed Linux's full suite and pinned-tool M4B checks, PostgreSQL migration smoke, and release-note contract. Windows build and full test steps passed. The macOS job was cancelled before a runner started, so the cross-platform matrix is incomplete. CodeQL, security, dependency-review, and NuGet checks passed. Representative media, restart/resume, and operator acceptance remain open. No release or bridge was published.Prior exact-head ChaptarrNG PR #131 validation (2026-10-19): candidate
b7e900d49648269d5118bbfba44289c0200b095bpassed Build 39292223717 on Linux, macOS, and Windows. PostgreSQL migration smoke, release-note contract, native-runner receipt reconciliation, and the Linux pinned-tool M4B smoke passed. CodeQL, security/secret scan, dependency review, and NuGet submission passed; disposable-fork validation was skipped by its gate. This is code validation only; representative data, parity, installed rollback, and channel acceptance remain open. No release or bridge was published. The prior docs-only PR #131 head was commit93213b677a0bbb256aaf782c389a4f1a3d9c2ee7on top of application-code commit0e881d921dd55aa89e12747557ccaadbb2352a21. Exact-head Build 39316535744 passed Linux, macOS, Windows, PostgreSQL migration, release-note contract, and native-runner receipt reconciliation in full attempt 3. The application-code Build 39313568727 passed on Linux, Windows, and macOS, including PostgreSQL migration, release-note validation, native-runner receipt reconciliation, and Linux pinned-tool M4B checks; CodeQL, security/dependency, dependency-review, NuGet, analysis, and Helm identity checks passed too. Disposable-fork validation was skipped by its external-fork gate. This is code validation only. At that checkpoint PR #131 remained draft; representative-data acceptance, semantic parity, installed rollback, and channel handoff remain open. No release or bridge was published.Follow-up request lifecycle probe (2026-10-19): then-draft ChaptarrNG PR #131 commit
d97136040e5f76f6aa0b140d5c0ed74f8de7501eaddedintegration/seerrng-request-lifecycle.mjs, wired intointegration/seerrng-smoke.compose.yml. It passed against the prebuilt Linux candidate0.9.978.0from Build 39239940373 (application snapshot0612cb4c90b75818e5349eb868cc0638825de02a) and SeerrNG sourceb810153c: the realReadarrAPIadapter created, polled, and cancelled a synthetic unavailable-author import, and ChaptarrNG returned terminalFailed/Cancelled by user.node --check, Prettier, and Compose configuration validation passed. The earlier Compose run used a temporary runtime image. A follow-up source-build run on 2026-10-19 built through the checked-inDockerfile.buildfrom ChaptarrNG PR #131 head7cfb5d87and passed both scripts after the harness prepared its disposable/booksvolume as UID/GID99:100. Successful fulfillment, retries, availability/history, converted records, saved operator settings, and operator acceptance remain open. This proves the synthetic cancellation path only; successful fulfillment, retries, availability/history, converted-record behavior, unchanged production settings, and operator acceptance remain open. On 2026-10-19, unpublished candidate build0.9.978.0passed migration preview, explicit apply, rollback preview, and explicit rollback against a task-scoped copy of populated migration-158 SQLite data withHARDCOVER=true. The live BookshelfNG service remained running; candidate commands targeted only the separate copy, and network access was not blocked for those commands. The restored source matched its retained backup byte-for-byte, the converted database was retained separately, and integrity/foreign-key checks passed. Unresolved books were preserved in both catalogs as unmonitored with a private review sidecar; their media types still need review. Every migrated author, book, and edition retained its native Hardcover identity. This is one populated SQLite rehearsal, not approval to migrate installations; older schemas, PostgreSQL operator data, parity, and installation-channel acceptance remain open. No private library counts or identifiers are published. See the fixture evidence and ChaptarrNG PR #131. A separate copy-only rehearsal against populated operator SQLite data with native Hardcover mode passed preview, apply, restore preview, and rollback. Preview left the source copy unchanged; restore preview left the converted database and retained source backup unchanged; rollback restored the retained backup byte-for-byte and preserved the converted database separately. Integrity and foreign-key checks passed. This does not close ambiguous-media review, older-schema or PostgreSQL operator-data validation, feature parity, or installation-channel acceptance. The.978Linux app artifact from Build 39267876585 also started against a fresh converted schema-121 copy using the published.977runtime image, empty scratch mounts for configured media roots, and an internal-only network./pingreturned HTTP 200. This verifies app startup with converted data, not candidate image packaging or a live installation switch. The published ChaptarrNG.977importer maps bare numeric IDs to Goodreads even if BookshelfNG used native Hardcover mode. Do not apply.977to a native Hardcover database; its preview cannot detect this identity mismatch. The merged, unreleased source implementation uses explicit provider mode. At an earlier candidate checkpoint, BookshelfNG source snapshot 6e1a62e12 and ChaptarrNG code snapshot 8b4c6e23 included the Editions and Narrations tab and series narrator comparison. That checkpoint passed Build 39205452341, CodeQL 39205449712, dependency review, security, NuGet, and release-note checks. These are prior-head results; merged source status and latest exact-head validation are summarized above. Public ChaptarrNG .977 predates the catalog UI and the explicit issue #114 setting. ChaptarrNG v0.9.974+ previously initialized new-author format paths from configured defaults; currentmainadds the requested disabled-by-default switch. A local SeerrNG Compose smoke passed against ChaptarrNG PR #131 source headddec3e81(application-code snapshot2c0401fc) and SeerrNG10f06eab9. It verified capability discovery, empty paged-library access, and restricted-key denials for administrative and unrelated commands. This is API/key evidence only; populated migrated data and end-to-end SeerrNG workflows remain open. Merged ChaptarrNG source includes format-aware, previewable single and bulk moves of registered media and linked book sidecars. It resolves sidecars from the linked book format root, rejects relative paths outside the author folders, stores moved paths relative to the destination format root, and leaves untracked files and author-wide extras in place. The media-move implementation passed Windows testing after commit 2c0401fc replaced POSIX-only fixture paths; application-code snapshot0612cb4cpassed all platform suites on Build 39239940373. Representative-library, cross-device, and partial-failure acceptance remain open; the change is in merged source but not released. Provider settings are copied only when ChaptarrNG has a matching implementation, contract, and saved settings fields. Merged, unreleased ChaptarrNG source includes BookshelfNG's Hardcover public-list/reading-status provider and compatibility ports for Goodreads OAuth bookshelf and owned-book lists and write notifications. Complete existing OAuth settings are retained; preview blocks missing or partial credentials and does not print their values. Public shelves can remain unauthenticated when a valid numeric user ID is saved. Goodreads API acceptance with existing credentials is still unverified, and Goodreads no longer issues new developer keys. These changes are not in published ChaptarrNGv0.9.977; keep the release freeze and BookshelfNG service in place. See the Goodreads API deprecation notice and the operator migration guide.
The ChaptarrNG PR #131 application-code snapshot 0612cb4c also ports the native Hardcover provider, maps saved HardcoverAuth to HardcoverApiToken, preserves bare numeric IDs according to source HARDCOVER mode, and fails closed when mode is unset or invalid. The candidate includes provider-mode image targets for Bookshelf aliases, but no legacy alias bridge has been published or enabled. These changes are not in the published .71 helper or ChaptarrNG .977 image. Earlier exact-head run 39175250100 passed platform, PostgreSQL, security, and release-contract checks; its final Linux artifact passed synthetic provider-mode and rollback checks. Current-head results are listed above. Converted-data and installed rollback acceptance remain open. Keep the release freeze in place.
BookshelfNG's tagged image/release jobs, manual distribution retries, and the
ChaptarrNG legacy bridge are also fail-closed. They require the
BOOKSHELFNG_RELEASE_READY=true repository variable, which is unset. Keep it
unset until migration, parity, rollback, and channel acceptance are complete.
BookshelfNG is a self-hosted ebook and audiobook library manager descended from Readarr. Follow authors and books, monitor indexers for new releases, automatically grab downloads, and organize, rename, and upgrade files in your library. BookshelfNG is a complete app on its own. It does not require SeerrNG or a metadata proxy.
BookshelfNG is built on .NET 10 LTS.
Support BookshelfNG on Ko-fi.
Published containers and native release archives include the required runtime; source builds require the .NET 10 SDK.
BookshelfNG 0.4.21.71 was the previous source release; 0.4.21.72 is the
one-time final security-maintenance release. Existing Unraid
installations should follow the
BookshelfNG-to-ChaptarrNG migration guide
and keep an independent appdata backup. The BookshelfNG Community Apps template
has not yet switched images. New Unraid installations should use the
ChaptarrNG Unraid template,
which installs the standard maintained application.
BookshelfNG is for people who want Readarr-style book automation with a choice of metadata providers. Goodreads-compatible metadata services and native Hardcover remain available for primary library refreshes. Runtime catalog search is independently selectable across those providers, Open Library, and the other public catalogs. See Metadata sources for provider behavior and settings.
For local MCP access, see the SnapeTech MCP integration guide.
A single BookshelfNG instance and database can track ebooks and audiobooks on the same author and book records. You do not need separate BookshelfNG instances just to support both formats. When SeerrNG routes ebook and audiobook requests separately, both service entries can point to this same BookshelfNG URL and API key.
Each author keeps the existing Path as the default, with optional ebook and
audiobook folder overrides for future imports, upgrades, and renames. Changing
an override alone does not move existing files. In the author editor, use
Move existing ebooks or Move existing audiobooks to preview and queue a
move for one author. To move one format for several authors, open the author
library, choose Author Editor, select authors, then choose Move selected
media. Both workflows are also available through the
API and CLI.
A move includes only media files and book sidecars registered in the current instance. It does not sweep unknown files, move author-wide extras, or merge a second instance's catalog or database. Bulk previews show each destination, missing files, conflicts, and estimated copy space; any conflict prevents the batch from being queued. A queued move runs in the background and is not an all-or-nothing transaction, so review its progress in Activity → Queue. Move actions require the instance's administrator API key. BookshelfNG has no separate in-app administrator and regular-user roles.
For a legacy ebook/audiobook setup with two BookshelfNG instances, move each instance's tracked format from that source instance, then import or rescan the files in the instance you are keeping. Keep both source databases until the files have been moved and verified: BookshelfNG does not merge their author, book, profile, monitoring, or history records. The full legacy consolidation runbook covers destination mounts, backups, the UI/API/CLI steps, and follow-up import. Quality and metadata profiles have optional ebook and audiobook overrides; each format falls back to the author's shared profile when its override is unset. Separate instances remain an option for isolated databases or settings. See the feature inventory and ChaptarrNG retirement matrix for current parity and migration status.
The final BookshelfNG release includes a source-side helper that archives the
entire appdata directory before it calls the standard ChaptarrNG preview,
apply, or rollback command. ChaptarrNG v0.9.977 remains the latest public
release. Its converter supports the final migration-158 SQLite schema and
bundles the BookshelfNG source migration chain, but rejects versions before
migration 14 because their table is still named Blacklist. PR #126 merged a
version-aware guard and migration-1 rollback fixture into ChaptarrNG main;
hosted Linux, macOS, Windows, and PostgreSQL migration checks passed. This
source fix is not available in .977. ChaptarrNG releases are frozen until
feature parity, representative data migration and rollback, and channel
acceptance are complete. Populated synthetic migration-22 tests cover
conversion and rollback, but older-schema behavior on real data is not
established. A separate private populated migration-158 SQLite snapshot also
passed preview, apply, and rollback with the public .977 Linux image. Preview
left the source unchanged, and both backups passed integrity and foreign-key
checks. Ambiguous media choices remain for human review, and this does not
establish older-schema, PostgreSQL, feature-parity, or channel acceptance.
PostgreSQL source conversion remains unsupported. If the source
does not identify a format, ChaptarrNG preserves the work in both catalogs
without monitoring and writes a private review file. This keeps conversion
moving without guessing which format to search.
ChaptarrNG PR #128 merged release and distribution workflows that fail closed
unless CHAPTARRNG_RELEASE_READY=true; the repository variable remains unset.
The current .978 source version bump is not a published release. ChaptarrNG
PR #127 merged as b3089a39 and adds selectable supplemental catalogs,
per-field metadata preferences, and exact-identity recovery for unmapped files.
Its cross-catalog fallback queues a reviewable pending-author import and never
attaches a file directly. Exact-head hosted validation passed; provider/settings
migration and behavior on converted operator data remain open.
ChaptarrNG PR #129 merged to main as 949ae3dd. The source now includes the
opt-in BookshelfNG M4B merge settings, tagged track ordering and chapter
titles, original-track fallback, and source cleanup only after a successful
move-mode import; copy mode retains the originals. The clean head passed the
full hosted Linux, macOS, and Windows suites, PostgreSQL migration validation,
CodeQL, dependency/security, and release-note checks. A synthetic two-track
smoke using the .977 image's m4b-tool preserved the supplied chapter titles
and offsets and produced AAC at 44.1 kHz stereo, about 128 kbps. It validates
the external tool and sidecar format. The then-draft ChaptarrNG PR #131 candidate at commit
bdd7518f added a six-case tool-enabled synthetic importer smoke that passed
locally in an isolated Linux container with m4b-tool 0.5.2, mp4v2 2.1.1,
and FFmpeg/FFprobe 6.1.1. Successful cases check tagged order, chapter titles
and offsets, metadata, registration, and Move/Copy source handling. Failure
cases check fallback to separate original-track imports in both modes when
FFprobe cannot read a source and when m4b-tool fails after a controlled
FFmpeg conversion error. Synthetic embedded-chapter tests pass on c4fa; representative M4B media and restart/resume remain open. The feature is not in public
.977; keep BOOKSHELF_M4B_MERGE unset after migration until the remaining
acceptance gates close and a release containing it is available.
ChaptarrNG PR #130 merged to main as 9f1ae60b. When no explicit
BookMatchingStrictness exists, it maps BookshelfNG's numeric
BookImportMinimumMatchPercent to the closest mode: 50–66 to Aggressive,
67–82 to Balanced, and 83–99 to Strict. Explicit Chaptarr settings take
precedence; invalid legacy values fail closed; and the raw BookshelfNG row is
retained while the report calls out the lossy approximation. The matching
algorithms differ, so converted-library behavior still needs acceptance. This
source change is not in public .977.
The helper does not copy media or download folders mounted outside appdata, translate every environment setting or external service, or update a pinned image or package on its own. Keep the same media/download mounts where possible, back up external settings separately, and follow the migration guide. PostgreSQL, full feature parity, and several package-channel upgrade and rollback paths remain unverified. The disabled-by-default release bridge does not change live tags or packages until its independent acceptance gates pass. The consolidation report records current evidence and open gates. The ChaptarrNG retirement status lists the current channel state and acceptance items.
The final source release also clears its frontend dependency audit. The local
braces toolchain patch and the full Yarn and .NET audit commands are
documented in Dependency security.
Retiring BookshelfNG into ChaptarrNG is a separate gate from any later ChaptarrNG retirement. Every BookshelfNG capability carried into ChaptarrNG then joins the upstream blocker set alongside all features ChaptarrNG maintains or is actively adding, including unpublished work in progress. That complete union blocks ChaptarrNG retirement as a whole. Active ChaptarrNG branch and pull-request features count before release; the matrix records the current snapshot and individual gates. See the combined ChaptarrNG retirement matrix.
- Choose how book metadata is served. The
hardcoverimage includes a native Hardcover GraphQL provider. Search, author, work, edition, series, ISBN, and ASIN lookups go from BookshelfNG directly to Hardcover. There is no proxy between them. When you need one, BookshelfNG can use a Readarr-compatible metadata endpoint instead, including a service you host yourself. - Keep old libraries usable. The
softcoverimage retains Goodreads compatible IDs and import behavior for existing Readarr/softcover databases. You can also choose a compatible metadata endpoint withMETADATA_URL. - Identify ebooks from their own metadata. BookshelfNG reads identifiers embedded in ebook files, strips ISBN formatting, validates ISBN-10 and ISBN-13 check digits, and prefers ISBN-13 when an ebook provides multiple valid identifiers. ISBN and ASIN are also used for direct metadata searches and edition matching.
- Control catalog search timing. The Add page waits for you to submit a search by default. Enable search-as-you-type when you want results as you enter a query; the preference is saved in the current browser.
- Find and compare likely releases. Import identification searches by ISBN, ASIN, and Goodreads ID before using author and title. If author information is missing, it can search by title alone. Candidate editions are ranked using identifiers and available edition details; ambiguous matches can still need review. Search result ordering is preserved.
- Keep multiple formats for a book. Different ebook formats and audiobook files can stay attached to the same book. Import and upgrade decisions only compare compatible formats; see import matching and format support.
- Import common ebook and audiobook formats. Recognized ebooks include EPUB, KEPUB, MOBI, AZW3, and PDF. Audiobooks include M4B, MP3, FLAC, AAC, M4A, OGG, and related formats; see the complete extension list.
- Tune edition matching and series names. Metadata profiles can rank edition title, format, and publisher terms, and choose preferred series for filenames and metadata. See import matching and format support.
- Organize books for Jellyfin. Jellyfin's Books library expects each book in its own folder. Enable Rename Books and use a book-title folder in Standard Book Format; see the Jellyfin folder layout guide.
- Import books from the lists you use. BookshelfNG supports Goodreads shelves, owned books, series, and Listopia lists, plus native Hardcover list imports. Hardcover imports honor the lists selected in configuration.
- Search MyAnonamouse directly. The native MyAnonamouse indexer lets you use the tracker without adding Prowlarr as an intermediary.
- Connect current download clients. BookshelfNG supports qBittorrent 5.2 authentication alongside the download clients inherited from Readarr.
- Build chaptered audiobook files when needed. Completed downloads with
multiple tracks for one edition can be merged into a single M4B when
BOOKSHELF_M4B_MERGE=trueand an FFmpeg executable is available. This is opt-in; the standard Docker image includes FFmpeg. - Keep the familiar automation. Monitor authors and books, watch indexer RSS feeds for releases, search for missing monitored books, apply quality and metadata profiles, manage download clients, scan and import existing files, and rename or upgrade releases automatically. Optionally move configured extra files when author renaming moves books to a new folder; see sidecar rename behavior.
- Search and recover downloads. Use interactive release search to choose an available release when an indexer supports it. BookshelfNG can search again after a failed download; automatic grabs and manually selected grabs have separate re-search settings. You can adopt a matching torrent already in a download client, and ignore an unmatched queue item without deleting the download. For supported ebook sources, add the built-in Direct Download indexer. It uses an API key when configured and can optionally resolve slow links in headless Chromium; its built-in client tracks the transfer without another download-client service. Direct search is interactive and does not provide RSS. See search and download workflows.
- Use narrator credits to identify audiobooks. Import matching compares narrator tags with edition metadata when both are present. Narrators stay separate from authors, appear in book search and filtering, and can be written to audio files when audio tag writing is enabled. See audiobook metadata.
- Send imports to BookLore. BookLore is an optional supported app. Add it as a notification destination to upload imported files to its BookDrop review queue; BookshelfNG runs without BookLore. See the BookLore integration guide. During a ChaptarrNG migration, this saved connection remains configured for BookLore; it is not automatically rewritten to BookOrbit. See the migration handoff.
- Connect a Calibre Content Server. Configure a Calibre library as a root folder to add imported books to the library, sync metadata, and convert into configured output formats.
- Keep library activity private. BookshelfNG removes Servarr's Sentry analytics and exception-reporting integration. An independent diagnostics module is available for operators who explicitly install and enable it; the standard app image contains no reporting module or telemetry SDK.
BookshelfNG retains the Readarr-compatible API and the broader Readarr library-management workflow. A book can keep multiple ebook formats and audio files in one instance; import and upgrade checks keep those formats separate. See import matching and format support.
Some capabilities are part of the Bookshelf and Readarr lineage rather than unique BookshelfNG additions. The capabilities and compatibility guide compares those upstream features with BookshelfNG's maintained changes and documents provider boundaries, migration limits, and implementation links.
Author and book metadata are persisted in BookshelfNG's application database. Refreshing a book for an author already in the library reuses that local author record when the provider IDs match, so a book refresh does not need to fetch the author's full catalog again. Automatic author validation is age and activity based; manual refreshes and metadata-profile changes can force an update. See Author metadata storage and refresh behavior for the exact rules, Hardcover request caching and rate-limit behavior, failure handling, troubleshooting logs, and source-code references.
For a normal Docker install, use the published image below. You do not need to
clone the source repository or run build.sh; the image already contains the
backend and web UI. Save the example as compose.yaml in an empty directory.
The web interface listens on port 8787. Persist /config, and mount your
downloads and library paths so BookshelfNG and your download clients can
access them.
services:
bookshelf:
image: ghcr.io/snapetech/bookshelfng:hardcover
ports:
- "127.0.0.1:8787:8787"
volumes:
- ./bookshelf-config:/config
- /path/to/downloads:/downloads
- /path/to/books:/books
restart: unless-stoppedRun docker compose pull and docker compose up -d, then open
http://localhost:8787 to set up your root folder, metadata source, indexers,
and download clients. The
softcover image is available for Goodreads-compatible libraries. Both
published Linux images support amd64 and arm64 hosts.
BookshelfNG also runs directly on Windows, macOS, Linux, and FreeBSD. Native release archives include the .NET runtime and web UI; they do not require SeerrNG or a container runtime. Start an extracted Linux, macOS, or FreeBSD archive with:
./Readarr -nobrowser -data="$HOME/.local/share/bookshelfng"On Windows, run Readarr.exe and set a persistent data path under
%LOCALAPPDATA%, or use the Windows x64 setup installer attached to each
release. The installer registers BookshelfNG as a service and backs up the
existing Readarr-compatible data before upgrades. Then open
http://localhost:8787. The
standalone installation guide covers platform
archives, data migration, system services, and package-specific setup.
The release pipeline builds .deb, RPM, Flatpak bundle, AppImage, and Helm
artifacts, and supports AUR, COPR, Ubuntu PPA, and Chocolatey publishing when
those publisher accounts are connected. See the
distribution channels guide for package links,
repository setup, and release details.
To combine a multi-track audiobook download into a single chaptered M4B, set
BOOKSHELF_M4B_MERGE=true. This applies to completed downloads received from a
download client. BookshelfNG groups approved tracks by book and edition,
orders them using embedded disc and track numbers or filenames, creates a
chapter for each track, and reruns the normal import checks on the merged
file. If FFmpeg is unavailable, a merge fails, or the merged file fails import
checks, BookshelfNG keeps the original tracks and continues the normal import.
The standard Docker image includes FFmpeg. For native installs, provide an
executable named ffmpeg on BookshelfNG's PATH, or set
BOOKSHELF_FFMPEG_PATH to its path. The merge transcodes audio to stereo AAC
at 44.1 kHz and 128 kbps by default.
Set BOOKSHELF_M4B_AAC_BITRATE_KBPS to a value from 48 to 320 to choose a
different bitrate. When the merged file imports successfully in move mode,
the original tracks are removed; copy mode and downloads that cannot be moved
retain their source tracks. See the capabilities and compatibility guide
for the exact behavior and implementation references.
ChaptarrNG's published v0.9.977 does not honor these three BookshelfNG
variables. A source-only compatibility candidate is being validated; this
does not change the final BookshelfNG build or release. Keep the merge opt-in
disabled after migration until a tested ChaptarrNG build documents support.
The hardcover image uses BookshelfNG's native Hardcover GraphQL provider by
default. It searches Hardcover for books and authors and maps work, edition,
series, ISBN, and ASIN data into Bookshelf's existing metadata model. This
removes the extra metadata service from the normal request path.
Native access requires a Hardcover API token at runtime:
HARDCOVER=true
HARDCOVER_AUTH=Bearer your-hardcover-api-tokenHARDCOVER_API_KEY is accepted in place of HARDCOVER_AUTH. The default API
endpoint is https://api.hardcover.app; set HARDCOVER_API_URL to use a
compatible endpoint or test service. The Hardcover token can also be entered
in Settings > Metadata > Primary Metadata Provider. Environment credentials
take precedence over the saved setting; the settings API never returns the
saved token.
Native mode handles transient request failures and sparse or nullable metadata responses, maps Hardcover work and edition records into Bookshelf's library model, and caches responses in the BookshelfNG process for the lifetime of the instance. Author responses are cached for 30 minutes, work responses for six hours, and search responses for 10 minutes. These response caches are separate from the author and book metadata stored in the library database. See the Hardcover API getting-started guide and Hardcover author schema for Hardcover's API reference. BookshelfNG does not silently switch to another metadata service after an API error.
When BookshelfNG creates the initial Standard metadata profile on a database
with no profiles, HARDCOVER=true selects a minimum popularity of 50; other
modes use 350. This lower default can keep more low-popularity catalog books
during refresh. Existing profiles are preserved and can be adjusted in the
metadata profile settings.
Text search fetches Hardcover's result IDs in one batched book query instead
of making a separate detail request for every result. ISBN/ASIN searches and
edition lookups fetch the parent work in the same GraphQL operation. API
requests are paced at one per second. BookshelfNG honors Hardcover's
Retry-After and exhausted rate-limit headers; when a limit is reached, it
stops sending further requests from this process until the reported reset and
returns an error for calls made during that cooldown instead of retrying into
the limit.
Every provider used for runtime book discovery can be turned on or off independently in Settings > Metadata > Runtime Catalog Sources. This selection controls title, ISBN, ASIN, and import searches. It does not change how existing library records refresh. Results from an alternate catalog retain a provider-qualified ID and continue to resolve through that provider. Results from the configured primary catalog keep its existing ID format so current libraries continue to match them; older unqualified IDs also keep using the configured primary provider.
The selectable sources are Hardcover, the configured Readarr-compatible metadata API, Open Library, Google Books, Library of Congress, Gutendex, Internet Archive, NDL Search, Europeana, and the Goodreads-compatible Apify adapter. With no saved source selection, Bookshelf enables LOC, Gutendex, and the currently configured primary provider. Open Library, Internet Archive, NDL Search, and Apify are opt-in. Google Books and Europeana are enabled when their keys are set. Hardcover needs its API token. All sources can be disabled, including the configured primary provider's catalog search.
Field-level metadata preferences are configured separately from catalog search. Choose an enabled supplemental catalog for a book's title, description, publisher, language, release date, page count, cover, genres, or author image. Edition details require a matching ISBN; work-level metadata and images can also use an exact title-and-author match. See capabilities and compatibility. Use catalog metadata composition and unmapped-file recovery to retry old no-match files in the UI, API, or CLI.
BOOKSHELF_METADATA_SOURCES accepts hardcover, metadata-api,
openlibrary, googlebooks, loc, gutendex, internetarchive, ndl,
europeana, and apify-goodreads. A custom value replaces the saved UI
selection; an empty value disables all runtime catalog searches. The
environment setting remains authoritative and disables catalog selection in
the UI. Saved credentials are stored in the BookshelfNG configuration database
and returned as presence flags only. Non-empty credential environment values
take precedence over saved values.
HARDCOVER=true
HARDCOVER_AUTH=Bearer your-hardcover-api-token
GOOGLE_BOOKS_API_KEY=your-google-books-api-key
EUROPEANA_API_KEY=your-europeana-api-keyWith these keys, Google Books and Europeana results are also queried alongside
the other selected sources. Library of Congress and Gutendex run without keys. Gutendex covers
Project Gutenberg's literature catalog, including multiple languages, and is
not a current commercial-book catalog. Google Books and Europeana are skipped
when their keys are absent. To keep only the default public catalogs, set
BOOKSHELF_METADATA_SOURCES=loc,gutendex,openlibrary; to disable all catalog
searches, set
BOOKSHELF_METADATA_SOURCES=.
Open Library can be enabled in Settings > Metadata > Runtime Catalog
Sources. It uses its public Search, Work, Edition, and Author APIs. Requests
identify BookshelfNG with its User-Agent, are paced to one per second, and are
cached for one day. Add a contact email in the same settings page or set
OPEN_LIBRARY_CONTACT_EMAIL so Open Library can identify the installation.
Open Library Work IDs and Author IDs stay namespaced in BookshelfNG, and its
edition mapping validates and normalizes ISBN-10 values to ISBN-13. Covers are
loaded from Open Library's Covers API when available. Read Open Library's
API usage policy,
Search API, and
Covers API documentation.
Internet Archive searches its text collection and resolves records by stable item identifier. Catalog records and edition metadata vary, so treat it as an optional fallback. NDL Search adds Japanese and partner-library metadata; it does not provide artwork because NDL ended its thumbnail service on March 31, 2026. It is opt-in because requests are paced to one per second and usage conditions vary by provider. Operators must show NDL Search API credit and check the provider's licensing/application requirements, especially for commercial or continuous use. See NDL's thumbnail service notice.
To add a Goodreads-compatible Apify Actor:
# Include only the providers you want; use metadata-api instead of hardcover
# when the Readarr-compatible metadata API should be searched.
BOOKSHELF_METADATA_SOURCES=hardcover,googlebooks,loc,gutendex,internetarchive,ndl,europeana,apify-goodreads
HARDCOVER_APIFY_GOODREADS_ACTOR=publisher~goodreads-scraper
HARDCOVER_APIFY_TOKEN=your-apify-token
# Override only when the Actor does not use searchQueries and maxItems:
HARDCOVER_APIFY_GOODREADS_INPUT_TEMPLATE={"searchQueries":[{{query}}],"maxItems":10}Google Books public searches require a Google API key; user OAuth is not
needed. Europeana requires a free key from a registered account and searches
text records with open reuse status. It is a cultural heritage index rather
than a complete current-book catalog, and per-record metadata and cover
availability vary. See Europeana's Search API documentation,
Record API documentation,
and API key registration. Library of
Congress search is public and rate limited. Requests are paced to one per 3.2
seconds per Bookshelf process and successful responses are cached for one day.
If multiple Bookshelf processes share an outbound IP, set a source list that
avoids querying LOC from every process. The optional Apify adapter runs a
user-selected Actor, whose schema, availability, terms, and pricing are
controlled by its publisher. The default Actor input is
{"searchQueries":[{{query}}],"maxItems":10}; a custom JSON template must
include the literal {{query}} placeholder, which Bookshelf replaces with a
JSON-escaped search string. Actor output is normalized from common Goodreads
scraper fields, and results missing a title or author are skipped.
Results from alternate providers receive a namespaced foreign ID such as
hardcover:123, metadata-api:123, openlibrary:OL...W,
googlebooks:volume-id, loc:<encoded-record-url>,
europeana:<encoded-record-id>, or apify-goodreads:<encoded-record-key>.
Bookshelf uses those same IDs for subsequent book and author metadata lookups;
it does not coerce them into numeric Goodreads IDs. The selected provider
names and credentials must remain
available when the library is refreshed. Search results are cached for 10
minutes; Open Library, Google Books, LOC, and Europeana responses and Apify
result sets are cached for one day. Provider failures are logged independently;
other configured sources continue to return results.
The source checkboxes and optional credentials are managed separately by each
BookshelfNG instance. If you choose to run separate ebook and audiobook
instances, configure each in its own Settings > Metadata page.
HARDCOVER_NATIVE,
METADATA_URL, and HARDCOVER_API_URL still select deployment mode or an API
endpoint and remain environment-level settings. SeerrNG's Settings >
Metadata page explains this boundary; its TMDB/TVDB selectors control video
metadata, not BookshelfNG catalogs. One-off SeerrNG migration-recovery adapters
also keep their own environment settings because they run outside BookshelfNG's
normal search process.
The source setting applies to the hardcover and softcover images. It does
not rewrite IDs already stored in the library, and it does not combine remote
catalog records into Hardcover itself.
The softcover image is intended for Goodreads-compatible metadata and
existing Readarr/softcover databases. Goodreads and Hardcover use different
foreign author, book, and edition IDs; those IDs cannot be converted by
changing an image tag or metadata URL.
BookshelfNG also supports the Readarr-compatible metadata API through
METADATA_URL. Use a hosted service such as rreading-glasses, preserve an
existing proxy or cache, or run your own compatible endpoint. In the
hardcover image, set HARDCOVER_NATIVE=false to select this compatibility
path instead of direct Hardcover GraphQL access. The choice is explicit, so
you can see which service is handling metadata requests.
METADATA_URL is a compatibility boundary, not an automatic multi-provider
aggregator. It can point to a service that itself translates or combines
providers, but BookshelfNG expects that service to return stable IDs and
compatible detail responses. Goodreads work and edition IDs, Hardcover IDs,
Google Books volume IDs, Open Library keys, and LOC identifiers are not
interchangeable. The optional runtime catalogs documented above provide
parallel search results and provider-specific detail lookups; they do not
rewrite IDs already stored in the library or silently replace a failed primary
provider.
Do not switch an existing Goodreads/softcover database to Hardcover by changing
only the image tag or METADATA_URL. The two providers' foreign IDs are not
portable, and a direct switch can leave existing authors, books, and editions
that Hardcover cannot resolve.
Back up the ebook and audiobook configuration directories before migrating.
SeerrNG includes a migration helper that can inventory the source database,
rebuild strict matches against a temporary Hardcover BookshelfNG target, and
optionally use a softcover endpoint to recover metadata for stale IDs. Its
deterministic local database fallback can preserve books that Hardcover still
cannot import. Those fallback entries, such as local:ebook:1076, are local
Bookshelf records rather than native Hardcover records.
SeerrNG's migration helper can additionally search Google Books and the Library of Congress and can optionally call a user-selected Apify Actor that scrapes Goodreads-compatible catalogs. These sources are used to recover candidate metadata and attempt strict remapping to Hardcover. Unmatched metadata can enrich the optional local fallback. This tooling does not add Google Books, LOC, or Apify results to BookshelfNG's ordinary search/detail flows. Apify Actors are third-party services with Actor-specific schemas and potential charges; Goodreads does not issue new public developer API keys.
SeerrNG can connect to BookshelfNG as a Readarr-compatible ebook or audiobook service. That integration is optional; BookshelfNG can monitor, download, and manage a library without SeerrNG.
Use one BookshelfNG instance and its existing database for both SeerrNG service
entries. New installations require Forms authentication for the web interface;
SeerrNG should use an API key in the X-Api-Key header. Legacy Readarr clients
that send ?apikey= remain supported; set BOOKSHELF_ALLOW_API_KEY_QUERY=false
to require header credentials. To give SeerrNG a
separate restricted key, set BOOKSHELF_SEERRNG_API_KEY from a Docker/Kubernetes
secret. That credential can read library/search/profile/root-folder data and
add or update authors and books, but it cannot change system settings, reset
the administrator key, or run arbitrary commands. Replace the secret and
restart BookshelfNG to rotate it. Existing global API keys continue to work.
BookshelfNG advertises a versioned SeerrNG capability contract and accepts the
format-scoped routes /readarr/{gr|hc}/ebook/api/v1 and
/readarr/{gr|hc}/audiobook/api/v1, where the dialect matches the configured
metadata provider. Both routes use the same BookshelfNG library and
database; a second instance or a database merge is not required. See the
SeerrNG integration and security guide for
trusted proxy, allowed-origin, API credential, and upgrade details.
For compatible book-add requests, BookshelfNG's
/api/v1/book/lookup response includes nested author and edition metadata when
it can resolve the requested book. Use the softcover image when retaining a
Readarr-compatible Goodreads database, or use the Hardcover migration process
above when moving to Hardcover metadata.
GitHub Actions publishes these rolling and versioned container tags:
softcoverandsoftcover-v<release-version>for the Readarr-compatible metadata modehardcover,latest, andhardcover-v<release-version>for native Hardcover mode
Tagged v* builds also publish a GitHub Release with curated release
notes, platform archives, the Windows x64 setup installer, checksums, and native
Linux packages, then announce the release to Discord. The AUR, COPR, PPA,
Chocolatey, and Helm channels use the same verified tag flow. External
stores require publisher credentials and repository registration. The Flatpak is
attached as a GitHub Release bundle and is not published to Flathub. See the
distribution setup and publisher requirements for
channel details. Pull requests require a release-note fragment for user-facing
changes; internal-only work must be marked release-note: none. See
release-notes/README.md for the format and
preview command.
If an anonymous pull returns denied, the GHCR package may not be public yet;
you can also authenticate with package read access.
- Documentation index
- OpenID Connect sign-in: provider setup, callbacks, allow-lists, and recovery · shared provider catalog
- Fork feature inventory, upstream comparison, and compatibility boundaries
- Import matching and multiple formats
- Search, direct downloads, torrent adoption, and queue workflows
- Audiobook narrator tags and Audiobookshelf sidecars
- BookLore import uploads
- Series pack search
- Optional audiobook M4B merging
- Metadata providers and configuration
- Moving an existing library to Hardcover
- Author metadata storage, refresh policy, and troubleshooting
- Reporting issues and collecting useful logs
- .NET 10 source builds, including the UI and Linux x86/FreeBSD packages
- Standalone installation and platform support
- Release distribution channels and publisher setup
- Optional diagnostics module
- Release-note format and preview
- SeerrNG migration metadata source matrix
Please file a GitHub issue or start a discussion for help. Contributions are welcome, especially fixes and quality-of-life improvements.
After cloning, maintainers can run scripts/install-package-sync-hook.sh to
install the post-commit and pre-push Unraid sync hooks. Commits on main, and
pushes targeting main, sync the full application source and Unraid package to
the companion repository; a failed sync blocks the push. Syncs use a clean
temporary worktree and leave other companion checkouts untouched. GitHub
workflows verify the Unraid package before release. Missing package sources or
the companion checkout are errors. Set BOOKSHELFNG_UNRAID_REPO if that
checkout is outside the sibling-repository layout.
BookshelfNG no longer maintains, publishes, or updates a YunoHost package. Existing installations remain on their last published version; operators should move to a supported deployment or maintain their own package updates.
The standard BookshelfNG image sends no analytics or exception reports. An optional module can report aggregated application-start, book-grab, book-import, and download-failure counts to an OTLP collector you configure. It requires the module assembly, an explicit enable flag, an HTTPS endpoint, and a bearer token. It sends no book or author metadata, paths, search terms, log messages, exception details, or persistent installation identifier. The collector can still see the source IP address of the HTTPS request. See the diagnostics module instructions for the data schema and installation steps.
BookshelfNG is derived from Bookshelf, a revival of Readarr, and Prowlarr. Those projects are licensed under GPLv3, and BookshelfNG is distributed under the terms of GPLv3. See LICENSE.
BookshelfNG is maintained as a fork because its standalone library model and SeerrNG integration go beyond the current Bookshelf parent API. The upstream Bookshelf README describes one type of a book per instance; BookshelfNG can keep ebooks and audiobooks on the same book in one database, and exposes format-specific availability and restricted SeerrNG access. Its parent is reviewed in the capability and compatibility guide, which records what is shared, what this fork maintains, and what would need to be available before SeerrNG could replace it.
Copyright 2025–2026.
Run scripts/security-scan-local.sh for local Semgrep Community Edition and applicable Trivy scans. Public GitHub Actions workflows run these scans on changes and weekly, alongside any existing CodeQL workflow. See docs/security-scanning.md for offline setup and updates. Run scripts/install-security-hooks.sh once to enable the staged Semgrep pre-commit hook.