Sync reading sessions from your Kobo e-reader to your Grimmory instance.
Kobo tracks reading sessions in its AnalyticsEvents table, but this data gets wiped every time the device syncs online.
This tool:
- Installs a trigger to preserve the data
- Extracts reading sessions (pairing OpenContent/LeaveContent events)
- Syncs them to Grimmory's
/api/v1/reading-sessionsendpoint
bundle installThe PrivacyPermissions field in the user-table of the Kobo database (at .kobo/KoboReader.sqlite) must be populated — if it's empty, no reading events will be recorded.
It's a bit unclear what exactly causes the analytics tracking to not be enabled, but after several reset-setup-flows the following worked:
- Visit https://www.kobo.com/ and be sure to accept all cookies
- Create an account
Be sure to pick the country where you'd want to buy content from. This can differ from the country the site detects. - Reset the Kobo
This starts the activation flow. It can be done by signing out (More > Settings > Accounts).
NOTE: notes and bookmarks are lost. - Activate
You'll be asked to connect wifi. Then you'll be shown a page with a QR-code and activation code.
Visit https://kobo.com/activate and fill out the activation code. This ties the device to the online account. - Connect your Kobo to your computer
Confirm connecting on the device. - Verify analytics are enabled
The following installs a trigger to prevent theAnalyticsEventstable from being cleared on sync, and verifies that analytics tracking is enabled on the device.rake kobo:setup
This is how you receive your books from your Grimmory instance - it's not strictly necessary for syncing the analytics data.
NOTE: Setting this doesn't prevent you from buying books from the official Kobo store (or using Kobo plus).
- Grimmory: Grab your Kobo sync token
On your Grimmory instance: VisitSettings > Devices, ensureEnable Kobo Syncis enabled and copy the token. - Kobo: Set the api_endpoint
In.kobo/Kobo/Kobo eReader.conf, setapi_endpoint=https://grimmory-instance.org/api/kobo/<token>.
On OSX:$EDITOR /Volumes/KOBOeReader/.kobo/Kobo/Kobo\ eReader.conf
rake grimmory:configureEnter your Grimmory URL, username, and password. Credentials are stored in ~/.kobo-sync/state.db.
rake automation:installThis installs a launchd agent that automatically syncs when you mount your Kobo. You'll get a macOS notification when sync completes.
See Usage below for manual sync.
rake sync:runrake sync:previewrake sync:statsThe automation uses macOS launchd to watch for Kobo mount events.
rake automation:install # Install auto-sync on mount
rake automation:uninstall # Remove auto-sync
rake automation:status # Check if automation is running
rake automation:logs # View sync logsWhen installed, the workflow is simply:
- Plug in your Kobo
- Reading sessions sync automatically
- You get a notification when done
Reading sessions for books not found in Grimmory (404) are handled with a fallback mechanism. This includes Instapaper articles synced to your Kobo, which generate reading events but aren't in your Grimmory library.
- Upload
support/uncategorized-reading.epubto Grimmory and note its book ID - Run
rake grimmory:configureand set the Default book ID to that ID
Sessions that would otherwise be lost now get assigned to this catch-all book. They're marked as fallback sessions internally.
If you need to delete and re-upload the catch-all book (e.g. to change the cover):
- Delete the old book in Grimmory
- Upload the new EPUB, note the new book ID
- Run
rake grimmory:configureand update the default book ID - Run
rake sync:reset_unknownsto clear fallback sessions - Run
rake sync:runto re-sync them to the new book
Sessions shorter than min_session_seconds (default: 60) are filtered out in both sync:preview and sync:run to skip accidental book opens. Configure via rake grimmory:configure.
- Local state stored in
~/.kobo-sync/state.db - Tracks which Kobo event IDs have been synced
- Re-running
sync:runonly sends new sessions - Use
sync:resetto clear the sync state if needed
rake kobo:check # Check if Kobo is mounted
rake kobo:setup # Set up Kobo for syncing (install trigger, check analytics)
rake kobo:install_trigger # Install trigger to preserve AnalyticsEvents data
rake kobo:remove_trigger # Remove the PreserveAnalyticsEvents trigger
rake kobo:schema # Show AnalyticsEvents table schema
rake kobo:triggers # Show installed triggers
rake grimmory:configure # Configure Grimmory API connection
rake grimmory:config # Show current configuration
rake sync:preview # Show reading sessions that would be synced (dry run)
rake sync:run # Sync reading sessions to Grimmory
rake sync:stats # Show sync statistics
rake sync:reset # Reset sync state (mark all sessions as not synced)
rake sync:reset_unknowns # Reset unknown/fallback sessions so they sync again
rake automation:install # Install launchd agent to auto-sync when Kobo is mounted
rake automation:uninstall # Uninstall the launchd agent
rake automation:status # Check automation status
rake automation:logs # Show automation logs
~/.kobo-sync/
├── state.db # Sync state and credentials
├── sync.log # Automation logs
└── sync-on-mount.sh # Installed sync script
~/Library/LaunchAgents/
└── com.kobo-sync.plist # launchd agent (when automation installed)
Kobo AnalyticsEvents
↓
OpenContent event (start reading)
LeaveContent event (stop reading, has SecondsRead)
↓
Paired into reading session
↓
POST /api/v1/reading-sessions
{
bookId, bookType,
startTime, endTime, durationSeconds,
startProgress, endProgress, progressDelta,
startLocation, endLocation
}