Back to Leaf

Leaf — App specification

Why an app specification

Buyers: know exactly what you get, with each feature checked against the source.

Developers: a clear app specification builds trust, helps reduce refunds and supports better ranking.

What you get

Found: 31; Partly: 1; Missing: 0; Couldn't verify: 0

App specification source review: 31.5 of 32 features found in source (98.44%)

  • ✓ Open an unencrypted EPUB and display its readable chapter text, title, and author. — found
  • ✓ Navigate between pages using the reader’s page controls. — found
  • ✓ Jump to a chapter from the contents sidebar. — found
  • ✓ Adjust reading text size while preserving the current passage during page reflow. — found
  • ✓ Reopen a previously opened book from the library. — found
  • ✓ Filter the library by book title or author. — found
  • ✓ Remove a library entry while keeping the original EPUB and saved bookmarks. — found
  • ✓ Restore saved reading and narration positions when returning to a book. — found
  • ✓ Save selected text as a bookmark for the current book. — found
  • ✓ Jump to a saved bookmark’s passage. — found
  • ✓ Delete a saved bookmark. — found
  • ✓ Read book text aloud using an installed Mac voice. — found
  • ✓ Read book text aloud offline using an installed Kokoro voice. — found
  • ✓ Read book text aloud using an OpenRouter speech model. — found
  • ✓ Pause and resume narration. — found
  • ✓ Change narration pace. — found
  • ✓ Move backward or forward by sentence during an active or paused listening session. — found
  • ✓ Start narration from a clicked word or sentence. — found
  • ✓ Follow narration with word or sentence highlighting. — found
  • ✓ Open a fullscreen listening view during a listening session. — found
  • ✓ Preview a local or cloud voice using fixed sample text. — found
  • ✓ Cancel an ongoing Kokoro setup. — found
  • ✓ Retry or repair Kokoro setup. — found
  • ✓ Remove downloaded Kokoro files. — found
  • ✓ Save an OpenRouter API key securely in macOS Keychain. — found
  • ✓ Remove the saved OpenRouter API key. — found
  • ✓ Refresh the available OpenRouter speech-model list. — found
  • ✓ Request audio transcription timestamps for cloud highlighting, with a visible fallback to estimated timing when alignment fails. — found
  • ✓ Look up selected text in macOS Dictionary. — found
  • ✓ Request an online definition through OpenRouter when the local dictionary has no result and a key is saved. — found
  • ✓ Prevent automatic display and system idle sleep while narration or a voice preview is active. — found
  • ◐ Download and prepare the optional Kokoro voice package with visible setup progress. — partly

Static AI review of the source. Partial features count half. Actual run verification: Not tested; source presence and a responding demo do not prove the features work.

Buy

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

  1. Open an unencrypted EPUB and display its readable chapter text, title, and author. — Files: Sources/Leaf/ReaderModel.swift#openBook, Sources/ReaderCore/EPUBImporter.swift#load
  2. Navigate between pages using the reader’s page controls. — Files: Sources/Leaf/ReaderView.swift, Sources/Leaf/ReaderModel.swift#turnPage
  3. Jump to a chapter from the contents sidebar. — Files: Sources/Leaf/ReaderView.swift, Sources/Leaf/ReaderModel.swift#selectChapter
  4. Adjust reading text size while preserving the current passage during page reflow. — Files: Sources/Leaf/ReadingSettingsView.swift, Sources/Leaf/ReaderModel.swift#repaginate
  5. Reopen a previously opened book from the library. — Files: Sources/Leaf/BookLibraryView.swift, Sources/Leaf/ReaderModel.swift#openLibraryBook
  6. Filter the library by book title or author. — Files: Sources/Leaf/BookLibraryView.swift
  7. Remove a library entry while keeping the original EPUB and saved bookmarks. — Files: Sources/Leaf/BookLibraryView.swift, Sources/Leaf/ReaderModel.swift#removeLibraryBook
  8. 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
  9. Save selected text as a bookmark for the current book. — Files: Sources/Leaf/ReaderModel.swift#bookmarkSelectedText, Sources/Leaf/ReaderAnnotations.swift
  10. Jump to a saved bookmark’s passage. — Files: Sources/Leaf/ReaderView.swift, Sources/Leaf/ReaderModel.swift#openBookmark
  11. Delete a saved bookmark. — Files: Sources/Leaf/ReaderView.swift, Sources/Leaf/ReaderModel.swift#removeBookmark
  12. Read book text aloud using an installed Mac voice. — Files: Sources/Leaf/ReaderModel.swift#speak, Sources/Leaf/ReadingSettingsView.swift
  13. 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
  14. 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
  15. Pause and resume narration. — Files: Sources/Leaf/ReaderModel.swift#toggleReading, Sources/Leaf/CloudNarrator.swift
  16. Change narration pace. — Files: Sources/Leaf/ReadingSettingsView.swift, Sources/Leaf/ReaderModel.swift#updateRate
  17. 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
  18. Start narration from a clicked word or sentence. — Files: Sources/Leaf/PageText.swift, Sources/Leaf/ReaderModel.swift#seek
  19. Follow narration with word or sentence highlighting. — Files: Sources/Leaf/ReaderModel.swift, Sources/Leaf/CloudNarrator.swift#tick, Sources/Leaf/PageText.swift
  20. Open a fullscreen listening view during a listening session. — Files: Sources/Leaf/ReaderModel.swift#toggleListeningView, Sources/Leaf/ReaderView.swift#syncListeningFullscreen, Sources/Leaf/ListeningExperience.swift
  21. Preview a local or cloud voice using fixed sample text. — Files: Sources/Leaf/ReadingSettingsView.swift, Sources/Leaf/ReaderModel.swift#previewCloudVoice
  22. Download and prepare the optional Kokoro voice package with visible setup progress. — Files: Sources/Leaf/ReadingSettingsView.swift, Sources/Leaf/LocalKokoro.swift#performInstall
  23. Cancel an ongoing Kokoro setup. — Files: Sources/Leaf/ReadingSettingsView.swift, Sources/Leaf/LocalKokoro.swift#cancelInstall
  24. Retry or repair Kokoro setup. — Files: Sources/Leaf/ReadingSettingsView.swift, Sources/Leaf/LocalKokoro.swift#install
  25. Remove downloaded Kokoro files. — Files: Sources/Leaf/ReadingSettingsView.swift, Sources/Leaf/LocalKokoro.swift#remove
  26. Save an OpenRouter API key securely in macOS Keychain. — Files: Sources/Leaf/ReadingSettingsView.swift, Sources/Leaf/SpeechSettings.swift#saveKey
  27. Remove the saved OpenRouter API key. — Files: Sources/Leaf/ReadingSettingsView.swift, Sources/Leaf/SpeechSettings.swift#removeKey
  28. Refresh the available OpenRouter speech-model list. — Files: Sources/Leaf/ReadingSettingsView.swift, Sources/Leaf/SpeechSettings.swift#refreshModels
  29. 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
  30. Look up selected text in macOS Dictionary. — Files: Sources/Leaf/ReaderModel.swift#lookUpSelectedText, Sources/Leaf/DictionaryLookup.swift#definition, Sources/Leaf/DictionaryLookupView.swift
  31. 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
  32. 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

  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. 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.
  6. 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.

Help us improve CookThisApp

0/2000