Sync your X bookmarks, search and organize them, and get a weekly email digest with what you saved.
You bookmark tweets to come back to later. You don't come back enough. Good stuff gets buried.
xbook pulls your bookmarks into a local database you can search, and emails you once a week with what you saved. The bookmarks come to you instead of sitting there waiting.
- Chrome Sync — Pull bookmarks straight from Chrome. Full history, no developer account needed (macOS)
- X API Sync — Or use the official X API. Works on all platforms (requires X Developer account)
- Import — Load bookmarks from JSON or CSV
- Full-text Search — Search across every bookmark you've ever saved
- Browse — Filter by folder, author, or tags. Add notes and tags per bookmark
- Newsletter — Weekly email digest of new bookmarks via Resend
- Scheduled — Run sync + newsletter on a cron for hands-off operation
- Self-hosted — Single Docker container, SQLite, your data stays on your machine
No API keys needed. Syncs your full bookmark history directly from Chrome.
git clone https://github.com/joedanz/xbook.git
cd xbook
npm install
cd web && npm install && cd ..
cp .env.example .env.local
cd web && npm run dev # Start the web UIIn a separate terminal:
xbook sync --chrome # Pulls all your bookmarks from ChromeOpen http://localhost:3000/dashboard to browse your bookmarks.
Note: Chrome sync requires macOS and Full Disk Access for your terminal (System Settings → Privacy & Security → Full Disk Access). You must be logged into x.com in Chrome.
If you're not on macOS, or prefer OAuth-based sync:
git clone https://github.com/joedanz/xbook.git
cd xbook
cp .env.example .env
# Edit .env with your X_CLIENT_ID and X_CLIENT_SECRET
docker compose up -dOpen http://localhost:3000/dashboard and click "Connect X Account" to link your X account.
You'll need an X Developer account with OAuth 2.0 credentials. See the X Developer setup guide for a walkthrough. The API is limited to your ~100 most recent bookmarks — use import or Chrome sync for full history.
Self-Hosting Details
xbook runs as a single Docker container with SQLite for storage. Data is persisted in a named volume at /data/xbook.db.
Requirements:
- Docker and Docker Compose
- X Developer account with OAuth 2.0 credentials (for API sync), or macOS with Chrome (for Chrome sync)
The SQLite database is stored in a Docker volume (xbook-data) and persists across restarts.
Pull the latest and restart. Migrations run automatically on startup.
git pull
docker compose build
docker compose up -dYour data is safe in the xbook-data Docker volume across upgrades.
Local Development
Prerequisites:
- Node.js 20+
- Resend account (optional, for newsletters)
- For Chrome sync: macOS + Chrome logged into x.com
- For API sync: X Developer account with OAuth 2.0 (PKCE)
Setup:
git clone https://github.com/joedanz/xbook.git && cd xbook
npm install
cd web && npm install && cd ..
cp .env.example .env.local
# Edit .env.local with your credentials (optional — not needed for Chrome sync)| Variable | Required | Description |
|---|---|---|
X_CLIENT_ID |
For API sync | OAuth 2.0 Client ID from X Developer Portal |
X_CLIENT_SECRET |
For API sync | OAuth 2.0 Client Secret |
RESEND_API_KEY |
No | For email newsletter digest |
NEWSLETTER_TO |
No | Newsletter recipient email |
Run:
cd web && npm run dev # Web UI at http://localhost:3000
xbook sync --chrome # Sync from Chrome (or xbook sync --api for API)
npm test # Run testsUpgrading:
git pull
npm install
cd web && npm install && cd ..Migrations run automatically on startup.
| Command | Description |
|---|---|
xbook login [api-key] |
Authenticate with an xbook API key (or set XBOOK_API_KEY env var) |
xbook logout |
Clear saved API key |
xbook sync |
Sync bookmarks from X |
xbook import <file> |
Import bookmarks from JSON or CSV (--dry-run to validate) |
xbook bookmarks |
List bookmarks (--search, --folder, --author, --tags, --starred, --page, --page-size) |
xbook folders |
List bookmark folders |
xbook stats |
Show bookmark statistics |
xbook status |
Check server status and connection |
xbook newsletter |
Send or preview newsletter (--dry-run to preview) |
xbook serve |
Run sync + newsletter on a cron (--cron, --sync-only, --newsletter-only) |
All commands support --json for machine-readable output and --api-url to override the API URL.
Start the dev server and open http://localhost:3000/dashboard:
- Dashboard with stats and recent bookmarks
- Full bookmark list with search, folder/author filters, and sort
- Import bookmarks from JSON/CSV file uploads
- Per-bookmark notes and tags
- Move bookmarks between folders
xbook/
├── src/ CLI commands (login, sync, import, serve)
├── shared/ Types, schema, repository, encryption, auth
├── web/ Next.js web interface
│ ├── app/ Pages and API routes
│ ├── components shadcn/ui components
│ └── lib/ Server actions and DB singleton
└── tests/ Vitest test suite
The CLI and web interface share the same SQLite database and auth tokens.
- API Reference — REST API endpoints, authentication, and response formats
- Import Formats — Supported file formats for bookmark imports
- Environment Variables — Complete env var reference
- Troubleshooting — Common issues and solutions
Contributions are welcome! Please open an issue or pull request on GitHub.
- Fork the repo and create a feature branch
- Make your changes with tests where applicable
- Run
npm testandcd web && npm testto verify - Open a PR against
main
Licensed under FSL-1.1-MIT (Functional Source License, Version 1.1, MIT Future License).
- Free to self-host, modify, and use for any non-competing purpose
- Cannot be used to offer a competing commercial service
- Automatically converts to MIT after 2 years per version
See fsl.software for details.


