fancy-cat renders PDF pages in a Kitty terminal
PDF reader for terminal emulators using the Kitty image protocol
At a glance
- What is it?
- fancy-cat is a Zig command line PDF viewer for terminal emulators that support the Kitty image protocol, with a Neovim-like modal interface, page navigation, zoom and a JSON config file. Building it needs a specific Zig version and a terminal with the Kitty image protocol.
- Who is it for?
- Adopt fancy-cat if you read PDFs from a terminal and your emulator supports the Kitty image protocol, since the whole tool is a single binary with a modal interface and a JSON config. Skip it if your terminal does not implement that protocol, because there is no fallback rendering path, and skip it if you want to read documents in a dedicated viewer with text selection.
- Can I use it commercially?
- Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
- Is it still maintained?
- Yes. The repository last received commits 81 days ago.
- What is it written in?
- Mainly Zig, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A PDF viewer that draws into the terminal
fancy-cat is a PDF viewer for terminal emulators using the Kitty image protocol, written in Zig, and the whole approach rests on one capability. The Kitty image protocol lets a terminal application transmit graphics as escape sequences, and a PDF renderer that can emit those sequences can draw a page inside a terminal window with no separate window, no X11 dependency and no remote display needed. The repository is small and the layout shows the shape of it, with src/ holding the code, deps/ and a.gitmodules file for the dependencies, build.zig and build.zig.zon as the build definition, and docs/ holding the command and configuration references. The command line takes a path and an optional page number, so the same binary serves both the first page and a specific page, which is what you want when a document is referenced by page somewhere in a terminal session.
A modal interface borrowed from Neovim
The interaction model is the second thing to understand, and the README describes it as a modal interface similar to Neovim with two modes, view mode and command mode. You enter command mode by typing a colon by default, and the colon is configurable in the config file. The list of commands is documented separately in docs/commands.md, which is where you would look for the navigation and display verbs. The features list names the areas it covers, with filewatch for hot reload, runtime config, custom keymappings, the modal interface itself, commands, a colorize mode for dark mode, a status bar, and page navigation covering zoom, previous and next. The status bar and the modal split are what make a terminal PDF viewer usable rather than a novelty, because they give the same kind of feedback loop a Neovim user already has, and the hot reload means editing the config file takes effect without restarting the viewer.
Building it needs Zig 0.15.2 and the Kitty protocol
The requirements are short and specific. You need Zig version 0.15.2, and you need a terminal emulator with the Kitty image protocol, with Kitty, Ghostty and WezTerm given as examples. The build itself is three steps. First you fetch the submodules, because the dependencies live there.
git submodule update --init --recursiveThen you build the project in the small release mode.
zig build --release=smallAnd then you install the resulting binary by moving it onto your PATH.
# Add to your PATH
# Linux
mv zig-out/bin/fancy-cat ~/.local/bin/
# macOS
mv zig-out/bin/fancy-cat /usr/local/bin/The small release mode is worth noting because it is the mode the documentation uses throughout, and for a tool whose entire job is to emit image sequences into a terminal, size matters more than raw speed. To run without installing, there is a build run step that takes the same arguments as the installed binary.
zig build run -- <path-to-pdf> <optional-page-number>The packaging status is tracked through a Repology badge, which is the usual way to say that the binary is packaged by a set of distributions rather than only by its author.
A processor specific build failure has a documented workaround
The build instructions include a known issue worth reading before you start, because the error message is alarming. There is a known issue with some processors where the build fails on the last steps with the error LLVM ERROR: Do not know how to expand the result of this operator!, and the documented workaround is to build with an explicit CPU target instead of letting the compiler pick.
zig build -Dcpu="skylake" --release=smallThis is the kind of detail that a project publishes only after someone has hit it, and it is a good illustration of the Zig toolchain's trade-off. The same LLVM that compiles the code is the one doing the instruction selection, and a sufficiently new or unusual processor can trip it, so the escape hatch is to name a conservative target rather than to wait for a new compiler. For a reader deciding whether to adopt the project, the relevant point is that the failure mode is documented and has a one flag workaround, rather than being a mysterious crash.
The configuration file is created for you on first run
fancy-cat is configured through a JSON configuration file that it looks for in one of several locations, with the primary being the config.json path under XDG_CONFIG_HOME, the fallback being the same relative path under the home directory, and a legacy location under the home directory itself. An empty configuration file is created automatically in the primary or the fallback location on the first run, which removes the usual first-run friction of hunting for a config file that does not exist yet. The documentation also points at an example config.json and at docs/config.md, so the reference for every option is separate from the README. Two things you will want to change early are the key that enters command mode, which defaults to a colon, and the jump target, which defaults to the XDG path, and both are the kind of setting that a user of Neovim will want to align with their own muscle memory.
Where fancy-cat is the wrong tool
Three limits. The first is hard and non-negotiable, since the tool depends on the Kitty image protocol, and a terminal without it has nothing to render into. That excludes a meaningful share of terminals, including the older ones and the minimal emulators people use over SSH, and the README does not describe a text fallback, which is the right call, because a text-mode PDF viewer would be a different and much less useful project. The second is that the AGPL-3.0-or-later licence is a real consideration for anything you distribute, since it reaches networked use rather than stopping at handing over files, and that is a question for your own review rather than for this article. The third is scope. This is a viewer, not a reader, so it gives you a rendered page, page navigation and zoom, and it does not give you text selection, search inside the document, annotations or a document outline, because none of those are in the feature list. On the maintenance side the picture is modest rather than busy, with the last push to the repository on 2026-08-03 and no GitHub releases, so the build from source is the distribution path that the documentation actually supports.
Editorial conclusion
Adopt fancy-cat if you read PDFs from a terminal and your emulator supports the Kitty image protocol, since the whole tool is a single binary with a modal interface and a JSON config. Skip it if your terminal does not implement that protocol, because there is no fallback rendering path, and skip it if you want to read documents in a dedicated viewer with text selection. Before you build, confirm your emulator is on the supported list and that you have Zig 0.15.2, and read docs/config.md for the config file, since the key to enter command mode and the location of the config file are both configurable.
Frequently asked questions
What terminal support does fancy-cat need?
It needs a terminal emulator with the Kitty image protocol, with Kitty, Ghostty and WezTerm given as examples. The tool renders PDF pages into the terminal using that protocol, and the requirements list Zig version 0.15.2 alongside it.
How do I build fancy-cat from source?
Fetch the submodules with git submodule update --init --recursive, build with zig build --release=small, then move zig-out/bin/fancy-cat onto your PATH. You can also run it without installing with zig build run -- followed by a PDF path and an optional page number.
Where does fancy-cat keep its configuration file?
In a JSON config file, looked for first under XDG_CONFIG_HOME, then under the home directory config path, with a legacy location under the home directory as a third option. An empty configuration file is created automatically in the primary or fallback location on the first run, and docs/config.md documents the options.
How do I enter command mode in fancy-cat?
The interface is modal in a way similar to Neovim, with a view mode and a command mode, and you enter command mode by typing a colon by default. That key is configurable, and the available commands are documented in docs/commands.md.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/freref-fancy-cat)Was this useful?