Skip to content

whit3rabbit/unlocr

Repository files navigation

██╗   ██╗███╗   ██╗██╗      ██████╗  ██████╗██████╗
██║   ██║████╗  ██║██║     ██╔═══██╗██╔════╝██╔══██╗
██║   ██║██╔██╗ ██║██║     ██║   ██║██║     ██████╔╝
██║   ██║██║╚██╗██║██║     ██║   ██║██║     ██╔══██╗
╚██████╔╝██║ ╚████║███████╗╚██████╔╝╚██████╗██║  ██║
 ╚═════╝ ╚═╝  ╚═══╝╚══════╝ ╚═════╝  ╚═════╝╚═╝  ╚═╝

GUI/CLI for unlimited-ocr

CI Crates.io GitHub release License

English | 简体中文

unlocr screenshot

Not affiliated with Unlimited OCR but a wrapper/GUI around Unlimited OCR

A fast, lightweight tool to OCR PDFs into clean Markdown. It is powered by the Unlimited-OCR model (DeepSeek-OCR 3B VLM) running locally via llama.cpp (GGUF).

Currently, a WIP and has pretty tough system requirements. Do not expect it to work on low end devices. This was created to use unlimited-ocr on local computer and it is not affiliated with the original unlimited-ocr.

This is vibe coded so don't expect everything to be perfect. Feel free to submit PR's. UI was done in Claude Design.

Key Features

  • Local & Secure: Runs entirely offline on your CPU or GPU.
  • Auto-cached: Model weights download automatically from Hugging Face on first run.
  • High Performance: Uses a single persistent llama-server background process to avoid reloading overhead across pages.
  • Flexible Engines: Supports GGUF (default, via llama.cpp) or the full unquantized model on GPU (via vLLM/SGLang).
  • Multi-Platform: Available for macOS, Linux, and Windows as both a CLI and a Desktop GUI application.

Requirements

To run unlocr, you need:

  1. poppler (provides pdftoppm for rasterizing PDF pages to images).
  2. llama-server — a patched llama.cpp build carrying the Unlimited-OCR R-SWA support from PR #24975. That PR is not yet merged upstream, so stock/Homebrew/apt builds do not work. unlocr downloads its own patched build for you (CLI and GUI) on first run — you do not install it manually. See the note below.
  3. pandoc (optional) — only for the GUI's "export to DOCX/ODT/RTF/HTML/TXT" feature. OCR works without it.
  4. Rust Toolchain (only if building from source or installing via cargo).

How prerequisites are provided (per platform)

Both the CLI and the Desktop GUI auto-download the sha256-pinned patched llama-server into the app cache on first run (macOS arm64/x64, Linux x64, Windows x64; CPU build, macOS with Metal). You only supply pdftoppm:

OS poppler (pdftoppm) llama-server (patched R-SWA build) pandoc (export)
Windows GUI downloads it for you auto-downloaded (CLI + GUI) GUI downloads it for you
Linux installed by the .deb/.rpm (declared dep) auto-downloaded (CLI + GUI, x86_64) installed by the .deb/.rpm (recommended dep)
macOS brew install poppler (cask dep) auto-downloaded (CLI + GUI) GUI downloads it, or brew install pandoc

Note

The patched llama-server is built by unlocr's own CI (build-llama.yml) and hosted on a dedicated llama-rswa-* GitHub release. In the GUI, Settings → Dependencies shows what is found/missing and can (re)download it. If you point unlocr at your OWN llama-server (--llama-bin, or one on PATH/Homebrew), it is used but you get a warning that it cannot be verified for R-SWA support; silence it with UNLOCR_ALLOW_EXTERNAL_LLAMA=1. GPU users (CUDA/Vulkan) should build llama.cpp from PR #24975 themselves and pass --llama-bin.

Model Variants & System Specs

By default, unlocr runs a quantized GGUF on llama.cpp (CPU or GPU-offloaded). You can also run the full, unquantized model on a dedicated GPU via vLLM.

Mode Variant Download Size RAM/VRAM Required Engine Quality Flag
GGUF Q4_K_M 1.82 GB ~4 GB RAM llama.cpp --quality less
GGUF Q8_0 (Default) 2.91 GB ~6 GB RAM llama.cpp --quality good
GGUF BF16 5.47 GB ~8 GB RAM llama.cpp --quality best
Full Model DeepSeek-OCR ~6.7 GB 16 GB+ VRAM vLLM --gpu

How to Install by OS

All installation files (pre-built binaries, desktop installers, and packages) are available on the GitHub Releases page.

  • macOS (Apple Silicon & Intel):
    • GUI (Desktop App): Download the .dmg installer from Releases (or install via Homebrew Cask: brew install --cask whit3rabbit/tap/unlocr)
    • CLI: brew install whit3rabbit/tap/unlocr
  • Windows:
    • GUI: Download the .msi installer from Releases
    • CLI: Download the CLI zip file from Releases
  • Linux:
    • GUI: Download the .AppImage, .deb, or .rpm package from Releases
    • CLI: Download the .tar.gz package from Releases

macOS

Homebrew is required for poppler (unlocr auto-downloads the patched llama-server itself; do NOT brew install llama.cpp — the Homebrew build lacks R-SWA). Install the prerequisite:

brew install poppler   # pandoc optional, only for GUI export: brew install pandoc

Then install unlocr using Homebrew:

# Install the CLI tool
brew install whit3rabbit/tap/unlocr

# Or install the GUI Desktop App
brew install --cask whit3rabbit/tap/unlocr

Note

For the unsigned macOS GUI app, Homebrew handles quarantine flags automatically. If downloading manually, run: xattr -dr com.apple.quarantine "/Applications/unlocr.app"

Linux

  1. Download the pre-built CLI binary or GUI installer (.AppImage, .deb, .rpm) from GitHub Releases.
  2. The .deb/.rpm declares poppler (and pandoc for GUI export) as dependencies, so your package manager pulls them in automatically.
  3. llama-server is auto-downloaded (x86_64) — unlocr fetches its patched R-SWA build (PR #24975) into the app cache on first run; you do not install llama.cpp manually. (Other arches, e.g. arm64, have no pinned download: build llama.cpp from PR #24975 and pass --llama-bin.)

Windows

  1. Download the CLI executable or the Windows GUI Installer (.msi) from GitHub Releases.
  2. GUI: no manual setup — open Settings → Dependencies and click Download for any missing tool. The GUI fetches sha256-pinned pdftoppm, the patched llama-server, and pandoc into its cache (GPU users should build llama.cpp from PR #24975 and pass --llama-bin).
  3. CLI: the patched llama-server auto-downloads on first run; just ensure pdftoppm is on your PATH, then run the installer or script:
    powershell -ExecutionPolicy Bypass -File packaging\windows\install.ps1

Alternative: Install via Cargo (CLI)

If you have the Rust toolchain installed:

cargo install unlocr

Alternative: Build from Source

# Clone the repository and run the install script (macOS/Linux)
./install.sh

(For Windows source installation details, see packaging/README.md.)


How to Run

Desktop GUI App

Simply launch the installed unlocr application from your OS Applications folder (or Start Menu). The GUI provides an intuitive interface to load PDFs, select quality presets, customize prompts, and start the OCR process.

CLI Tool

Run unlocr by passing one or more PDFs:

unlocr <input.pdf> [more.pdf ...] [options]

Example:

unlocr report.pdf --out ./out --quality best
# Generates ./out/report.md with page-delimited <!-- page N --> markers

Developer Reference & CLI Arguments

For a complete, in-depth guide on all CLI arguments, sampling configurations, and advanced setups, see docs/CLI.md.

CLI Arguments & Options

Option Default Description
--out DIR . Output directory for the converted Markdown files.
-o, --output FILE (from input name) Single output file path (single-input only). .md appended when no extension; joined under --out when relative.
--recursive false Recurse into subdirectories when an input is a folder.
--from-list FILE (none) Read extra PDF paths from a text file (one per line; # comments and blank lines skipped).
--password PW UNLOCR_PDF_PASSWORD User/open password for encrypted PDFs. --password overrides the env var. Prefer the UNLOCR_PDF_PASSWORD env var or --password-file to keep the secret out of your shell history and unlocr's own argv. (Poppler still receives it as -upw, so it appears in the process list while pdfinfo/pdftoppm run, whichever source you use.)
--password-file FILE (none) Text file of candidate PDF passwords (one per line; # comments and blank lines skipped). Each PDF is tried against every password until one unlocks it, so a batch with different passwords works. A PDF no password unlocks is skipped (reported), and the rest of the batch continues.
--quality TIER good Quality preset. Options: best (BF16), good (Q8_0), less (Q4_K_M).
--quant TAG (from quality) Exact Hugging Face model quant tag (e.g. Q6_K, IQ4_XS). Overrides --quality.
--model PATH (HF download) Use this GGUF directly, skipping the HF download and naming convention. Disables --quant/--quality/--model-dir selection.
--mmproj PATH (cached projector) Projector (mmproj) GGUF override. Requires --model.
--max-tokens N 4096 Max tokens generated per page (prevents infinite loop/runaways on dense pages).
--pages RANGE (all) Pages to OCR: a single page (5) or inclusive 1-based range (5-9). Applies to every input.
--task PRESET markdown Prompt preset: markdown (clean md), grounding (md + layout coordinates), free (plain text), figure (parses charts/figures).
--prompt TEXT (from task) Custom OCR prompt. Overrides --task. Use `<
--dpi N 144 PDF page rendering DPI (higher DPI gives larger/clearer source images).
--image-max-tokens N (model default) Vision-token budget for llama-server (local mode only). Higher means finer detail recognition but slower/more VRAM.
--chat-template NAME (model default) Forwarded to llama-server --chat-template (e.g., deepseek-ocr); local mode only.
--repeat-penalty F 1.3 (local GGUF) / (server default) (--endpoint/--gpu) Sampling repeat penalty; helps break generation loops in smaller quants.
--llama-bin PATH Auto-detected Path to the llama-server binary.
--model-dir PATH OS Cache Custom cache directory for GGUF model downloads.
--port N 0 (Auto) Port for the spawned llama-server.
--keep-images false Retain the intermediate page PNGs generated during processing.
--gpu false Run the full DeepSeek-OCR model via local vLLM. Shortcut for --endpoint http://localhost:8000 --endpoint-model deepseek-ai/DeepSeek-OCR.
--endpoint URL Local spawn Route requests to a remote OpenAI-compatible server (vLLM, SGLang, etc.) and skip local spawn.
--endpoint-key KEY UNLOCR_API_KEY Bearer API token for --endpoint (or set via UNLOCR_API_KEY env var).
--endpoint-model M (none) Model name sent in endpoint request body (required by vLLM/LiteLLM gateways).

Subcommands: unlocr doctor (alias preflight) validates system deps, model files, RAM, and disk space without running OCR. Accepts --llama-bin, --model-dir, --quant.

How It Works Under the Hood

  1. Preflight: Resolves llama-server (preferring unlocr's cached patched R-SWA build, auto-downloading it if absent) and locates pdftoppm. An external llama-server (--llama-bin/PATH) is used with a warning that it cannot be verified for R-SWA support (silence via UNLOCR_ALLOW_EXTERNAL_LLAMA=1).
  2. Model Cache: Checks for Unlimited-OCR-<quant>.gguf and mmproj-Unlimited-OCR-F16.gguf in the cache directory, downloading them from HF if missing.
  3. Spawn Server: Starts a single background llama-server instance and polls /health until active.
  4. OCR Processing: For each PDF, runs pdftoppm to extract pages as PNGs, POSTs them sequentially (base64 encoded) to /v1/chat/completions, and appends the markdown output.

Model Caching

GGUFs are cached locally. They can be quite large (~1.8 GB to ~8.0 GB total depending on quants downloaded).

OS Default Cache Path
macOS ~/Library/Caches/unlocr
Linux $XDG_CACHE_HOME/unlocr (or ~/.cache/unlocr)
Windows %LOCALAPPDATA%\unlocr

Override the path using --model-dir PATH or the $XDG_CACHE_HOME env var.

Uninstalling & Reclaiming Space

To remove the application binary and purge downloaded model weights, run:

  • macOS/Linux: ./uninstall.sh
  • Windows: powershell -ExecutionPolicy Bypass -File packaging\windows\uninstall.ps1

Running the Full Model on GPU (vLLM)

For high-performance GPU serving of the unquantized model:

  1. Install vLLM (pre-release recommended for DeepSeek-OCR support):
    pip install -U vllm --pre --extra-index-url https://wheels.vllm.ai/nightly
  2. Serve the model:
    vllm serve deepseek-ai/DeepSeek-OCR \
      --no-enable-prefix-caching \
      --mm-processor-cache-gb 0 \
      --logits-processors vllm.model_executor.models.deepseek_ocr:NGramPerReqLogitsProcessor
  3. Run unlocr targeting this endpoint:
    unlocr report.pdf --gpu
    (In the GUI, select the GPU full model (vLLM · DeepSeek-OCR) engine preset.)

Tip

Google Colab: Check out the Google Colab notebooks to run the full GPU pipeline on a free Colab T4 cloud instance:

Unofficial Benchmark

  • Hardware: macOS (Apple Silicon, Metal)
  • llama.cpp: build b9770
  • Model: BF16 (--quality best, 5.47GB)
  • Document: 355-page book PDF (~12.4MB), 144 DPI
Metric Result
Cold Start (Model Loaded) ~15 seconds
Total Processing Time 42 min 44 s (~7.2s/page)
Output size 1.2 MB markdown (~192k words)

Smaller quants (--quality good / less) trade off accuracy for much faster speeds and smaller downloads.

Limitations & Security

  • Ctrl-C (SIGINT): Interrupting CLI does not clean up the background server process, which might orphan llama-server.
  • Abnormal exit (macOS): If the app is force-killed (SIGKILL/segfault) or panics (panic=abort), cleanup is skipped. Linux (PR_SET_PDEATHSIG) and Windows (Job Objects) kill llama-server with the parent; macOS has no equivalent, so a warm server can be orphaned. Recover with pkill llama-server.
  • Port Race: Free-port allocation may occasionally conflict; pin using --port N.
  • Authentication: The local llama-server binds to 127.0.0.1 without auth. On multi-user machines, other local users could access the server port during execution. Single-user environments are recommended.
  • Repetition loops on blank/ruled/low-content pages: The underlying Unlimited-OCR/DeepSeek-OCR model can degenerate into repetitive or hallucinated output (e.g. rambling about "the Ground Truth image" instead of transcribing) on blank regions, ruled/underscore lines, or other low-content input. This is an open, currently unresolved upstream model issue (deepseek-ai/DeepSeek-OCR#151), not a bug in unlocr's prompt: upstream's vLLM/SGLang serving suppresses it with a custom n-gram-repetition logits processor that has no llama.cpp/GGUF equivalent. If you hit this, first confirm you are on unlocr's managed R-SWA build, not a stock/PATH/Homebrew llama-server: an unpatched build cannot load the vision tower and is the most common cause of ocr-ocr-style loops (the GUI pipeline shows an amber "external" flag when it is; the CLI doctor prints the provenance). Then try the anti-loop DRY knobs the community found for dense/math pages: --dry-allowed-length 2 --dry-penalty-last-n -1 (the GUI's Anti-loop (dense pages) toggle sets both), raising --repeat-penalty (e.g. 1.5), raising --dry-multiplier, or using a higher-precision quant (--quality best/good over less). A page whose generation hits --max-tokens without a natural stop is flagged with a warning (likely a repetition loop) rather than silently written out as if it were real text.

License

The unlocr codebase is released under the MIT License. Note that model weights downloaded automatically from Hugging Face are governed by their respective licenses (see HF model card).

About

Convert PDF to markdown using a GUI/CLI for Unlimited-OCR. Uses GGUF models

Topics

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Packages

 
 
 

Contributors