← All projects

PaperDistill

Batch-convert scientific PDFs into structured, AI-ready Markdown

PaperDistill is a desktop application. Point it at a folder of PDFs, a prompt file describing the structure you want extracted, and an output folder — it writes one Markdown file per PDF, using Anthropic, OpenAI, or a local Ollama model.

It never invents content: extraction is driven entirely by your prompt and the text pulled from the PDF. The default instruction tells the model to work only from the provided text and to write Not found in PDF rather than guess.

Download

PlatformFileVersionSize
Linux PaperDistill-0.1.1.AppImage — portable, no install 0.1.1 150 MB

Checksums: SHA256SUMS.txt.

Linux only here. There is no Windows or macOS download on this server — a Windows installer has to be built on Windows, and there is no Mac to build on. On either, build from source; the steps are below and need no admin rights either.
Not code-signed. Nothing here is signed, so nothing can vouch for it but the checksum. Verify it before you run it — the command is below — and if you did not expect to be downloading this, don't.

Run it on Linux

The AppImage is a single self-contained file. Nothing to install, nothing to uninstall, no sudo anywhere. Download it, make it executable, run it:

curl -O https://pina.dedyn.io/release/PaperDistill-0.1.1.AppImage
chmod +x PaperDistill-0.1.1.AppImage
./PaperDistill-0.1.1.AppImage
If it fails with a FUSE errordlopen(): error loading libfuse.so.2 — your distribution ships FUSE 3 and AppImages still want FUSE 2. Ubuntu 22.04 and later are the common case. Either install the compatibility library, or skip FUSE entirely:
sudo apt install libfuse2                                  # option 1
./PaperDistill-0.1.1.AppImage --appimage-extract-and-run   # option 2, no root needed

Verify the download

sha256sum PaperDistill-0.1.1.AppImage

The result must match the line in SHA256SUMS.txt:

69b4e28372b3c1ce261a78e0a0b5daba087957dfb5f1bc8867df1626638590f5

Build from source

Needs Node 20+ and access to the repository, which is private. This is also the route for Windows and macOS.

git clone [email protected]:pvnazarov/PaperDistill.git
cd PaperDistill
npm install
npm run dev        # run it
npm test           # 46 tests
npm run package    # build for the platform you are on, into release/

Verified on Linux with Node 24 and Node 26: dependencies install, all 46 tests pass, and the packaging step produces the AppImage offered above. npm run package builds only for the platform you run it on.

Set up a model

PaperDistill has no LLM of its own — you bring one.

ProviderWhat you need
AnthropicAn API key, pasted into the app. It is held in memory for that session only and never written to disk. Model name, e.g. claude-sonnet-4-5.
OpenAIAn API key, pasted the same way. Model name, e.g. gpt-4o.
OllamaNothing — no key, no account. Run ollama serve locally, pull a model, and use Test Connection against the default http://localhost:11434. Your PDFs never leave your machine this way.

To avoid pasting a key each session, set ANTHROPIC_API_KEY or OPENAI_API_KEY in the environment before launching. The app reads the environment it was started with and never overrides a variable that is already set.

Using it

  1. Select a PDF folder, an output folder, and a prompt. Two prompts ship with the app and need no file picking: Use Papers Prompt for published papers, and Use Proposals Prompt for research and grant proposals — work packages, deliverables, planned cohorts, partners, and which methods were proposed for which data. Either is a working starting point to copy and edit.
  2. Choose a provider and model.
  3. Scan PDFs — extracts text from each and flags likely scanned or image-only PDFs, which are skipped rather than sent to the model.
  4. Start. Pause, Resume and Cancel all work mid-run.

For each PDF you get <name>.md plus a <name>.paperdistill.json sidecar recording provider, model, page count and status, and one paperdistill_run_log.jsonl for the whole run. Existing .md files are never overwritten unless you ask.

Your prompt can use {{PDF_TEXT}}, {{PDF_FILENAME}}, {{PDF_PATH}} and {{PAGE_COUNT}}. If you use none of them, the extracted text is appended after your prompt — so plain English works fine.

Known limits