Comprehensive Python SDK for Readwise with high-level workflow abstractions. Supports V2 (highlights/books) and V3 (Reader) APIs with managers, workflows, and CLI.
Project description
readwise-plus
Comprehensive Python SDK for Readwise, covering both the Readwise API (v2) for highlights/books and the Reader API (v3) for documents behind one concept-oriented interface.
Table of Contents
- Features
- Installation
- Quick Start
- Architecture
- Concept Operations
- Compatibility APIs
- CLI
- MCP Server
- Development
- Contributing
- License
Features
- Concept-oriented facade:
Readwise/AsyncReadwiseexpose.documents,.highlights,.books,.tags,.digests, and.sync— one place to call each operation, shared by the SDK, CLI, and MCP server - Raw escape hatch:
.raw.v2/.raw.v3for direct, low-level Readwise/Reader API access when you need it - CLI: full command tree (
documents,highlights,books,tags,digest,sync) with--output table|json|jsonl - MCP server: nine tools for AI agents (Claude Code, Claude Desktop, or any MCP client)
- Compatibility APIs: the pre-0.3
ReadwiseClient, managers, workflows, and contrib helpers keep working unchanged — see Compatibility APIs and MIGRATION.md
Installation
pip install readwise-plus
With CLI support:
pip install readwise-plus[cli]
As an MCP server for AI agents:
pip install readwise-plus[mcp]
Quick Start
from readwise_sdk import Readwise
from readwise_sdk.models import DocumentSearch
with Readwise() as readwise: # reads READWISE_API_KEY from the environment
result = readwise.documents.search(DocumentSearch(query="python", limit=20))
for doc in result.items:
print(doc.title)
Async, for agent runtimes and async apps:
from readwise_sdk import AsyncReadwise
from readwise_sdk.models import DocumentSearch
async with AsyncReadwise() as readwise:
result = await readwise.documents.search(DocumentSearch(query="python", limit=20))
for doc in result.items:
print(doc.title)
Readwise and AsyncReadwise are the preferred entry points as of 0.3. New code should start here — see Concept Operations below. Everything under Compatibility APIs (ReadwiseClient, .v2/.v3, managers, workflows, contrib) still works and is not scheduled for removal before 1.0; if you have existing code using it, there is no need to migrate immediately.
Architecture
readwise-plus/
├── Concept facade → Readwise | AsyncReadwise
│ ├── .documents Reader documents (v3)
│ ├── .highlights Readwise highlights (v2)
│ ├── .books Readwise books/sources (v2)
│ ├── .tags Tag reports, auto-tag, merge/rename/delete
│ ├── .digests Daily/weekly/book/custom digest data
│ ├── .sync Full/incremental sync, checkpoints
│ └── .raw.v2 / .raw.v3 Low-level escape hatch (same clients as below)
├── Operations layer → async-first; shared by the facade, CLI, and MCP server
├── Resource clients → readwise_sdk.resources.v2 / .v3 (endpoint-only)
└── Compatibility layer → ReadwiseClient/.v2/.v3, managers, workflows, contrib
The CLI and MCP server call the same operations layer as the Readwise/AsyncReadwise facade, so behavior (limits, filtering, error handling) is consistent across all three surfaces. See docs/architecture.md for a short contributor-facing note on the layering, and MIGRATION.md for the old→new API mapping and deprecation timeline.
Concept Operations
Each concept attribute exposes the same methods on both Readwise (sync) and AsyncReadwise (await-prefixed):
from readwise_sdk import Readwise
from readwise_sdk.models import BookSearch, DocumentSearch, HighlightSearch
with Readwise() as readwise:
# Documents (Reader v3)
docs = readwise.documents.search(DocumentSearch(location="later", query="python"))
doc = readwise.documents.get(docs.items[0].id, with_content=True)
readwise.documents.add_tag(doc.id, "to-review")
# Highlights (Readwise v2)
highlights = readwise.highlights.search(HighlightSearch(query="python"))
created = readwise.highlights.create_from_fields(
text="Important quote", title="Book Title", author="Author Name"
)
# Books (Readwise v2)
books = readwise.books.search(BookSearch(query="python"))
with_highlights = readwise.books.with_highlights(books.items[0].id)
# Tags
report = readwise.tags.get_tag_report()
# Digests
daily = readwise.digests.daily()
# Sync
checkpoint = readwise.sync.status()
For advanced or low-level use, readwise.raw.v2 and readwise.raw.v3 return the same client objects documented under Compatibility APIs.
Compatibility APIs
Everything below predates the 0.3 concept facade. It is unchanged and fully supported — these are not "legacy" in the sense of being broken or scheduled for imminent removal, just no longer the recommended starting point for new code. See MIGRATION.md for the full old→new mapping and the deprecation timeline through 1.0.
ReadwiseClient / AsyncReadwiseClient
from readwise_sdk import ReadwiseClient
from readwise_sdk.v3.models import DocumentLocation
client = ReadwiseClient(api_key="your_token_here") # or READWISE_API_KEY env var
client.validate_token()
# V2 API (Readwise) — highlights and books
for highlight in client.v2.list_highlights():
print(highlight.text)
review = client.v2.get_daily_review()
# V3 API (Reader) — documents
for doc in client.v3.list_documents(location=DocumentLocation.LATER):
print(doc.title)
result = client.v3.save_url("https://example.com/article")
client.close()
Managers
from readwise_sdk.managers import BookManager, DocumentManager, HighlightManager
from readwise_sdk import BookCategory
highlights = HighlightManager(client)
recent = highlights.get_highlights_since(days=7)
matches = highlights.search_highlights("python programming")
books = BookManager(client)
python_books = books.get_books_by_category(BookCategory.BOOKS)
book_with_highlights = books.get_book_with_highlights(book_id=123)
docs = DocumentManager(client)
inbox = docs.get_inbox()
docs.archive(inbox[0].id)
Workflows
from readwise_sdk.workflows import DigestBuilder, TagWorkflow
from readwise_sdk.workflows.tags import TagPattern
digest = DigestBuilder(client)
print(digest.create_daily_digest())
workflow = TagWorkflow(client)
patterns = [
TagPattern(r"\bpython\b", "python", case_sensitive=False),
TagPattern(r"TODO:", "actionable", match_in_notes=True),
]
result = workflow.auto_tag_highlights(patterns, dry_run=True)
print(f"Would tag {len(result)} highlights")
Contrib
from readwise_sdk.contrib import BatchSync, BatchSyncConfig, DocumentImporter, HighlightPusher
pusher = HighlightPusher(client)
pusher.push(text="Great quote from the article", title="Article Title", source_url="https://example.com/article")
importer = DocumentImporter(client)
doc_id = importer.save_url("https://example.com/article", tags=["to-read", "python"])
sync = BatchSync(client, config=BatchSyncConfig(batch_size=100, state_file="sync_state.json"))
result = sync.sync_highlights(on_item=lambda h: print(h.text))
CLI
readwise [--output table|json|jsonl] [--no-color] [--quiet] <group> <command> ...
--output defaults to table; use json or jsonl for scripting and agent use. --no-color disables Rich styling; --quiet suppresses non-data notices.
Highlights
readwise highlights list --limit 10 --book-id 123
readwise highlights show 123456
readwise highlights create "Important quote" --title "Book Title" --author "Author Name"
readwise highlights update 123456 --note "revised note"
readwise highlights delete 123456
readwise highlights tag 123456 to-review
readwise highlights untag 123456 to-review
readwise highlights export -f markdown -o highlights.md
Books
readwise books list --limit 20 --category books
readwise books show 123
Documents
readwise documents inbox --limit 50
readwise documents get abc123 --with-content
readwise documents save "https://example.com/article"
readwise documents update abc123 --title "New title"
readwise documents move abc123 archive
readwise documents tag abc123 to-review
readwise documents delete abc123
readwise documents stats
readwise reader ... remains as a deprecated alias for readwise documents ... (inbox, save, archive, stats, plus every documents subcommand); it emits a stderr warning in table mode.
Tags
readwise tags list
readwise tags search python --limit 20
readwise tags untagged --limit 20
readwise tags auto-tag --pattern '\bpython\b' --tag python --dry-run
readwise tags rename old-name new-name --dry-run
readwise tags merge "tag-a,tag-b" --into merged-tag --dry-run
readwise tags delete old-tag --dry-run
readwise tags report
Digests
readwise digest daily -f markdown
readwise digest weekly -o weekly.md
readwise digest book 12345 -o book-notes.md
readwise digest custom --since 2024-01-01 --group-by-date
Sync
readwise --output json sync full
readwise sync incremental --state-file sync.json
readwise sync status --state-file sync.json
readwise sync reset --state-file sync.json
MCP Server
readwise-plus ships an optional MCP server that exposes Readwise and Reader operations as tools for AI agents (Claude Code, Claude Desktop, or any MCP client). It's a thin layer over the same operations layer used by the SDK facade and CLI — install the mcp extra and register the readwise-mcp command.
Register with Claude Code
claude mcp add readwise --env READWISE_API_KEY=your-token -- uvx --from "readwise-plus[mcp]" readwise-mcp
Register with any MCP client
{
"mcpServers": {
"readwise": {
"command": "uvx",
"args": ["--from", "readwise-plus[mcp]", "readwise-mcp"],
"env": { "READWISE_API_KEY": "your-token" }
}
}
}
If readwise-plus[mcp] is already installed in the environment, run the readwise-mcp console script (equivalently python -m readwise_sdk.mcp) directly.
Tools
Nine tools, backed by the SDK:
- Documents (Reader v3):
save_to_reader,search_documents,get_document,update_document,delete_document - Highlights (Readwise v2):
get_highlights,export_highlights,create_highlight - Books (Readwise v2):
get_books
Auth comes from READWISE_API_KEY (an environment variable, or a READWISE_API_KEY= line in ~/.env). Talk to your agent in natural language — "save this URL to my reading list", "find the article I archived about X" — and it picks the right tool.
Development
# Clone the repository
git clone https://github.com/EvanOman/readwise-plus.git
cd readwise-plus
# Install dependencies
just install
# Run all checks (format, lint, type-check, test)
just fc
# Run tests only
just test
# Run specific test file
uv run pytest tests/v2/test_client.py
Contributing
Contributions are welcome! Please follow these guidelines:
- Fork the repository and create a feature branch
- Follow conventional commits for commit messages:
feat(scope): add new featurefix(scope): fix a bugdocs: update documentation
- Run
just fcbefore committing to ensure all checks pass - Write tests for new functionality
- Submit a pull request with a clear description
See AGENTS.md for detailed development guidelines and docs/architecture.md for the layering contributors should preserve.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file readwise_plus-0.3.0.tar.gz.
File metadata
- Download URL: readwise_plus-0.3.0.tar.gz
- Upload date:
- Size: 283.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0cb2c0041c1493106c630774c950b4315eeb0a5d921680c63f31282087fc9ee3
|
|
| MD5 |
6632d94d1314df0d68744078cf87aa96
|
|
| BLAKE2b-256 |
2107cd87e27b062bf8535b3eb32db29c9f345361f56b3c0bec97c53ab2375cc2
|
File details
Details for the file readwise_plus-0.3.0-py3-none-any.whl.
File metadata
- Download URL: readwise_plus-0.3.0-py3-none-any.whl
- Upload date:
- Size: 121.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8fcd24ed3435043008f77a235c4f0a35a4eb4216895bec05b7bf14c33956842e
|
|
| MD5 |
032ce838f8d38e3a20001254045542a2
|
|
| BLAKE2b-256 |
0cfe6cd8011a4ca891369a1b7a880d1d79e6d23062b54b167b19dd9ed75858a1
|