Version 0.1.16 · released September 4, 2026 · macOS · MIT

The PDF reloads when the file changes.

Realtime PDF watches one PDF on your Mac, keeps a saved history, and can run a command when a related source file changes. If that command regenerates the PDF, the viewer reloads it.

brew tap dickwu/tap
brew install --cask realtime-pdf

Open source under the MIT license. DMGs for Apple silicon and Intel are on the v0.1.16 release. The cask homepage is the GitHub repository.

invoice.pdf

The viewer reloads this file when it changes on disk.

  1. When this file changes ~/Sites/app/resources/views/pdf/invoice.blade.php
  2. Run this command php artisan test --filter=GenerateInvoicePdfTest
  3. In this folder ~/Sites/app
The hook example from the Realtime PDF README. The lamp steps through the app’s own words: Watching, Running, then Reloaded.

Point Settings at a PDF.

The app opens on the viewer. Watching starts from Settings, with a picked file or a pasted path.

  1. 1

    Open the app.

  2. 2

    Click Settings.

  3. 3

    Pick a PDF or paste a PDF path.

  4. 4

    Reopen Settings to manage saved PDF history, hook definitions for the active PDF, and hook templates copied from another saved PDF.

A hook regenerates the PDF.

Each saved PDF has its own hook list, and one PDF can hold several hooks. Hook execution is debounced. In Settings the fields read When this file changes, Run this command, and In this folder. Leave the folder empty to use your home folder. Add hook appends another hook. Copy hooks from another PDF copies a template from a different saved PDF that already has hooks.

If the command regenerates the watched PDF, Realtime PDF reloads it through the existing PDF watcher.

Watch path
The source file the hook watches. Settings labels this When this file changes.
Execute command
The command that runs after that file changes. Settings labels this Run this command.
Execution path
The folder the command runs in. Settings labels this In this folder. The default is your home folder.
Enabled toggle
Disable hook stops that hook. Enable hook turns it back on. A disabled hook stays in the list.

Laravel invoice, from the README

Watch path ~/Sites/app/resources/views/pdf/invoice.blade.php. Execution path ~/Sites/app. Execute command php artisan test --filter=GenerateInvoicePdfTest.

The window remembers the file.

The window is a full-window PDF viewer powered by @embedpdf/react-pdf-viewer. The zoom level is persisted. Reopen the app and it restores the last watched PDF.

Saved history keeps every PDF you watch, together with its hooks. Missing entries stay listed. They are disabled, and you can remove them. Recent PDFs puts it this way: files that can't be found stay listed until you remove them.

When a PDF loads, the status line says the file is loaded and that Realtime PDF is watching for filesystem changes. A later reload can show Reloaded.

Install it with Homebrew.

Tap first, then install the cask named in the tap. Version 0.1.16 installs Realtime PDF.app.

brew tap dickwu/tap
brew install --cask realtime-pdf

Or download a DMG from the v0.1.16 release: Apple silicon or Intel. Changes since v0.1.15.

If macOS says the app is damaged or cannot be opened

sudo xattr -d com.apple.quarantine /Applications/Realtime\ PDF.app/

Updates check GitHub Releases

Realtime PDF checks on launch and every five minutes after that. The result lands in Settings → App version. Up to date shows the current version and a Check now button. Update available shows Update to vX.Y.Z. Clicking it downloads the minisign-signed bundle, replaces the installed .app, and relaunches. An update installs only if the signature matches the public key compiled into the running app.

The first install of any version is still a DMG or brew install --cask dickwu/tap/realtime-pdf. In-app update starts once an updater-enabled build is running. If you installed with Homebrew, brew upgrade --cask realtime-pdf also works. Both paths work. Use one of them consistently so Homebrew’s record and the installed binary do not drift.

brew upgrade --cask realtime-pdf

Build from the repository

You need Bun, a Rust toolchain, and the Tauri desktop build prerequisites for macOS. Clone dickwu/realtime-pdf, then:

bun install
bun run dev

Run the desktop app with:

bunx tauri dev

Verify with:

bun test
bunx tsc --noEmit
cargo check --manifest-path src-tauri/Cargo.toml
bunx tauri build --debug --no-bundle

Questions

What does Realtime PDF do?

Realtime PDF watches a target PDF file, reloads it when the file changes on disk, keeps a persistent saved-history list, and can run per-PDF source hooks that regenerate the PDF when related files such as Laravel Blade templates change.

Which operating systems does it run on?

Realtime PDF is a desktop PDF watcher for macOS. The Homebrew cask installs Realtime PDF.app and publishes separate DMGs for Apple silicon and Intel.

How do I install it?

Run brew tap dickwu/tap, then brew install --cask realtime-pdf. You can also download the v0.1.16 DMG from GitHub Releases. The cask homepage is https://github.com/dickwu/realtime-pdf.

What if macOS says the app is damaged or cannot be opened?

Run sudo xattr -d com.apple.quarantine /Applications/Realtime\ PDF.app/

How do I start watching a PDF?

Open the app. Click Settings. Pick a PDF or paste a PDF path. Reopen Settings to manage saved PDF history, hook definitions for the active PDF, and hook templates copied from another saved PDF.

What does a hook store?

Each saved PDF can have multiple hooks. A hook has a watch path, an execute command, an execution path, and an enabled toggle. Hook execution is debounced, and you can copy a hook template from another saved PDF. If the command regenerates the watched PDF, Realtime PDF reloads it through the existing PDF watcher.

What happens when a saved PDF is missing?

Missing entries stay in the saved history. They are disabled, and you can remove them. Files that can't be found stay listed until you remove them.

Does it remember zoom and the last PDF?

Yes. The zoom level is persisted, and Realtime PDF restores the last watched PDF when you reopen the app. The window is a full-window PDF viewer powered by @embedpdf/react-pdf-viewer.

How do updates work?

Realtime PDF checks GitHub Releases for a new version on launch and every five minutes after that. The result lands in Settings → App version. Up to date shows the current version and a Check now button. Update available shows Update to vX.Y.Z and a primary button. Clicking it downloads the signed update bundle, replaces the installed .app, and relaunches. Updates are signed with minisign at release time, so an update only installs if its signature matches the public key compiled into the running app. The first install of any version still happens via DMG download or brew install --cask dickwu/tap/realtime-pdf. In-app auto-update only kicks in once an updater-enabled build is running. If you installed via Homebrew and prefer to keep cask metadata in sync, you can also run brew upgrade --cask realtime-pdf instead of using the in-app updater. Both paths work, but using one consistently avoids version drift between Homebrew's records and the installed binary.

Where is the source?

The source repository and the cask homepage are https://github.com/dickwu/realtime-pdf. The license is MIT.