View documents without leaving the terminal
A fast, terminal-native document viewer. Markdown, plain text and logs render today — more formats land milestone by milestone.
It is not an editor. It is not a converter. It is not an IDE.
v0.1.0 · M0 complete · M1 in progressRelease notes A fast, terminal-native document viewer, with inline code and a link[1]. Formats • Markdown, plain text and logs • Detection for JSON, YAML, TOML, XML, CSV ◦ and the Office/ZIP family • PDF and EPUB are on the roadmap ┌──────────┬──────────┬───────────┐ │ Format │ Status │ Milestone │ ├──────────┼──────────┼───────────┤ │ Markdown │ ready │ M0 │ │ CSV │ detected │ M1 │ │ 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 · HTML · CSV | ● | ◐ |
| Source code | ● | ◐ |
| 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 │ │ CSV │ detected │ M1 │ │ PDF │ pending │ M3 │ └──────────┴──────────┴─────┘
+----------+----------+-----+ | Format | Status | M | +----------+----------+-----+ | Markdown | ready | M0 | | CSV | detected | M1 | | PDF | pending | M3 | +----------+----------+-----+
Format Status M Markdown ready M0 CSV detected M1 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 memorytermdoc 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# 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 # Homebrew, AUR, 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). A Homebrew formula is still on the backlog.
Readers exist for Markdown, plain text and logs. Detection recognises considerably more — JSON, YAML, TOML, XML, HTML, CSV, source code, 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.