Making the files portable¶
Every other comic reader — Komga, Kavita, ComicRack, YACReader, Chunky, Panels —
reads ComicInfo.xml from inside the archive. None of them has a library-import
format; they scan directories. So the way to move a library elsewhere is to make
the files describe themselves, and then point the other application at them.
Write metadata to file on a comic's page does that: it rebuilds the CBZ with
a ComicInfo.xml carrying everything Longbox knows. In bulk:
python -m app.cli tag --dry-run # see what would be written
python -m app.cli tag
Reading state, favourites and your own rating are deliberately not written. They belong to an account, not to a file that may be copied or shared.
Converting CBR to CBZ¶
python -m app.cli convert --dry-run
python -m app.cli convert
Worth doing regardless of portability. RAR is proprietary: it needs unar
installed on the server, cannot be written to at all (so CBR files can never be
tagged), and is slower to seek. The images inside are identical either way —
conversion copies each one across byte for byte, with no re-encoding.
Originals are kept unless you pass --delete-original, so a rescan will find
them again until you remove them.
How the rewriting is done¶
Both operations are careful with files you own:
- Never in place. A new archive is built beside the original, opened, and compared page by page against what went in. Only then is it moved over the top. A crash halfway leaves the original untouched.
- Never lossy. Images are copied between containers unchanged — never re-encoded, resized or recompressed. They are stored rather than deflated in the new zip, since they are already compressed.
- Nothing left stale. The stored size, both hashes and any cached pages are
refreshed, so a
verifyrun stays clean and the reader cannot serve pages from the file that used to be there.
PDF and EPUB are refused rather than half-handled: neither carries
ComicInfo.xml, and converting them would mean re-encoding every page.
On the Docker deployment the comics volume is mounted read-only, which is the right default for a catalogue but blocks both of these. Remount it read-write if you want to use them, and take a backup first.
CBR files need a RAR tool¶
RAR is a proprietary format and Python cannot unpack it alone, so a CBR is
opened by trying several tools in order until one works: 7-Zip first (the
most dependable RAR5 reader), then the rarfile package via unar/unrar,
then bsdtar. The Docker image installs unar, which handles both RAR4 and
RAR5 on its own — 7-Zip is not required there. On a bare-metal install:
sudo apt install unar
Installing 7-Zip (p7zip-full on Debian/Ubuntu) as well is not required but
is not wasted either: it becomes the first thing tried, and a file one tool
struggles with still has two more chances rather than one. Without any of
these, CBRs fail to import with a message naming what was tried and why each
failed, rather than failing silently. Everything else needs no external
tools.
CB7 needs no external binary either: py7zr is tried first (it is in
requirements.txt), with the 7-Zip CLI as a fallback if that fails. It is
worth knowing that 7-Zip is a solid format: entries share one compression
stream, so pulling out a single page costs nearly as much as pulling out all
of them. Longbox therefore expands a CB7 once, on first read, into a
temporary directory that lasts as long as the file is open — to disk rather
than memory, since a long comic runs to hundreds of megabytes. Converting CB7
to CBZ removes that cost permanently, and the images are copied across
untouched.
PDF support needs pymupdf, which is in requirements.txt but has no wheel for
Python 3.14 yet. On 3.14 the app still runs; PDFs import without covers or page
counts. Python 3.12 gets full PDF support.