PhiTeX

A fast, modern
TeX compiler.

Incremental, parallel, and byte-identical to pdfTeX and XeTeX.

Edit, and only what changed is rebuilt: a word in a 400-page thesis in milliseconds. One process to the fixed point, BibTeX and makeindex included, no second pass. It runs on your machine from a single phitex binary, and phitex watch serves a live preview in your browser that redraws only the pages you changed.

  • ~10msa word edit in a 64-page thesis, rebuilt
  • byte-identicalto pdfTeX 1.40.29, cold and after every edit
  • oneprocessBibTeX & makeindex folded in, no second pass
~/thesis — phitex watch

      

The compiler itself. A phitex watch session: a cold build, then each edit rebuilt on its own. The status line, progress bar and sparkline are the real TUI; per-edit times are illustrative, within the measured native range.

Instant.

Only what you touched is rebuilt. A word edit in a 64-page thesis lands in about 10 ms. You forget a compile step was ever there.

Open Source & Private.

PhiTeX compiles on your computer. Your thesis, your grant, your unpublished paper: none of it leaves your machine.

Exact.

Byte for byte the PDF pdfTeX and XeTeX would make. And the instant result always equals a full rebuild.

§1 A better way to write

Write. PhiTeX handles the rest.

A compiler you never wait for, never fight, and never have to think about.

References settle themselves

\ref, \cite, the table of contents, the index: no more “run it twice”. PhiTeX repeats what it must until nothing changes, and only that.

Big documents stay instant

A 400-page thesis edits as fast as a one-page letter. PhiTeX rebuilds the paragraph you touched and the pages it moved, never the whole book.

Click the page, land in the source

Click any word in the PDF and your cursor jumps to it. Select text in the editor and it lights up on the page. Both ways, always in sync.

Works offline

On a plane, in a library basement, behind a firewall: PhiTeX needs no server and no connection. Your document compiles where you are.

Easy on the eyes

Dark mode for the page as well as the editor, crisp at any zoom, and text you can select, copy and search, because the preview is vector, not an image.

Your packages, your fonts

LaTeX with the packages you already use, BibTeX and biber, Unicode and OpenType fonts, SyncTeX: click the page to jump to the source.

§1.1 Friendly errors

Errors that point at the line.

No wall of log. The preview says why the page looks the way it does, at the line to look at, and it never breaks. Incomplete input doesn't trap: an open { just runs to the end, and the last good page stays up, dimmed, with a banner saying why.

  • warning{ never closed: the group runs to the end of the filemain.tex:12 · unclosed-brace
  • warning\input chapter2: no such file in the projectmain.tex:15 · missing-file
  • infoï: this font has no glyph for it; using Latin Modernmain.tex:16 · font-fallback
  • error\cite{knuth84}: no such entry in refs.bibmain.tex:17 · missing-citation

Every message comes from the compiler itself, with the exact place in your source. There's a --json mode for tools too.

§2 One engine, everywhere

Works where you write.

The same compiler, the same instant page, in the editor you already use.

thesis · Overleafextension
⚡ Instant
⚡ 9 ms

Overleaf

One switch in the PDF toolbar, and the page follows your typing. Collaborators' edits too.

main.tex — VS Codeextension
EXPLORERmain.texbook.tex
PhiTeX preview
⚡ 7 ms

VS Code

A live page beside your editor, errors in the Problems panel, click-to-source both ways.

~/PhiTeX — zshtoday

The CLI

phitex watch rebuilds on every save and serves a live preview in your browser, the same viewer the extensions use. Scriptable and CI-friendly.

§3 Try it

Type in it. The page follows.

The same engine, compiled to WebAssembly and running on this page. No server, nothing uploaded. Type, and it repaints on every keystroke, or pick another file on the left.

main.tex — thesis runs locally · WebAssembly
main.tex
Live preview Fit ▾
⚡ 9 ms · 1 of 12 chunks

Type in it. A design preview of PhiTeX's own editor, running in your browser. It repaints on every keystroke, no Recompile. Pick another file on the left.

§4 Also on Overleaf

Already write on Overleaf? PhiTeX runs there too.

A browser extension adds a PDF | ⚡ Instant switch to Overleaf's toolbar: the same compiler, in your browser, repainting as you type. Nothing leaves it, and your editor is untouched.

PhiTeX for Overleaf →
OverleafShare
RecompilePDF⚡ Instant

§5 For VS Code

Your editor, too.

The same instant preview beside your editor: a live page that follows your typing, errors in the Problems panel, and click-to-source both ways.

It's the same engine and the same session as the Overleaf extension, in a webview.

Install for VS Code

§5.1 In the CLI

A CLI, and a library.

One binary, for any OS. phitex build main.tex writes your PDF, and phitex watch keeps it up to date as you save, serving a live page in your browser that repaints only the pages that changed. No editor plugin needed. There's also a Rust library to embed it in your own tools, plus --ssa to see your document the way the compiler does.

$ phitex --ssa examples/phi.tex
; l.1  \count1=0
%0 = prim count
%1 = %0(1, 0)                 ; \count1 = 0
…
%21 = φ(%7, %20, %1)          ; \count1 (then)

§6 Numbers

How fast it actually is.

Native figures from the compiler's benches, and keystroke→page figures from the same engine in Chromium.

~10ms

a word edit in a 64-page thesis, rebuilt natively with phitex

8.7ms

keystroke → page on real Overleaf, 46 keys through CDP key input

0.1–0.3ms

the core's edit, even on a 185 KB, 38-page document

24→ 2

fast keystrokes, coalesced into 2 builds. One build is in flight at a time, and the rest merge.

The core, per document (V8, medians of 11)
documentpagesopenfirst paintfixed pointfresh-build check
3 paragraphs116 ms0.06–0.09 mssame0.8 ms
200 paragraphs, 18 KB410 ms0.10–0.26 mssame5.2 ms
2000 paragraphs, 185 KB3862 ms0.23–0.26 ms0.26–0.28 ms47 ms
book.tex + main (refs, .aux loop)615 ms0.14–0.21 mssame8.8 ms

Browser figures: phitex-overleaf REPORT.md, “Measured latencies”, from bench/latency.mjs. Native figures: the PhiTeX repository's bench/.

§7 For engineers: how it works

How is it this fast?
Your document is a program.

PhiTeX compiles TeX the way compilers like LLVM compile code: into SSA (static single assignment), where every value is defined exactly once. Then, through a second IR for the pages, it knows precisely what each edit changed, and rebuilds only that.

01

Files, through one layer

Every file comes through PhiTeX's virtual file layer. Each has its own tree and can be edited. The build's own files are values too, read like any file: the .aux (what was written to it), and the .bbl and .ind that BibTeX and makeindex make.

02

A lossless tree, by paragraph

The CST's children are paragraphs, up to their blank lines, each with an id. An edit reparses only the paragraphs it touched, until the old boundaries come back, and hands back a splice.

03

SSA, in chunks

Every value (a primitive, a macro, a catcode table, a register, a paragraph) is defined once, and every use points at the one value it means. The SSA is cut into chunks, one per paragraph, or per run of paragraphs that a group, a conditional or a macro call spans. Each chunk records its imports (what the names it read meant) and its exports.

04

Pages, painted first

Each chunk's material flows into the page state. Where a page is full, the output routine runs as an output chunk: kept if its page is the same, built again if not. The page you are looking at is painted first. The rest catch up after.

05

The fixed point, down to PDF

The .aux, .bbl and .ind are the only back edges (μ). Only the chunks that read a μ that changed are built again, and the loop runs until nothing changes. That is the document's fixed point, the same whether it was reached from nothing or from the last build. Then each page's PDF stream is written, and a page that didn't change reuses its stream.

§7.1 One keystroke

Touch one paragraph. One chunk lights up.

An edit rebuilds the chunks it touched. Then it walks the rest: a chunk whose imports all mean what they meant is kept, untouched. A node whose value comes out equal wakes nothing (early cutoff). Change a macro's body, and exactly its readers light up.

rebuiltimports checked, keptuntouched

Illustration of the rule. The demo's own counts appear under the demo above.

§7.2 One graph, one engine

Multi-tier, delta-driven.

The document is one graph of typed nodes, run by one agenda. Deltas flow down the tiers, and stop where a value comes out equal.

tier 1

Source chunks

Read names by position. Equal imports: kept.

tier 2

Fragments

Each adds its chunk's material to the page state. Equal state after: stop.

tier 3

Output chunks

The output routine, one per page. Same page: kept.

μ

Loop-carried

.aux, .bbl, .ind: the only back edges, iterated to the fixed point.

on every core

Multithreaded

Typesetting is TeX's own algorithms, ported from tex.web as pure functions: line breaking, hyphenation, math, the page builder. Each is memoized and runs in parallel, on every core you have.

§8 FAQ

Questions.

Is my document uploaded?

No. On this page and in the browser extension, everything runs locally as WebAssembly; the phitex CLI runs on your own machine. The extension's only requests go to overleaf.com, as you, for your own project's files, the same way the editor gets them. No analytics, no server, no remote code. This site makes no third-party requests either: its fonts and libraries are bundled.

Does it compile my LaTeX thesis?

Yes. It handles LaTeX with your packages, BibTeX and biber, Unicode and OpenType fonts, and the PDF matches pdfTeX and XeTeX byte for byte. LuaTeX is planned.

What does “incremental = fresh build” mean?

It's PhiTeX's core invariant: after any sequence of edits, the incremental program equals a fresh build of the same text. The tests check it after random edits, and the extension can check it live against a fresh build.

Why SSA?

In SSA, every value is defined once, and every use points at the one value it means. Names exist only while the program is built. That makes “what did this edit change?” a question about values, so a chunk whose imports mean the same is simply kept.

What does it cost?

Nothing. PhiTeX is free and open source.

Is it open source?

Yes. The PhiTeX engine is free software under the GNU Affero General Public License v3.0 (AGPL-3.0-only).