Files
ihatepdfs/README.md
2026-06-30 10:47:14 -07:00

7.7 KiB

I Hate PDFs app icon

I Hate PDFs

Native macOS PDF reading, highlighting, commenting, and review.
Local-first. No accounts. No tracking. No cloud upload.

Platform: macOS 13+ License: GPL v2 only Version Language: Swift Status: active development Vibe coded

Download · Report a bug · Contribute · Support · Privacy


I Hate PDFs is a small native macOS PDF reader for local reading, highlighting, commenting, and review. It uses SwiftUI, AppKit, and PDFKit, keeps documents on your Mac, and avoids accounts, tracking, and cloud upload.

Minimum supported macOS version: macOS 13 Ventura.

Supported Mac architectures: Apple Silicon and Intel.

Latest Release

Current version: 0.4.0 build 7.

Download the v0.4 macOS DMG from the GitHub release page:

https://github.com/akkolli/ihatepdfs/releases/tag/v0.4

Use IHatePDFs-v0.4-macos.dmg for direct installation. Open the DMG, then move I Hate PDFs.app into /Applications.

The direct-download DMG is separate from the Mac App Store build. The App Store package uses bundle ID net.akkolli.ihatepdfs and is built with sandbox entitlements documented in docs/RELEASE.md.

Features

  • Incredibly small app size: v0.4 ships as a 998 KB direct-download DMG, with a 255 KB Apple Silicon archive and a 288 KB Intel archive.
  • Extremely fast native PDF reading: built on SwiftUI, AppKit, and PDFKit instead of a bundled browser, runtime, database, or PDF engine.
  • Power- and size-efficient by design: minimal assets, no bundled services, and no background sync workload.
  • Local-first privacy: opens user-selected PDFs from disk and does not require accounts, analytics, tracking, or cloud upload.
  • No internet auto-updater: releases are explicit downloads, so the app is not running update checks in the background.
  • No AI features: no summaries, remote prompts, embeddings, model downloads, or document analysis.
  • Clean review system: focused highlighting, commenting, replies, bookmarks, search, and sidebars that stay hidden until needed.
  • Standards-compatible annotations: comments and highlights are written back into PDFs so they remain useful in common PDF readers.

Privacy And Support

I Hate PDFs works with user-selected local files. It does not require an account, collect analytics, or upload PDFs.

Build From Source

Requirements:

  • macOS 13 or newer
  • Xcode 15 or newer with command line tools
  • Swift Package Manager

Build and run the debug executable:

swift run IHatePDFs

Run tests:

swift test

Build a release .app bundle:

scripts/build-app.sh

Release app builds default to a universal arm64 + x86_64 executable. To build only the current architecture during development, run:

ARCHS="" scripts/build-app.sh

Create a downloadable .dmg:

scripts/make-dmg.sh

The packaged app is written to dist/I Hate PDFs.app; the disk image is written to dist/IHatePDFs-v0.4-macos.dmg by default.

Create the size-gated per-architecture archives:

scripts/make-tiny-archives.sh

This writes dist/IHatePDFs-v0.4-macos-arm64.tar.xz and dist/IHatePDFs-v0.4-macos-x86_64.tar.xz, then verifies each archive is under the 400,000-byte direct-download budget.

Build an App Store upload package after installing the application signing certificate, installer signing certificate, and App Store provisioning profile:

APP_SIGNING_IDENTITY="3rd Party Mac Developer Application: Your Name (TEAMID)" \
INSTALLER_SIGNING_IDENTITY="3rd Party Mac Developer Installer: Your Name (TEAMID)" \
PROVISIONING_PROFILE="$HOME/Downloads/IHatePDFs_AppStore.provisionprofile" \
scripts/make-app-store-pkg.sh

The App Store package is written to dist/IHatePDFs-v0.4-macos-appstore.pkg. More details are in docs/RELEASE.md.

Installation

Download IHatePDFs-v0.4-macos.dmg from the latest GitHub release, open it, and move I Hate PDFs.app into /Applications.

For local direct-download builds, the app may not be Developer ID notarized. If macOS blocks first launch, open Finder, Control-click I Hate PDFs.app, choose Open, then confirm.

Development

The project is a Swift Package with two targets:

  • IHatePDFsCore: PDF annotation models, annotation export helpers, hit testing, color preference logic, file selection, and keyboard policies.
  • IHatePDFs: SwiftUI macOS app, PDFKit bridge, toolbar, menus, sidebars, anchored comment popovers, opening, saving, sharing, and search.

Engineering rule: keep this a native macOS app with the smallest final bundle that still delivers the required fluidity and functionality. See CONTRIBUTING.md before adding dependencies, bundled assets, PDF engines, runtimes, or broad architectural changes. Use docs/RELEASE.md when preparing a new version; it is the checklist for version bumps, release validation, size gates, and upload packaging.

Open source contribution policy:

  • Contributions are accepted under GPL-2.0-only. See LICENSE.
  • Vibe coded pull requests are welcome, but they must include clear change documentation, strict QA notes, and screenshots or recordings for UI changes.
  • This project is vibe coded and maintained with AI agents. Feature requests are welcome, and agent-assisted PRs are welcome when they follow the QA and contribution guidelines.
  • Start with CONTRIBUTING.md before opening a pull request.
  • UI pull requests must include before/after screenshots or a short screen recording.
  • Screenshots, recordings, and committed media files included with a pull request must each be under 1 MB.

Useful checks:

swift test
swift build -c release
swift scripts/verify-pdf-annotations.swift
scripts/verify-release-artifacts.sh

The PDF verification script generates and inspects standard highlight, underline, selected-text comment, reply, free-text, contents, and annotation relationship dictionaries. The release artifact verifier checks the current direct-download app and DMG by default. Run REQUIRE_APP_STORE_PKG=1 scripts/verify-release-artifacts.sh after creating an App Store package.

Manual release QA and workflow guardrails for Preview, Acrobat Reader, and browser PDF viewers are documented in docs/QA.md. Release and App Store packaging are documented in docs/RELEASE.md.

Screenshot

Screenshots live in docs/screenshots.

Default reading mode

License

GNU General Public License version 2 only. See LICENSE.