View documents without leaving the terminal
A fast, terminal-native document viewer. Markdown, plain text, logs, JSON, YAML, TOML, XML, CSV and source code render today — more formats land milestone by milestone.
It is not an editor. It is not a converter. It is not an IDE.
v0.2.0 · M0 and M1 completeRelease notes A fast, terminal-native document viewer, with inline code and a link[1]. Formats • Markdown, plain text, logs, data files and source code • Detection for HTML, PDF and the Office family ◦ and the Office/ZIP family • PDF and EPUB are on the roadmap ┌──────────┬──────────┬───────────┐ │ Format │ Status │ Milestone │ ├──────────┼──────────┼───────────┤ │ Markdown │ ready │ M0 │ │ HTML │ detected │ M3 │ │ PDF │ pending │ M3 │ └──────────┴──────────┴───────────┘ fn main() { println!("hello"); } │ Streaming by default: a 488 MB log costs 1.4 MB of memory. [1] https://termdoc.app
Not a mock-up. That block is generated by running termdoc over a Markdown file and translating the ANSI it emits — the colours, the wrapping and the box-drawing are the renderer’s own.
| Format | Detected | Renders |
|---|---|---|
| Markdown | ● | ● |
| Plain text | ● | ● |
| Logs | ● | ● |
| JSON · YAML · TOML · XML · CSV | ● | ● |
| Source code | ● | ● |
| HTML | ● | ◐ |
| PDF · EPUB | ● | ✕ |
| DOCX · ODT · XLSX · PPTX | ● | ✕ |
● works today · ◐ reader in development, shown as plain text with a warning on stderr · ✕ recognised, but this build refuses to display it rather than dumping bytes at your terminal.
The middle row is the honest one. A recognised text format still gets shown, because mid-roadmap that beats refusing to open the file — and --strict turns that warning into a non-zero exit if a script would rather stop. Run termdoc --formats to see what the binary you actually installed can read.
┌──────────┬──────────┬─────┐ │ Format │ Status │ M │ ├──────────┼──────────┼─────┤ │ Markdown │ ready │ M0 │ │ HTML │ detected │ M3 │ │ PDF │ pending │ M3 │ └──────────┴──────────┴─────┘
+----------+----------+-----+ | Format | Status | M | +----------+----------+-----+ | Markdown | ready | M0 | | HTML | detected | M3 | | PDF | pending | M3 | +----------+----------+-----+
Format Status M Markdown ready M0 HTML detected M3 PDF pending M3
One table, three rungs down. Each gives up something the rung above it could afford, and the last one gives up the frame entirely: below a certain width a bordered table can only fit by truncating cells, so it stops being a table and becomes tab-separated values — output for cut and awk rather than for reading. Losing the borders is recoverable; losing the data is not.
Degradation is an input to the layout, not a chain of special cases bolted onto it. The terminal’s real capabilities are detected once, and every ladder — colour truecolor → 256 → 16 → none, hyperlinks, headings — reads from that same value. With colour off, not one escape byte is emitted.
mmap, never a materialised tree. A 488 MB log costs 1.4 MB of memorykubectl logs -f | termdoc shows each line when it is written, flushing the moment it would otherwise wait. 122 MB piped in costs 2.8 MB, and yes | termdoc | head answers at oncetermdoc huge.log | head -5 dies with signal 13 like cat does, instead of panicking. In a pipe, stdout carries only the documenttermdoc --explain prints every opinion, including the losing ones# Homebrew — macOS and Linux, the prebuilt binary $ brew install marturojt/tap/termdoc # from crates.io $ cargo install termdoc # or a prebuilt binary — macOS · Linux · Windows $ github.com/marturojt/termdoc/releases/latest # then point it at anything $ termdoc README.md $ termdoc --explain odd.dat $ cat README.md | termdoc $ kubectl logs -f pod | termdoc # AUR and Scoop — planned
Prebuilt binaries for macOS (universal), Linux (x86_64 and aarch64) and Windows are attached to every release, with SHA256SUMS.txt covering each archive — and CI unpacks and runs every one of them before the release is drafted. Building from source needs a Rust toolchain (rustup.rs). The Homebrew formula installs that same binary, and the tap’s own CI installs and audits it on macOS and Linux whenever it changes. What changed in each release is in the changelog.
Readers exist for Markdown, plain text, logs, JSON, YAML, TOML, XML, CSV and source code. Detection recognises considerably more — HTML, PDF and the Office/ZIP family — and until each dedicated reader lands, a recognised-but-unreadable text format is shown as plain text with a warning on stderr. --strict turns that warning into an error.