A universal document viewer for the terminal
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 universal document viewer for the terminal, 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 │ 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 # then point it at anything $ termdoc README.md $ termdoc --explain odd.dat $ cat README.md | termdoc # Homebrew, AUR, Scoop, static binaries — planned
Requires a Rust toolchain (rustup.rs). Prebuilt binaries and a Homebrew tap are on the backlog. Runs on Linux, macOS and Windows — all three are covered by CI.
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.