From Mobile Scans to AI-Queried Library: Syncing Android Book Catalogue with Obsidian and Antigravity

By | November 7, 2026

For book lovers and physical media collectors, cataloging an extensive physical library is a rite of passage. But having cataloged hundreds or thousands of books, where does that data live?

All too often, personal collections get locked into siloed smartphone apps or proprietary walled gardens like Goodreads. You can scan barcodes on your phone, but querying your collection from your terminal, connecting book themes to your personal notes in Obsidian, or asking an AI assistant questions like “Do I own any sci-fi books featuring dinosaurs or paleontology?” remains impossible.

To fix this, I set out to build a clean, bidirectional pipeline between Book Catalogue (the veteran, open-source Android book organizer) and my local knowledge base in Obsidian, connected to my local terminal coding assistant, Google Antigravity (agy).

With over 1,076 physical books in my collection, here is the complete architecture, the real-world edge cases (especially Android FAT/exFAT filesystem clashes), and how my local agent continuously ingests new mobile backup dumps into interactive Markdown notes.


1. The Architecture: Mobile Barcodes to Local AI Mind

The pipeline connects three core realms:

  1. The Mobile Layer (Android): Rapid barcode scanning, bookshelf tagging, reading status, and ratings on the go using the open-source Book Catalogue app.
  2. The Sync & Ingestion Engine (sync_book_catalogue.py): An idempotent Python pipeline that unpacks mobile .bcbk backup archives, sanitizes book titles for multi-platform sync, fetches missing cover art from Open Library, and generates structured YAML frontmatter.
  3. The Obsidian & Agent Layer (agy): A searchable library of individual Markdown notes equipped with Dataview indices, queried in sub-second time by Antigravity via Omnisearch.

2. Why Book Catalogue on Android?

Before diving into the pipeline, it’s worth highlighting why Book Catalogue (book-catalogue.com, package com.eleybourn.bookcatalogue) remains an exceptional companion for self-hosters and privacy enthusiasts:

  • 100% Free & Open-Source: Available directly on Google Play and open-source repositories with zero ads, tracking, or mandatory cloud logins.
  • Rapid Multi-Source Barcode Scanning: Uses the camera to scan ISBN barcodes and instantly fetches metadata from Google Books, Goodreads, Open Library, Amazon, and LibraryThing.
  • Full Local Data Ownership: Offers both standard CSV exports and complete application backup archives (.bcbk format).
  • Deep Metadata Support: Tracks bookshelves (e.g. Default, to-read, read, custom shelf locations), ratings, publication years, publishers, formats (Hardcover, Paperback), anthologies, and loaned books.

When I trigger a backup in Book Catalogue, it saves an archive named BookCatalogue-YYYY-MM-DD.bcbk into my shared mobile storage.


3. Dissecting the Mobile Backup Format (.bcbk)

At first glance, a .bcbk file looks like a proprietary Android binary blob. However, inspecting it reveals standard UNIX tooling:

$ file BookCatalogue-2026-11-07.bcbk
BookCatalogue-2026-11-07.bcbk: POSIX tar archive

A .bcbk file is simply an uncompressed POSIX tar archive. Inside it resides:

  • INFO.xml: Archive metadata (total books, number of bundled covers, app version, Android SDK).
  • books.csv: The complete relational database export containing 29 columns of book attributes.
  • *.jpg: Locally cached cover images named after each book’s internal book_uuid (e.g. 1f0f91f000bf07352796dad227429d75.jpg).
  • preferences: Serialized Android app settings.

Because my mobile Obsidian vault folder (Documents/Obsidian/03-Resources/Books/) is kept in perpetual peer-to-peer sync with my Linux laptop using Syncthing and Tailscale, dumping a backup in the Android app lands the .bcbk file directly onto my workstation within seconds.


4. The Engineering Challenges: Filesystems & Cover Art

Building an automated pipeline from mobile export to Obsidian notes revealed two critical challenges that every developer will face when syncing between Linux and mobile devices.

Challenge 1: The Android Illegal Filename Trap (EINVAL)

On a Linux workstation running ext4, Btrfs, or ZFS, note titles can contain almost any character except /. Many book titles contain colons or question marks:

# Example invalid titles for Android:
"Nothing: From Absolute Zero to Cosmic Oblivion"
"What If?: Serious Scientific Answers to Absurd Hypothetical Questions"
"Pushing the Frontiers: Towards Faster Payments"

If your ingestion script writes a Markdown note named Author - Title: Subtitle.md on your laptop, Syncthing will immediately crash on Android with an EINVAL (Invalid Argument) I/O error. The Android storage layer (emulated FAT/exFAT/FUSE) strictly prohibits:

  • Colon (:)
  • Question mark (?)
  • Asterisk (*)
  • Pipe (|)
  • Double quotes (")
  • Angle brackets (<, >)

To prevent sync collisions across the entire fleet, the ingestion tool implements strict filename sanitation:

def clean_android_filename(text: str, max_len: int = 150) -> str:
    """Sanitize string to prevent Android FAT/exFAT sync errors."""
    clean = re.sub(r'[:/\\|]', ' - ', text)
    clean = re.sub(r'[*?"&lt;>]', '', clean)
    clean = re.sub(r'\s+', ' ', clean)
    clean = re.sub(r'\s*-\s*-\s*', ' - ', clean)
    clean = clean.strip(' .-')
    if len(clean) > max_len:
        clean = clean[:max_len].rstrip(' .-')
    return clean or "Untitled"

Colons and slashes are cleanly converted to hyphen separators (" - "), and dangerous characters are stripped. The result is 100% clean cross-device synchronization.

Challenge 2: The Missing Covers Conundrum

In Book Catalogue, to keep export file sizes compact and fast, the mobile app often bundles only recently cached thumbnail covers into the quick backup archive. In my export of 1,076 books, only 7 covers were bundled inside the .bcbk tar:

&lt;item name="NumBooks" type="Int">1076&lt;/item>
&lt;item name="NumCovers" type="Int">7&lt;/item>

Rather than manually downloading over a thousand book covers, we automated it. Since over 92% of the catalog had valid ISBNs, the script implements an automated fallback cover fetcher (--fetch-covers) querying Open Library:

def fetch_openlibrary_covers(isbns_map: dict, covers_dir: Path):
    """Batch-queries Open Library books API (50 ISBNs per request)."""
    # Batches ISBN:XXXXXXXXX queries to https://openlibrary.org/api/books
    # Converts ISBN-10 to ISBN-13 checksums if needed
    # Downloads high-resolution cover images directly into Covers/

In a single background pass, the script queried the ISBNs and immediately populated 150+ high-resolution cover images, rendering beautiful cover previews across the vault.


5. The Ingestion Script: sync_book_catalogue.py

The core synchronization lever lives at ~/scripts/sync_book_catalogue.py. Whenever a new .bcbk archive or .csv export is detected, it executes an idempotent sync:

# Basic run: Ingests the latest backup dump and updates notes
python3 ~/scripts/sync_book_catalogue.py

# Full run: Ingests dump and fetches missing covers via Open Library
python3 ~/scripts/sync_book_catalogue.py --fetch-covers

What Each Generated Book Note Looks Like

Every book in 03-Resources/Books/Library/ is created as an individual Markdown document formatted with rich YAML frontmatter that matches Obsidian’s standard metadata types:

---
type: book
title: Toate sistemele în alertă
author: Martha Wells, Iuliana Dromereschi
isbn: '9786069000335'
publisher: Paladin
date_published: '2020-11-01'
pages: 240
rating: 5
status: read
bookshelf: Default
format: Hardcover
book_id: 1069
book_uuid: 1f0f91f000bf07352796dad227429d75
date_added: '2026-06-20 14:04:49'
tags:
- book
- literature
- sci-fi
cover: Covers/1f0f91f000bf07352796dad227429d75.jpg
---
# Toate sistemele în alertă

![[Covers/1f0f91f000bf07352796dad227429d75.jpg|260]]

## Details
- **Author**: [[Martha Wells]] (Martha Wells, Iuliana Dromereschi)
- **ISBN**: `9786069000335`
- **Publisher**: Paladin
- **Published**: 2020-11-01
- **Pages**: 240
- **Format**: Hardcover
- **Bookshelf**: Default
- **Status**: `read`
- **Rating**: ★★★★★

## Description
Ediție omnibus. Conține primele două cărți din seria Murderbot...

## Key Takeaways
1. 
2. 
3. 

## Favorite Quotes
>

Notice how the author field generates a wikilink [[Martha Wells]]. This immediately weaves the book into Obsidian’s knowledge graph, connecting it to other books by the same author, related essays, or reading logs.


6. Real-Time Browsing with Dataview

Alongside the 1,076 individual notes, the script automatically generates and updates a master catalog dashboard at 03-Resources/Books/_index.md.

Using the Dataview community plugin, this dashboard dynamically organizes the collection into real-time interactive tables:

Currently Reading & To-Read Shelf

TABLE author AS Author, bookshelf AS Bookshelf, rating AS Rating
FROM "03-Resources/Books/Library"
WHERE status = "to-read" OR bookshelf = "to-read"
SORT author ASC
LIMIT 50

Top Rated Five-Star Reads

TABLE author AS Author, rating AS Rating, status AS Status
FROM "03-Resources/Books/Library"
WHERE rating >= 4
SORT rating DESC, title ASC

7. The Antigravity (agy) Integration: AI Inquiries

The greatest benefit of bringing mobile app data into plain text Markdown inside Obsidian is that your local AI assistant inherits immediate, native access to your entire library.

Because Antigravity has access to Obsidian’s Omnisearch HTTP API and local semantic memory, I can ask complex, contextual questions directly in the terminal:

Example Terminal Interaction with agy:

> user: So any book about dinosaurs?
> agy: 
  No dedicated dinosaur or paleontology books, but there are three books in your 
  catalog that feature them or related themes:

  1. The Year's Best Science Fiction (Vol. 1 / 23rd Annual Collection) — Ed. Gardner Dozois
     * Features the Hugo-nominated story "Triceratops Summer" by Michael Swanwick, 
       about a herd of genetically engineered triceratops roaming the Vermont countryside.
  2. The Greatest Show on Earth — Richard Dawkins
     * Covers evolutionary transitions and the fossil record.
  3. Ouăle fatale. Diavoliada — Mikhail Bulgakov
     * Satirical sci-fi novella with giant irradiated prehistoric reptiles in Moscow.

The agent didn’t just match keywords; it inspected descriptions, story anthologies, and book summaries in under two seconds.

Furthermore, following our Standing Directives, the synchronization routine is codified in ~/.agents/AGENTS.md (Section 11), ensuring any future CLI session knows how to ingest new mobile backup archives automatically.


Summary & Key Takeaways

  1. Own Your Media: By extracting data from Book Catalogue (.bcbk tar archives) into Obsidian, you escape mobile silos and build a future-proof, plain-text library that will last for decades.
  2. Respect Mobile Filesystems: Always sanitize filenames (:, ?, *, |, ") before syncing Markdown notes between Linux and Android to avoid silent EINVAL sync stalls.
  3. Automate the Levers: Writing a deterministic Python bridge (sync_book_catalogue.py) that handles extraction, normalization, and API cover fetching turns a tedious chore into a zero-friction background routine.
  4. Empower Your Local Agent: Once physical assets become structured Markdown files in your vault, local assistants like Antigravity transform your library from a static catalog into an interactive, intelligent knowledge partner.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.