Skip to content

Latest commit

 

History

48 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

TermPDF

中文 README 点这里

TermPDF is a terminal PDF reader built with Rust, ratatui, PDFium, and the kitty image protocol.

It focuses on reader-oriented navigation for kitty-compatible terminals, with image-based PDF rendering instead of text reflow.

CHANGELOG

0.4.2

  • Added termpdf completions zsh and termpdf completions fish to generate shell completion scripts on stdout.
  • Added completion hints for PDF files, layout directories, output directories, and PDFium library paths.

0.4.1

  • Rebuilt PDF text extraction around page-wide glyph ownership and visual line geometry, improving character completeness, line bounding boxes, and inline annotation placement.
  • Added conservative two-column reading order with repeated row evidence and support for full-width and short centered headings between column regions.
  • Added text.txt to extracted layout packs with one agent- and human-readable p1.t1<TAB>content record per text line.
  • Added generated-PDF regressions for column ordering, spanning headings, table false positives, glyph containment, and fallback annotations.

0.4.0

  • Added recursive PDF image extraction, including images nested inside Form XObjects, with processed PNG assets in layout packs.
  • Added Normal-mode image focus with Tab / Shift-Tab; press y to copy the focused image as PNG without decoding all document images at startup.
  • Updated the layout schema to termpdf.layout.v2 with images.jsonl, stable image refs, transform and pixel metadata, SHA-256 hashes, and assets/*.png. termpdf grep remains compatible with v1 packs.

0.3.1

  • Added a visible block cursor in normal mode with Vim-style text cursor motions (h, j, k, l, w, b, ^, $) and count support.
  • Added visual character selection (v), visual line selection (V), visual block selection (Ctrl-v), and clipboard copy (y) as plain text using platform clipboard commands (pbcopy, wl-copy, xclip, xsel, clip).
  • Reworked the status bar: left-aligned color mode indicator (NORMAL / VISUAL / V-LINE / V-BLOCK) with a section divider before context-specific keybinding chips.
  • Normal mode shows / search, f links, m mark, F5 present, q quit; visual modes show y copy.
  • Improved PDF line clustering to use glyph center lines and vertical overlap, with a second pass that merges small inline annotations (superscripts, subscripts, footnote markers) into their source-adjacent body line instead of creating spurious single-glyph lines.
  • Changed termpdf grep to default to regular expression search; use --literal for plain text matching.

0.2.0

  • Added tmux support through Kitty graphics passthrough. Enable it in ~/.tmux.conf with set -g allow-passthrough on.
  • Added mouse and touchpad navigation for scrolling, horizontal scrolling, zooming with Ctrl + scroll, and presentation navigation.

Features

  • PDFium-backed PDF rendering
  • Kitty image protocol rendering for page images
  • Smooth scrolling across multi-page documents
  • Vim-style navigation and page jumps
  • Search with image-level highlights
  • Follow links with image-level tag overlays
  • Marks for quick navigation
  • Presentation mode
  • Dark mode toggle
  • Watch mode with live PDF reload
  • Agent and LLM-oriented layout pack extraction with stable refs
  • Vim-style visual selection with clipboard copy as plain text
  • Recursive PDF image extraction and processed PNG assets
  • Image focus and PNG clipboard copy
  • zsh and fish shell completions

Install

For Arch Linux with AUR

yay -S tpdf

For Mac:

Homebrew tap:

brew tap NiJingzhe/termpdf
brew install termpdf

Or install directly:

brew install NiJingzhe/termpdf/termpdf

Shell Completions

Generate a completion script with termpdf completions <zsh|fish>.

For zsh:

mkdir -p ~/.zfunc
termpdf completions zsh > ~/.zfunc/_termpdf

Add fpath=(~/.zfunc $fpath) before compinit in ~/.zshrc, then restart the shell.

For fish:

mkdir -p ~/.config/fish/completions
termpdf completions fish > ~/.config/fish/completions/termpdf.fish

Manual Install

Runtime Requirements

  • A supported release platform:
    • aarch64-apple-darwin
    • x86_64-unknown-linux-gnu
    • aarch64-unknown-linux-gnu
  • A terminal with kitty graphics protocol support, such as kitty or ghostty
  • tmux is supported when the outer terminal supports Kitty graphics and set -g allow-passthrough on is enabled in ~/.tmux.conf; TermPDF wraps Kitty image commands in tmux passthrough automatically
  • termpdf and the matching packaged libpdfium in the same directory, unless you explicitly point to another PDFium build with PDFIUM_LIB_PATH or --pdfium-lib

Install From A Release Archive

Download the archive for your platform from the GitHub Releases page, then extract it:

tar -xzf termpdf-0.4.2-x86_64-unknown-linux-gnu.tar.gz
cd termpdf-0.4.2-x86_64-unknown-linux-gnu
./termpdf path/to/file.pdf

Each release archive contains:

  • termpdf
  • the matching packaged libpdfium
  • LICENSE
  • README.md

If you install the files manually into the filesystem, keep termpdf and libpdfium.so or libpdfium.dylib together in the same directory.

Build From Source

Build dependencies:

  • Rust stable toolchain with cargo
  • gh or curl and tar when using bundled PDFium variants (not required for TERMPDF_PDFIUM_VARIANT=SYSTEM)
  • A supported PDFium bundle variant, or another compatible PDFium dynamic library

Set the PDFium variant with an environment variable and build:

TERMPDF_PDFIUM_VARIANT=linux-x64-glibc cargo build --release
./target/release/termpdf path/to/file.pdf

Supported source-build values for TERMPDF_PDFIUM_VARIANT:

  • macos-arm64
  • linux-x64-glibc
  • linux-arm64-glibc
  • SYSTEM

When using a bundled variant, TermPDF automatically downloads the matching PDFium archive from bblanchon/pdfium-binaries into .cache/pdfium/, extracts it, and then copies the matching libpdfium next to the binary in target/<profile>/.

When set to SYSTEM, the build skips PDFium download/copy in build.rs and uses your system PDFium at runtime (or a path provided by PDFIUM_LIB_PATH / --pdfium-lib).

Packaging Notes

The binary looks for a packaged PDFium library next to itself first. For manual packaging, distro packaging, or AUR packaging, install the real executable and the matching PDFium library into the same directory.

A working Linux layout is:

/usr/lib/termpdf/termpdf
/usr/lib/termpdf/libpdfium.so
/usr/bin/termpdf

Where /usr/bin/termpdf is a small wrapper:

#!/usr/bin/env bash
exec /usr/lib/termpdf/termpdf "$@"

For an AUR source package on x86_64, the build step should be equivalent to:

TERMPDF_PDFIUM_VARIANT=linux-x64-glibc cargo build --release

For an AUR binary package on x86_64, unpack the release tarball and install the bundled termpdf and libpdfium.so together without separating them.

Usage

For source builds, set TERMPDF_PDFIUM_VARIANT to the bundle that matches your machine, or set it to SYSTEM to use system PDFium.

TERMPDF_PDFIUM_VARIANT=linux-x64-glibc cargo run -- path/to/file.pdf

Watch mode:

TERMPDF_PDFIUM_VARIANT=linux-x64-glibc cargo run -- path/to/file.pdf -w

If PDFium is not available in the system library path, TermPDF will try the downloaded cache under .cache/pdfium/. You can also point to a PDFium build explicitly:

cargo run -- path/to/file.pdf --pdfium-lib /path/to/pdfium

Layout Pack Extraction

TermPDF can extract a stable layout pack for agents, LLMs, search pipelines, and other CLI tools:

termpdf extract path/to/file.pdf --out path/to/file.layout

If --out is omitted, TermPDF writes next to the source PDF with a .layout suffix:

termpdf extract paper.pdf
# writes paper.layout/

Use --overwrite to replace an existing TermPDF layout pack:

termpdf extract paper.pdf --overwrite

Each layout pack contains:

  • manifest.json: schema, TermPDF version, source PDF hash, coordinate system, and file map
  • pages.jsonl: one page record per line
  • blocks.jsonl: text line and link records
  • text.txt: plain reading-order text with p1.t1<TAB>content line markers
  • glyphs.jsonl: one precise glyph record per visible character
  • images.jsonl: image bbox, transform matrix, source pixel dimensions, PNG path, and SHA-256
  • refs.jsonl: a global reference registry for quick lookup
  • assets/: processed PNG files that can be opened directly by filesystem and image tools

Image extraction recursively traverses Form XObjects, so images embedded inside reusable PDF forms are included. PNG assets are decoded and processed during extract; the viewer keeps only lightweight metadata and decodes one image on demand when it is copied.

Stable refs use one-based, type-namespaced addresses:

p1           page 1
p1.t1        page 1, text line 1
p1.t1.c1     page 1, text line 1, character 1
p1.link1     page 1, link 1
p1.image1    page 1, image 1 (`assets/p1.image1.png`)

text.txt is the human- and agent-friendly view of the extracted text. It keeps one physical PDF text line per output line, prefixes it with the stable page/text-line ref, and separates the ref from the content with one tab:

p1.t1\tSyzSpec: Specification Generation for Linux Kernel Fuzzing via
p1.t2\tUnder-Constrained Symbolic Execution

The layout schema is termpdf.layout.v2. Bboxes use PDF points with a bottom-left origin, matching PDFium extraction and TermPDF rendering projection. termpdf grep also accepts legacy termpdf.layout.v1 packs.

Search a layout pack and return stable refs with grep:

termpdf grep "method" paper.layout
termpdf grep "method" paper.layout --refs-only
termpdf grep "method|approach" paper.layout --json
termpdf grep "literal.dot" paper.layout --literal

By default, grep treats the pattern as a regular expression and prints ref<TAB>text. Use --ignore-case for case-insensitive search and --literal when the pattern should be treated as plain text.

Build Environment

TERMPDF_PDFIUM_VARIANT selects which PDFium dynamic library Cargo should download and copy next to the built binary.

Supported values:

  • macos-arm64
  • linux-x64-glibc
  • linux-arm64-glibc
  • SYSTEM (skip download/copy; use system PDFium)

Example:

TERMPDF_PDFIUM_VARIANT=linux-x64-glibc cargo build --release

TERMPDF_PDFIUM_VARIANT is the recommended path for development, packaging, and CI because it keeps the build configuration explicit and local to the command being run.

Bundled PDFium Variants

The build currently supports automatic PDFium downloads for:

  • macos-arm64
  • linux-x64-glibc
  • linux-arm64-glibc

When TERMPDF_PDFIUM_VARIANT is set to one of the bundled variants above, build.rs downloads the matching PDFium archive if needed, caches it in .cache/pdfium/, and copies the matching libpdfium into target/<profile>/, so both cargo run and the final executable can load the packaged dynamic library from the binary directory.

When TERMPDF_PDFIUM_VARIANT=SYSTEM, build.rs skips bundling and relies on system PDFium resolution at runtime.

The older Cargo feature based bundle selection still works, but the recommended path for development is the environment variable above.

To refresh the vendored PDFium archives from upstream, run:

./scripts/fetch_pdfium.sh linux-x64-glibc

Releases

Tagged releases build artifacts for the currently supported packaged targets:

  • aarch64-apple-darwin
  • x86_64-unknown-linux-gnu
  • aarch64-unknown-linux-gnu

Each release archive contains:

  • termpdf
  • the matching packaged libpdfium
  • LICENSE
  • README.md

Keybindings

  • h / j / k / l: move the text cursor
  • w / b / ^ / $: move by word or line boundary
  • H / J / K / L: pan viewport
  • Ctrl-u / Ctrl-d: half-page up/down
  • Ctrl-b / Ctrl-f: full-page back/forward
  • gg, {count}gg, G: jump to page
  • /, n, N, Esc: search, navigate results, hide highlights
  • f / F: follow visible links
  • v: visual character selection
  • V: visual line selection
  • Ctrl-v: visual block selection
  • Tab / Shift-Tab: focus the next/previous extracted PDF image
  • y: copy the focused image as PNG, or copy the active visual selection as plain text
  • m<char> / `<char>: set and jump to marks
  • F5: presentation mode
  • = / - / 0: zoom in / out / reset
  • i: toggle dark mode
  • q: quit

Status

This project is under active development.

About

A terminal PDF reader built for both human and agent with Rust, ratatui, PDFium, and the kitty image protocol, with smooth scrolling, link following, search, marks, presentation mode, and live watch reload

Topics

Resources

Stars

5 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages