Releases: mavrovde/bookvault
Release list
v1.2.0 — Linux installer (AppImage)
Adds a Linux AppImage, completing the desktop trio (macOS / Windows / Linux).
Built with PyInstaller + appimagetool on an ubuntu-latest runner, with a
headless smoke test (xvfb) that boots the frozen app to prove the GTK/WebKit
binding works, then attaches the .AppImage to each release.
Added
- Linux
.AppImage.chmod +xand run it. It bundles the app + the gi
bindings/typelib; WebKitGTK 4.1 is a host runtime dependency (WebKit's
multiprocess helpers use compile-time absolute paths that can't live inside an
AppImage) — oneaptline covers it on Ubuntu 24.04+
(libwebkit2gtk-4.1-0 gir1.2-webkit2-4.1 gir1.2-gtk-3.0). Chromium is fetched
on first run; app data lives in~/.local/share/BookVault/. - CI (
.github/workflows/desktop-linux.yml) builds + smoke-tests the AppImage on
ubuntu-lateston every tag and attaches it to the GitHub Release.
v1.1.0 — Windows installer (Setup.exe)
Adds a native Windows installer, built the same way as macOS: a PyInstaller
onedir app wrapped by Inno Setup into Setup.exe, with Chromium fetched on first
run. Built on a windows-latest CI runner and attached to each release.
Added
- Windows
Setup.exe. Download it from the release and run it (unsigned, so
SmartScreen → More info → Run anyway); BookVault installs to Program Files
with a Start-menu shortcut. Requires the WebView2 runtime (present on Windows
11 and up-to-date Windows 10). App data lives in%LOCALAPPDATA%\BookVault;
Chromium caches in%LOCALAPPDATA%\ms-playwright(shared, survives reinstall). - CI (
.github/workflows/desktop-windows.yml) buildsSetup.exeon
windows-lateston every tag and attaches it to the GitHub Release, and runs
as a build check on PRs touching the Windows packaging.
v1.0.1 — Fix: macOS app couldn't launch its browser
The downloadable macOS app failed at login with an "Internal server error".
Inside a frozen .app, Playwright resolved Chromium to a path inside the
read-only bundle and could neither install nor launch it, so every login died at
chromium.launch(). Fixed by pinning the browser cache (and the app's data dir)
to the standard writable per-OS locations.
Fixed
- Desktop app login on the packaged macOS build.
chromium.launch()failed
withExecutable doesn't exist at …/BookVault.app/…/.local-browsers/…because
a frozen Playwright defaults its browsers path relative to the (read-only)
bundle. The launcher now setsPLAYWRIGHT_BROWSERS_PATHto the standard
~/Library/Caches/ms-playwrightcache — writable, persistent, and shared with
any normal Playwright install on the machine.
Changed
- The frozen entry point moved to a single cross-platform
packaging/entry.py
(per-user data dir + browsers path chosen by OS), shared by all packaged
builds.
v1.0.0 — BookVault 1.0: now a native desktop app, too
BookVault reaches 1.0 with a third way to run it: a native desktop app for
macOS, Windows, and Linux, alongside the local web app and the MCP server. All
three are front-ends over the same backend -- the desktop app embeds the exact
bookvault-web server and shows it in a native window, with no browser tab or
terminal needed.
Added
-
bookvault-desktop-- a native desktop app. A
pywebview shell that starts the FastAPI web
app on a private127.0.0.1port in a background thread and shows it in a
native OS window (WKWebView on macOS, WebView2 on Windows, WebKitGTK on
Linux). It reusesbookvault-webverbatim -- the backend is imported, not
duplicated -- so the web app, the MCP server, and their Docker images are
unchanged. A splash is shown while a saved session restores (which drives a
real headless Chromium), then the live app loads; closing the window cleanly
stops the backend and the Playwright/Chromium session (bounded graceful
shutdown, so the browser is never orphaned)..venv/bin/pip install -e ./core -e ./web -e ./desktop .venv/bin/bookvault-desktop
Notes
- The desktop app currently runs from a source checkout; packaged installers
(.dmg/.msi/.AppImage) and package-manager channels (Homebrew /
winget / AUR) are the next step. tests/test_desktop.pyskips itself unless thedesktoppackage is
installed, so the released web/MCP CI is unaffected.
v0.12.0 — Shared state across browsers, a results view, and your name in the header
The web app's selection and format choices now live on the server, so every
browser, tab, and device pointed at the app shows the same ticked books, the
same formats, and the same live progress. The header shows your account
email/name instead of a generic "Signed in", and a new results view makes a
failed download easy to find among hundreds of successes.
Added
- Server-side shared UI state. Which books are selected and your preferred
ebook/audiobook formats now live on the backend (GET/POST /prefs, and
folded into the/activitypoll every browser already makes) instead of each
browser'slocalStorage/sessionStorage. Open the app in a second browser
mid-download and it shows the same selection and progress. Persisted to
LITRES_STATE_FILE(defaults onto the Docker/datavolume), so it also
survives a restart. - Account identity in the header. A cookie-only session (e.g. in Docker,
where there's no OS keychain to remember the login name) now recovers your
email/login from litres.ru's/users/me, so the header shows who you are
rather than a generic "Signed in". - Results view with a status filter. After a build, a summary shows
All N · ✓ done · ! skipped · ✗ failedas clickable pills -- one click
filters the log to just the failures, so a single rights-limited title no
longer hides among hundreds of successes. - End-to-end / smoke tests. An offline e2e suite (real server boot + full
login → build → download flow + the MCP tool flow) plus an opt-in
pytest -m livesuite that smoke-tests a running instance.
Fixed
- The results and the download link survive a page reload. The cache-only
size-check that runs on every page load used to wipe the finished build's
per-book results and its zip download link. Both are now kept until the
next build starts, so you can reload to inspect failures and still download
the zip. - A build where every selected title failed no longer offers an empty zip.
Changed
- New
LITRES_STATE_FILEsetting (default.litres_state.json;/data/...
in Docker) holds the shared UI state; it's git-ignored like the session and
cache files.
0.11.1 — Faster release builds
Patch release: the Docker publish workflow now uses a registry-backed build cache (a per-image buildcache tag in GHCR) instead of the per-ref GitHub Actions cache, so releases reuse unchanged layers (the ~2.5GB Playwright base + dependency install) instead of rebuilding from scratch. CI-only change — no application code. This first run populates the cache; the next release will be noticeably faster.
Full notes: CHANGELOG.md.
0.11.0 — Renamed to BookVault
The project is now BookVault — own the books you bought. Renamed so the identity no longer leads with a third-party trademark, with clear non-affiliation notices.
Changed (breaking)
- Renamed the whole product identity: repo →
mavrovde/bookvault; distributions →bookvault-core/-web/-mcp; modules →bookvault_core/_web/_mcp; commands →bookvault-web/bookvault-mcp; Docker images →ghcr.io/mavrovde/bookvault/{web,mcp}; OS-keychain + MCP server id →bookvault. - Kept as nominative references to the litres.ru service: the
LITRES_*env vars, theLitresClientclass, litres.ru URLs, and the.litres_session.json/.litres_cache.jsonfiles.
Added
TRADEMARKS.md+ non-affiliation notices in README, MCP README, and LICENSE. "LitRes"/"ЛитРес"/"litres.ru" are trademarks of ООО «ЛитРес»; BookVault is independent and unofficial, uses the name only nominatively, and uses none of LitRes's logos/branding. Links to the official LitRes sites included.- LICENSE now states it covers this project's own code only and grants no trademark rights.
Migration
pip install -e ./core -e ./web -e ./mcp # reinstall renamed packages
bookvault-web # was: litres-web
docker pull ghcr.io/mavrovde/bookvault/web:0.11.0If the web app shows logged-out after upgrading (the keychain service id changed), just log in once more.
Full notes: CHANGELOG.md.
0.10.1 — Multi-arch Docker images
Patch release fixing the Docker images published in 0.10.0.
Fixed
- Images are now multi-arch (
linux/amd64+linux/arm64). 0.10.0 built amd64 only, sodocker pull/docker compose upfailed on Apple Silicon (arm64) withno matching manifest for linux/arm64. The publish workflow now sets up QEMU and builds both, soghcr.io/mavrovde/litres-assistant/{web,mcp}run natively on Intel and Apple Silicon.
Changed
- Bumped the publish workflow's docker actions to their Node 24 releases (
build-push-action@v7,login-action@v4,metadata-action@v6,setup-buildx-action@v4,setup-qemu-action@v4), clearing the "Node.js 20 is deprecated" warnings.
No application code changed since 0.10.0.
0.10.0 — Docker images (web + MCP)
Both entry points now ship as container images, and docker compose up -d starts and controls both.
Two images (Playwright base, Chromium included), published to GHCR with this release, tagged 0.10.0 + latest:
ghcr.io/mavrovde/litres-assistant/webghcr.io/mavrovde/litres-assistant/mcp
Added
docker-compose.ymlruns both services sharing one named volume (/data) — logging in via the web app authenticates the MCP server too (shared session cookies); cache + downloads persist. Ports publish to127.0.0.1only, preserving the localhost-only design.- MCP
streamable-httptransport (LITRES_MCP_TRANSPORT) so the container runs a long-lived networked MCP service Compose can control (http://127.0.0.1:8421/mcp). Stdio stays the default for direct/Claude-Desktop use. - CI workflow builds + pushes both images on every
v*tag. - New env vars:
LITRES_APP_HOST,LITRES_RELOAD,LITRES_MCP_TRANSPORT,LITRES_MCP_HOST,LITRES_MCP_PORT. - LICENSE — MIT with an attribution requirement (credit the author + link the source).
Changed
credentialsdegrades gracefully with no OS keychain (headless container): falls back to session-only instead of crashing login. No password written to the container — the saved session (on the volume) keeps you logged in; re-login via the web form once it lapses.- README overhaul — TOC, badges, features, clearer quick-starts, Docker guide, and a Legal & fair use section (personal backups of fairly-bought books only; no DRM circumvention, no redistribution).
Quick start
git clone https://github.com/mavrovde/litres-assistant.git
cd litres-assistant && docker compose up -d
# open http://127.0.0.1:8420Full notes: CHANGELOG.md.
0.9.0 — Don't provoke DDoS-Guard
Makes this low-volume personal backup tool behave like one, so it stops tripping DDoS-Guard's false-positive checks. Diagnosed and hardened from real block logs.
Fixed
- Downloads carry the browser's TLS fingerprint. Downloads must stream (audiobook bundles ~2GB) over a separate client from the Chromium API calls; plain
httpxhas a Python JA3/JA4 that can be re-challenged even with valid__ddg*cookies.download_filenow streams viacurl_cffiimpersonating Chrome (measured: JA3 + JA4 both differ from httpx; negotiates HTTP/2 like Chrome). Falls back tohttpxif unavailable. - Auto-fallback to the subscription download endpoint. litres serves purchases from
download_bookand subscription/abonement titles fromdownload_book_subscr. On a plain (non-anti-bot) 403 the client now tries the other endpoint automatically before giving up — so subscription titles that used to fail just download.
Added
- Retry with backoff + cookie re-warm on transient blocks (DDoS-Guard 403 / 429 / 503): honor
Retry-After, jittered exponential backoff, re-warm__ddg*cookies via a page visit, retry — for downloads and API GETs. Interruptible by Stop. Genuine rights-403s aren't retried. - Instrumentation: failures log the response
Serverheader, so an anti-bot block is distinguishable from a litres app error. - New env vars:
LITRES_MAX_RETRIES,LITRES_RETRY_BASE_DELAY,LITRES_RETRY_MAX_DELAY.
Changed
- Opening the app no longer sweeps every book's size — the on-load sweep is cache-only (zero litres.ru calls); live size fetches happen only on explicit Refresh.
- Jittered pacing between live fetches and library pages.
- Honest failure messages: persistent anti-bot block → "wait a few minutes"; both endpoints 403 → likely subscription-only/region-locked/preview-only (no more "retry this book").
Full notes: see CHANGELOG.md.