Summary
Leaf is an open source macOS EPUB reader for reading and listening to unencrypted books. It provides a local library, bookmarks, saved reading positions, dictionary lookup, and narration through Mac voices, optional offline Kokoro voices, or OpenRouter.
Platforms
macOS desktop: macOS 13 or later. Offline Kokoro narration requires Apple Silicon and macOS 14 or later. App launch and interactive behavior were not verified during this specification review; Intel support and the full supported macOS range were not verified.
User roles
Reader: A single local user reads books and manages personal reading preferences. No application account, administrator role, or shared workspace is implemented.
Features
- Open an unencrypted EPUB and display its readable chapter text, title, and author. — Files: Sources/Leaf/ReaderModel.swift#openBook, Sources/ReaderCore/EPUBImporter.swift#load
- Navigate between pages using the reader’s page controls. — Files: Sources/Leaf/ReaderView.swift, Sources/Leaf/ReaderModel.swift#turnPage
- Jump to a chapter from the contents sidebar. — Files: Sources/Leaf/ReaderView.swift, Sources/Leaf/ReaderModel.swift#selectChapter
- Adjust reading text size while preserving the current passage during page reflow. — Files: Sources/Leaf/ReadingSettingsView.swift, Sources/Leaf/ReaderModel.swift#repaginate
- Reopen a previously opened book from the library. — Files: Sources/Leaf/BookLibraryView.swift, Sources/Leaf/ReaderModel.swift#openLibraryBook
- Filter the library by book title or author. — Files: Sources/Leaf/BookLibraryView.swift
- Remove a library entry while keeping the original EPUB and saved bookmarks. — Files: Sources/Leaf/BookLibraryView.swift, Sources/Leaf/ReaderModel.swift#removeLibraryBook
- Restore saved reading and narration positions when returning to a book. — Files: Sources/Leaf/ReaderModel.swift#applyRestoredPosition, Sources/Leaf/ReadingPosition.swift, Sources/Leaf/BookLibrary.swift
- Save selected text as a bookmark for the current book. — Files: Sources/Leaf/ReaderModel.swift#bookmarkSelectedText, Sources/Leaf/ReaderAnnotations.swift
- Jump to a saved bookmark’s passage. — Files: Sources/Leaf/ReaderView.swift, Sources/Leaf/ReaderModel.swift#openBookmark
- Delete a saved bookmark. — Files: Sources/Leaf/ReaderView.swift, Sources/Leaf/ReaderModel.swift#removeBookmark
- Read book text aloud using an installed Mac voice. — Files: Sources/Leaf/ReaderModel.swift#speak, Sources/Leaf/ReadingSettingsView.swift
- Read book text aloud offline using an installed Kokoro voice. — Files: Sources/Leaf/SpeechSettings.swift#configuration, Sources/Leaf/CloudNarrator.swift#prepare, Sources/Leaf/LocalKokoroWorker.swift#generate
- Read book text aloud using an OpenRouter speech model. — Files: Sources/Leaf/ReaderModel.swift#speak, Sources/Leaf/CloudNarrator.swift#prepare, Sources/ReaderCore/CloudSpeech.swift#speech
- Pause and resume narration. — Files: Sources/Leaf/ReaderModel.swift#toggleReading, Sources/Leaf/CloudNarrator.swift
- Change narration pace. — Files: Sources/Leaf/ReadingSettingsView.swift, Sources/Leaf/ReaderModel.swift#updateRate
- Move backward or forward by sentence during an active or paused listening session. — Files: Sources/Leaf/LeafApp.swift, Sources/Leaf/ReaderModel.swift#navigateReading, Sources/ReaderCore/SentenceNavigation.swift#destination
- Start narration from a clicked word or sentence. — Files: Sources/Leaf/PageText.swift, Sources/Leaf/ReaderModel.swift#seek
- Follow narration with word or sentence highlighting. — Files: Sources/Leaf/ReaderModel.swift, Sources/Leaf/CloudNarrator.swift#tick, Sources/Leaf/PageText.swift
- Open a fullscreen listening view during a listening session. — Files: Sources/Leaf/ReaderModel.swift#toggleListeningView, Sources/Leaf/ReaderView.swift#syncListeningFullscreen, Sources/Leaf/ListeningExperience.swift
- Preview a local or cloud voice using fixed sample text. — Files: Sources/Leaf/ReadingSettingsView.swift, Sources/Leaf/ReaderModel.swift#previewCloudVoice
- Download and prepare the optional Kokoro voice package with visible setup progress. — Files: Sources/Leaf/ReadingSettingsView.swift, Sources/Leaf/LocalKokoro.swift#performInstall
- Cancel an ongoing Kokoro setup. — Files: Sources/Leaf/ReadingSettingsView.swift, Sources/Leaf/LocalKokoro.swift#cancelInstall
- Retry or repair Kokoro setup. — Files: Sources/Leaf/ReadingSettingsView.swift, Sources/Leaf/LocalKokoro.swift#install
- Remove downloaded Kokoro files. — Files: Sources/Leaf/ReadingSettingsView.swift, Sources/Leaf/LocalKokoro.swift#remove
- Save an OpenRouter API key securely in macOS Keychain. — Files: Sources/Leaf/ReadingSettingsView.swift, Sources/Leaf/SpeechSettings.swift#saveKey
- Remove the saved OpenRouter API key. — Files: Sources/Leaf/ReadingSettingsView.swift, Sources/Leaf/SpeechSettings.swift#removeKey
- Refresh the available OpenRouter speech-model list. — Files: Sources/Leaf/ReadingSettingsView.swift, Sources/Leaf/SpeechSettings.swift#refreshModels
- Request audio transcription timestamps for cloud highlighting, with a visible fallback to estimated timing when alignment fails. — Files: Sources/Leaf/ReadingSettingsView.swift, Sources/Leaf/CloudNarrator.swift#prepare, Sources/ReaderCore/CloudSpeech.swift#timings
- Look up selected text in macOS Dictionary. — Files: Sources/Leaf/ReaderModel.swift#lookUpSelectedText, Sources/Leaf/DictionaryLookup.swift#definition, Sources/Leaf/DictionaryLookupView.swift
- Request an online definition through OpenRouter when the local dictionary has no result and a key is saved. — Files: Sources/Leaf/ReaderModel.swift#lookUpSelectedText, Sources/ReaderCore/CloudSpeech.swift#dictionaryDefinition
- Prevent automatic display and system idle sleep while narration or a voice preview is active. — Files: Sources/Leaf/ReaderModel.swift#updatePlaybackActivity, Sources/Leaf/PlaybackActivity.swift#setActive
Main user flows
- Read a book: Choose Open a book or press Command-O → select an unencrypted EPUB → read the displayed text → use page controls or select a chapter → adjust text size in Reading settings if needed.
- Return to a book: Open Library or press Command-L → optionally search by title or author → select a book → continue from its saved position. If the file is unavailable, reopen its EPUB.
- Listen with a Mac voice: Open Reading settings → select Mac voice → choose an installed voice and pace → return to the reader → press Read aloud or Space → pause or resume with Space → use arrow keys to move by sentence during the listening session.
- Listen offline with Kokoro: Open Reading settings → select Local model → choose Download and prepare Kokoro → wait for the ready status → select a voice and optionally preview it → return to the book → start narration.
- Listen through OpenRouter: Open Reading settings → enter and save a personal API key → choose or enter a speech model and voice → select highlighting and timing preferences → optionally preview the voice → return to the book → start narration.
- Save or investigate a passage: Select book text → choose Bookmark to save it, or Look Up to request a definition → return to saved text through the bookmark sidebar, or read the lookup result. Lookup tries macOS Dictionary first and may use OpenRouter if a saved key is available.
Integrations and external services
- macOS speech voices: Local narration using installed voices.
- macOS Dictionary: Local definitions for selected text.
- macOS Keychain: Secure storage of the OpenRouter API key.
- OpenRouter: Optional speech generation, speech-model discovery, audio transcription, and dictionary fallback. Requests use the reader’s account and may incur charges. Cloud narration sends book text; dictionary fallback sends the selected text and nearby context.
- Hugging Face: Downloads optional Kokoro model weights and voices during setup.
- GitHub-hosted downloads and Python package distribution services: Supply the optional local speech runtime and its dependencies during setup. Local narration works offline after preparation.
Known limitations
- Rendering is text-first; publisher images, publisher CSS, and fixed layouts are not supported.
- DRM-protected EPUBs and EPUBs containing encrypted resources are rejected.
- Complete EPUB navigation support is not implemented.
- Import limits include a 100 MB archive-size ceiling, 20,000 archive entries, and five million UTF-16 text units across readable chapters.
- Book progress is approximate.
- Library entries reference original files; moving or deleting a book can make it unavailable.
- Local Kokoro supports English voices and requires Apple Silicon, macOS 14 or later, at least 8 GB RAM, and 4 GB available disk space for initial setup.
- Estimated narration highlighting can drift. Online transcription adds preparation time and cost and may fall back to estimates.
- Cloud functionality depends on network access, account credits, and provider/model availability.
- No silent fallback to another narration provider is implemented.
- The default app package is ad-hoc signed. Notarized distribution and App Store sandboxing remain release work.
- Full accessibility, older macOS, Intel, and device compatibility qualification are incomplete.
- No app launch or interactive verification was performed for this specification.
How to install
Installation document found: yes
Instructions were found in README.md, CONTRIBUTING.md, docs/RELEASE.md, and scripts/package.sh.
Prerequisites
macOS 13 or later. Swift 5.9 or later. Xcode command-line tools. Git to clone the repository. Internet access for cloning and optional downloads. Optional Kokoro narration: Apple Silicon, macOS 14 or later, at least 8 GB RAM, and 4 GB available disk space. Optional OpenRouter functionality: a personal OpenRouter account, API key, and sufficient credits. Optional source-export and dependency-audit helpers: Python 3.9 or later. Optional Developer ID distribution: an installed Developer ID signing certificate.
Install
Clone the repository and enter its directory:
git clone https://github.com/searchrome/leaf.git
cd leaf
Configure
- SIGNING_IDENTITY (optional): Selects the signing identity for app packaging.
- REGISTER_APP (optional): Controls local registration of the packaged app.
- LEAF_VERIFY_LOCAL_KOKORO (optional): Enables the hardware integration test that prepares and exercises the real local speech runtime.
No environment configuration is required for ordinary reading or Mac narration. Configure optional voice providers inside Reading settings. Enter the OpenRouter key through the app; it is stored in Keychain. Prepare Kokoro through the app’s download control.
Build
The README lists the following development run, test, and packaging sequence after cloning:
swift run Leaf
swift test
bash scripts/package.sh
The first command launches the development app; exit it before continuing to the remaining commands. The packaging script performs a release build and creates dist/Leaf.app with an ad-hoc signature by default.
Optional source archive:
python3 scripts/package-source.py --require-license
Run
After packaging:
open dist/Leaf.app
No app launch was performed for this specification.
Port
None. Leaf is a desktop app and exposes no application server port.