A lightweight native EPUB and PDF reader for macOS. Paginated reading, typography and theme controls, highlights with notes and drawings, configurable Ask AI, webpage reading, optional iCloud or Google Drive sync, and a distraction-free interface.
Kodi Reader is not affiliated with the Kodi media center or the XBMC Foundation.
Paginated EPUB rendering with typography, margin, and theme controls, plus native PDF reading with fit-to-page zoom and adaptive two-page spreads. Position and progress survive layout changes and app relaunches.
Rename a document from its library context menu (Rename…) or while reading with File → Rename Document…. The name persists and syncs with book details; the original file keeps its name, and reading data stays attached.
Text highlights in multiple colors, each with an attached note, stored alongside the book.
Export all notes from the notes sidebar’s export menu, or one note from its
… → Export Note menu. Choose Markdown (.md), Word (.docx), Apple Notes
(.html), or Notion (.md). Each export includes the referenced passage,
chapter, book title, author, and note body. Import the HTML file through
Apple Notes’ File → Import to Notes, or the Markdown file through Notion’s
Settings → Import → Text & Markdown. Drawing notes include their passage
and a notice; the drawing itself is not embedded.
Freeform sketches per highlight via a bundled, offline Excalidraw editor.
Opt-in OpenAI-powered chat about the book, with per-book chat threads and surrounding-passage context sent for better answers. Quick prompt badges and personal saved prompts make recurring questions easier to ask.
Load an article or page, extract the readable content, and read it in the same paginated view as a book.
Settings → Sync offers Off (the default), iCloud, or Google Drive, with one provider active per Mac. Choose Notes only or Books and notes; saved Ask AI history has a separate opt-in toggle. Book files download when opened or through Download for Offline Reading. Switching providers requires a confirmed copy of this Mac's library; the old cloud copy remains. See iCloud help, Google Drive help, and their release setup guides.
Source is public under MIT. Issues are welcome for bugs. Pull requests are not the goal right now — this is a source-available personal project, not a contributor funnel. See NOTICE.md for third-party licenses and SECURITY.md to report vulnerabilities privately.
For implementation details, see How Kodi Reader works.
A macOS disk image is published on GitHub Releases. Release builds are signed with Developer ID and notarized by Apple. You can also build from source (Xcode 16.3 or later).
The site is deployed on Vercel at www.kodi-reader.app.
The linked Vercel project's Root Directory must be website, with the Other
framework preset. Git deployments then use website/vercel.json and serve only
the static site. Deploying the repository root puts the homepage under /website/
and leaves / returning 404. After production deployments, verify the homepage,
its assets, and the download link on both the apex and www domains.
- Books, PDFs, highlights, notes, and drawings are stored on this Mac (Application Support). Optional sync stores selected categories in either the user's private iCloud database or hidden Google Drive app-data folder, using their respective storage allowance. EPUBs are read directly from their archives and PDFs remain byte-for-byte unchanged; Kodi annotations are stored separately.
- There is no analytics or telemetry.
- Ask AI is opt-in. Quoted passages and chat are sent to the hosted Kodi AI proxy, which forwards requests to OpenAI. The OpenAI API key lives only on the server, never in the Mac app. Kodi AI uses a stronger default model tuned for simple explanations with references to the passages you attach.
- Ask AI requires email-code sign-in through Supabase. Supabase stores the account email and authentication records; the configured email provider delivers login codes. Session tokens stay in macOS Keychain. The AI proxy validates the session and applies temporary per-account/IP request limits; it does not log tokens or book passages. Sign out or delete the account from the Ask AI account menu. Local books, notes, and conversations remain on this Mac after either action.
- Opened webpages are fetched and converted locally. There are no extra network calls beyond the page itself.
- macOS 15 or later
- Xcode 16.3 or later (Swift 6.1 is required by the authentication SDK)
- XcodeGen to generate the project file
- Node.js/npm only when changing the bundled Excalidraw drawing host
brew install xcodegenFor hosted Ask AI, follow the email authentication setup guide. Without Supabase configuration the reader works normally, but AI sign-in is unavailable.
Kodi Reader checks for updates quietly on launch and daily. An Update available button appears in the home header and reading/browser toolbar only when a new version is available. Click it to download, then Restart to update when ready. Choose Kodi Reader → Check for Updates… to check manually. Settings → Updates controls automatic checks and optional automatic downloads/installations. Updating keeps local reading data. Users on v0.3.0 or earlier need to install v0.3.1 manually once to get the updater.
Download KodiReader.dmg from
GitHub Releases,
open it, and drag Kodi Reader.app into Applications.
Current releases are signed with Developer ID and notarized by Apple. macOS will still show its normal confirmation the first time an Internet-downloaded app is opened.
Clone the repository and install XcodeGen:
git clone https://github.com/dev-olly/kodi-reader.git
cd kodi-reader
brew install xcodegenDebug builds use ad-hoc signing so they run locally without distribution
credentials. Release builds require the project's Developer ID certificate.
Ordinary builds omit Finder document handlers, including local Release builds.
package-dmg.sh opts into EPUB/PDF registration for the distributed app and
removes its loose app copies after creating the DMG. It preserves release metadata
in .build/release-info.plist for appcast generation.
After an installed release launches (including after a Sparkle update), it
unregisters older or equal-version Kodi copies and registers itself. Newer copies
are left alone. Sparkle replaces the previous installed release in place;
registration cleanup does not delete other installations or reader data.
On a machine with multiple Xcode versions, point the shell at the Xcode you want:
export DEVELOPER_DIR=/Applications/Xcode.app/Contents/DeveloperGenerate the Xcode project and open it:
xcodegen generate
open KodiReader.xcodeprojOr build from the command line. Debug builds on this machine should disable code signing:
xcodegen generate
xcodebuild \
-project KodiReader.xcodeproj \
-scheme KodiReader \
-configuration Debug \
-destination 'platform=macOS' \
CODE_SIGNING_ALLOWED=NO \
buildThe .xcodeproj is generated from project.yml and is not committed, so
regenerate it after pulling changes that touch the project layout.
The bundle identifier is com.olly.KodiReader. Product name lives in
project.yml as PRODUCT_NAME: Kodi Reader.
The shared logo master is website/assets/kodi-logo.svg.
It uses solid forest green (#245744) and a white k with an upward-turning page.
To regenerate the macOS app icon, welcome-screen image, website PNGs, and favicons
after editing the master, run on macOS:
swift Scripts/generate-brand-assets.swiftGenerated assets are committed, so normal builds do not need this step.
The app uses Sparkle with a signed
appcast.xml served from this repository's main branch. Sparkle 2.10.0 is pinned
in project.yml; update archives and the feed both require Ed25519 signatures.
The private signing key stays in the release Mac's login Keychain under account
com.olly.KodiReader. Only SUPublicEDKey is committed. Preserve this Keychain
key when moving release machines; never commit or publish the private key.
For each release:
- Increase both
MARKETING_VERSIONand the integerCURRENT_PROJECT_VERSIONinproject.yml, and writedocs/releases/<version>.md. - Run
./Scripts/package-dmg.sh --notarize. - Run
./Scripts/generate-appcast.shto generate and sign the feed using Sparkle. The tool embeds release notes and checks the signing key and notarization ticket. - Publish
KodiReader.dmgto the matching GitHub release (v<version>). - Commit and push
appcast.xmlafter the download is public. Installed apps can then discover the update. Do not edit the signed feed by hand.
The DMG script signs Sparkle's nested helpers before signing the outer app. Debug builds enable Sparkle's sandbox installer service; Release builds are unsandboxed and use the normal installer. Development-only library-validation exceptions are kept out of Release entitlements.
./Scripts/fetch-samples.sh # downloads three Project Gutenberg books
swift testEpubKitTests covers container and metadata parsing against real books;
ReaderUITests drives a live WKWebView through the whole rendering path and
asserts that pagination, page turns, progress, and position restoring all work.
Tests skip rather than fail if the sample books have not been downloaded.
swift test --filter SnapshotTests
open Snapshots/This renders real pages to PNGs in Snapshots/ using WKWebView.takeSnapshot,
covering every theme, a two-column spread, the typography extremes, and
highlights on both light and dark backgrounds. It captures the web view's own
output in-process, so it needs no screen recording permission and shows what
the reader actually draws rather than whatever is on the display.
It is worth doing after any change to reader.css. Assertions cannot tell you
that a page is ugly, and a theme bug that made dark mode black-on-black
passed every functional test before the snapshots exposed it.
The drawing editor is a bundled, offline Excalidraw build. npm is only needed when changing that host:
cd Tools/excalidraw-host
npm ci
npm run buildThat writes static assets into Sources/ReaderUI/Resources/Excalidraw/. Commit
those generated files so the app builds without Node.
No library shelf, DRM/LCP, OCR, password-protected PDF support, sync, OPDS
catalogues, bundled audiobooks, or fixed-layout EPUB. EPUBs and PDFs are opened
with Cmd-O or by dropping them on the window; articles and websites can be
opened from a URL. The welcome screen lists what you were reading recently.





