Automatically syncs your Audiobookshelf library with Hardcover, including reading progress, book status, and ownership information.
The project follows standard Go project layout:
.
βββ cmd/ # Main application entry points
β βββ audiobookshelf-hardcover-sync/ # Main application
βββ internal/ # Private application code
β βββ api/ # API clients
β β βββ audiobookshelf/ # Audiobookshelf API client
β β βββ hardcover/ # Hardcover API client
β βββ config/ # Configuration loading and validation
β βββ logger/ # Structured logging
β βββ models/ # Data structures
β βββ services/ # Business logic
β βββ sync/ # Sync logic
β βββ utils/ # Utility functions
βββ pkg/ # Public libraries
β βββ cache/ # Caching implementation
β βββ edition/ # Edition creation logic
β βββ mismatch/ # Mismatch detection
βββ test/ # Test files
βββ testdata/ # Test data
βββ unit/ # Unit tests
βββ integration/ # Integration tests
βββ e2e/ # End-to-end tests
- π Full Library Sync: Syncs your entire Audiobookshelf library with Hardcover
- π― Smart Status Management: Automatically sets "Want to Read", "Currently Reading", and "Read" status based on progress
- π Ownership Tracking: Marks synced books as "owned" to distinguish from wishlist items
- π Incremental Sync: Efficient state-based syncing to only process changed books
- Tracks sync state between runs
- Configurable minimum change threshold
- Persistent state storage
- π Smart Caching: Intelligent caching of author/narrator lookups with cross-role discovery
- π Enhanced Progress Detection: Uses
/api/me
endpoint for accurate finished book detection, preventing false re-read scenarios - π Periodic Sync: Configurable automatic syncing (e.g., every 10 minutes or 1 hour)
- ποΈ Manual Sync: HTTP endpoints for on-demand synchronization
- π₯ Health Monitoring: Built-in health check endpoint
- π³ Container Ready: Multi-arch Docker images (amd64, arm64)
- π Configurable Logging: JSON or console (human-readable) output with configurable log levels
- π§ Edition Creation Tools: Interactive tools for creating missing audiobook editions
- π ID Lookup: Search and verify author, narrator, and publisher IDs from Hardcover database
- π‘οΈ Production Ready: Secure, minimal, and battle-tested
- Go 1.21 or later
- Docker (optional, for containerized deployment)
- Audiobookshelf instance with API access
- Hardcover API token
-
Clone the repository:
git clone https://github.com/drallgood/audiobookshelf-hardcover-sync.git cd audiobookshelf-hardcover-sync
-
Install dependencies:
make deps
-
Create a config file:
cp config.example.yaml config.yaml # Edit config.yaml with your settings
-
Build and run the application:
make build ./bin/audiobookshelf-hardcover-sync
- Docker installed on your system
- Docker Compose (recommended for the main sync service)
- Hardcover API token
- (Optional) Audiobookshelf URL and token if using the sync service
-
Create a project directory and navigate to it:
mkdir -p ~/abs-hardcover-sync && cd ~/abs-hardcover-sync
-
Create a docker-compose.yml file:
version: '3.8' services: audiobookshelf-hardcover-sync: image: ghcr.io/drallgood/audiobookshelf-hardcover-sync:latest container_name: abs-hardcover-sync restart: unless-stopped volumes: - ./config:/app/config # For configuration files - ./data:/app/data # For persistent storage and state - ./logs:/app/logs # For log files (optional) # Optional environment variables (config file takes precedence) environment: - CONFIG_PATH=/app/config/config.yaml - LOG_LEVEL=info healthcheck: test: ["CMD", "wget", "--spider", "http://localhost:8080/health"] interval: 30s timeout: 10s retries: 3 start_period: 10s
-
Create a config directory and config.yaml file:
mkdir -p config && touch config/config.yaml
-
Add your configuration to config.yaml:
audiobookshelf: url: https://your-abs-server.com token: your_abs_token hardcover: token: your_hardcover_token sync: interval: 10m state_file: /app/data/sync_state.json logging: level: info format: json # or text for improved readability during development
-
Create data directories:
mkdir -p data logs
-
Start the service:
docker compose up -d
-
View logs:
# Follow logs docker compose logs -f # View recent logs (last 100 lines) docker compose logs --tail=100 # View logs for a specific time period docker compose logs --since 1h
-
Common management commands:
# Stop the service docker compose down # Restart the service docker compose restart # Update to the latest version docker compose pull docker compose up -d --force-recreate
For Kubernetes deployments, use the official Helm chart:
-
Add the Helm repository:
helm repo add audiobookshelf-hardcover-sync https://drallgood.github.io/audiobookshelf-hardcover-sync helm repo update
-
Create a values file with your configuration:
# my-values.yaml secrets: audiobookshelf: url: "https://your-audiobookshelf-instance.com" token: "your-audiobookshelf-token" hardcover: token: "your-hardcover-token" # Optional: Enable persistence persistence: enabled: true size: 2Gi # Optional: Configure resources resources: limits: cpu: 500m memory: 512Mi requests: cpu: 100m memory: 128Mi
-
Install the chart:
helm install my-sync audiobookshelf-hardcover-sync/audiobookshelf-hardcover-sync -f my-values.yaml
-
Check the deployment:
kubectl get pods -l app.kubernetes.io/name=audiobookshelf-hardcover-sync kubectl logs -l app.kubernetes.io/name=audiobookshelf-hardcover-sync -f
-
Upgrade the deployment:
helm upgrade my-sync audiobookshelf-hardcover-sync/audiobookshelf-hardcover-sync -f my-values.yaml
For detailed Helm chart configuration options, see the Helm Chart Documentation.
Version 2.0.0 introduces a YAML configuration file as the primary way to configure the application:
server:
port: 8080
timeout: 30s
logging:
level: info # debug, info, warn, error
format: json # json or text for improved readability during development
pretty: false # human-readable formatting for logs
file: /app/logs/sync.log # optional log file path
audiobookshelf:
url: https://your-abs-server.com
token: your_abs_token
hardcover:
token: your_hardcover_token
rate_limit: 10 # requests per second
rate_burst: 15 # burst capacity
sync:
interval: 1h # sync frequency (10m, 30m, 1h, etc)
want_to_read: true # sync "Want to Read" status
owned: true # mark books as owned
match_mode: continue # book matching behavior (continue, skip, fail)
incremental: true # incremental sync strategy enabled (true, false)
min_progress: 0.01 # minimum progress change to sync (0.01 = 1%)
state_file: /app/data/sync_state.json # state storage location
dry_run: false # simulation mode without making changes
force_full_sync: false # force full sync regardless of state
libraries: # library filtering (optional)
include: ["Audiobooks", "Fiction"] # only sync these libraries (by name or ID)
exclude: ["Magazines", "Podcasts"] # exclude these libraries (include takes precedence)
Primary configuration variables:
Variable | Description | Default | Example |
---|---|---|---|
CONFIG_PATH |
Path to config file | ./config.yaml |
/app/config/config.yaml |
LOG_LEVEL |
Logging level | info |
debug , warn , error |
LOG_FORMAT |
Log output format | json |
json , text |
Legacy variables (config file takes precedence):
Variable | Description | Maps to config |
---|---|---|
AUDIOBOOKSHELF_URL |
URL of your AudiobookShelf instance | audiobookshelf.url |
AUDIOBOOKSHELF_TOKEN |
AudiobookShelf API token | audiobookshelf.token |
HARDCOVER_TOKEN |
Hardcover API token | hardcover.token |
SYNC_INTERVAL |
Time between automatic syncs | sync.interval |
SYNC_LIBRARIES_INCLUDE |
Comma-separated list of libraries to include | sync.libraries.include |
SYNC_LIBRARIES_EXCLUDE |
Comma-separated list of libraries to exclude | sync.libraries.exclude |
Container Path | Recommended Host Path | Description |
---|---|---|
/app/config |
./config |
Configuration files |
/app/data |
./data |
Persistent data (cache, database) |
/app/logs |
./logs |
Application logs |
/tmp |
- | Temporary file storage |
Endpoint | Method | Description |
---|---|---|
/health |
GET | Basic health status |
/ready |
GET | Service readiness |
/metrics |
GET | Prometheus metrics |
The sync service supports filtering which AudioBookShelf libraries to sync. This is useful when you have multiple libraries (e.g., Audiobooks, Podcasts, Magazines) but only want to sync specific ones to Hardcover.
Sync only "Audiobooks" and "Fiction" libraries:
sync:
libraries:
include: ["Audiobooks", "Fiction"]
Sync all libraries except "Magazines" and "Podcasts":
sync:
libraries:
exclude: ["Magazines", "Podcasts"]
You can also use library IDs instead of names:
sync:
libraries:
include: ["lib_abc123", "lib_def456"]
SYNC_LIBRARIES_INCLUDE="Audiobooks"
SYNC_LIBRARIES_EXCLUDE="Magazines,Podcasts,Children's Books"
- Include takes precedence: If both
include
andexclude
are specified, only theinclude
list is used - Case-insensitive matching: Library names are matched case-insensitively
- ID matching: You can use either library names or library IDs
- Comma-separated: When using environment variables, separate multiple libraries with commas
- Default behavior: If no filtering is configured, all libraries are synced
To find your library names, check your AudioBookShelf web interface or look at the sync logs when filtering is disabled. The service will log all discovered libraries at the start of each sync.
- Major Rewrite: Complete architectural overhaul for improved stability and maintainability
- New: YAML configuration file support (replaces environment variables)
- Enhanced: GraphQL client for Hardcover API interactions
- Improved: Incremental sync with better state management
- New: Comprehensive logging system with multiple format options
- Enhanced: Edition information now properly handles "Unabridged" and source-specific formats
- Added: Health monitoring and metrics
- Fixed: Multiple issues with book matching and progress tracking
See the CHANGELOG.md for complete details and the MIGRATION.md guide for upgrading from previous versions.
- From v1.x to v2.0.0: Major breaking changes - refer to MIGRATION.md
- Configuration now uses YAML files (environment variables still supported but limited)
- Several environment variables have been renamed or removed
- Docker setup requires volume mapping for persistent configuration
- New logging system with configurable formats
- Reverse Proxy Users: Review the new config.yaml path settings
The project includes several utility tools to help with specific tasks:
The edition-tool
helps create and manage audiobook editions in Hardcover.
# Build the tool
make build-tools
# Show help
./bin/edition-tool help
# Create an edition interactively
./bin/edition-tool create --interactive
# Create an edition prepopulated with data from Hardcover
./bin/edition-tool create --prepopulated
# Create an edition from a JSON template file
./bin/edition-tool create --file path/to/edition-template.json
The image-tool
allows you to upload and attach cover images to books and editions in Hardcover.
# Upload an image to a book
./bin/image-tool upload --url "https://example.com/cover.jpg" --book "hardcover-book-id"
# Upload an image to an edition
./bin/image-tool upload --url "https://example.com/cover.jpg" --edition "hardcover-edition-id" --description "Audiobook Cover"
# Using a custom config file
./bin/image-tool --config /path/to/config.yaml --url "https://example.com/cover.jpg" --book "hardcover-book-id"
The hardcover-lookup
tool helps you search and verify author, narrator, and publisher information in Hardcover.
# Look up an author
./bin/hardcover-lookup author "Stephen King"
# Look up a narrator with JSON output
./bin/hardcover-lookup narrator "Neil Gaiman" --json
# Look up a publisher with custom results limit
./bin/hardcover-lookup publisher "Penguin Random House" --limit 10
# Get help for a specific command
./bin/hardcover-lookup help author
If you're experiencing issues with configuration:
-
Check Configuration File Path
# Make sure CONFIG_PATH is correctly set CONFIG_PATH=/app/config/config.yaml
-
Enable Debug Mode
logging: level: debug format: text # For more human-readable output
-
API Endpoint Access Ensure your AudiobookShelf token has the necessary permissions.
- Check
sync.min_progress
setting (default: 0.01 = 1%) - Verify incremental sync is working properly
- Enable debug logging to see detailed progress calculations
For additional support:
- π Check existing issues
- π Review the MIGRATION.md documentation
- π Create a new issue with debug logs if problems persist
We welcome contributions! Please see our contributing guidelines for details.
Areas for contribution:
- π§ͺ Test coverage improvements
- π Documentation enhancements
- π Bug fixes and performance improvements
- β¨ New features and integrations
- π Issues: GitHub Issues
- π Security: See SECURITY.md for vulnerability reporting
- π License: Apache 2.0
β If this project helps you, please consider giving it a star on GitHub!