# moor: a Go pager for UTF-8 text with search and highlighting

> moor is a terminal pager written in Go that syntax highlights source code, searches incrementally, transparently decompresses gzip and xz input and follows output like tail, with no configuration file to learn.

**walles/moor** — Moor is a pager. It's designed to just do the right thing without any configuration.

- Repository: https://github.com/walles/moor
- Stars: 1,177 · Forks: 65
- Language: Go
- License: NOASSERTION
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/walles-moor

## What moor is trying to do that less does not

moor is a pager. It reads UTF-8 encoded text from files or pipes and displays it, and the README frames it as a tool designed to just do the right thing without any configuration. The stated intention is that moor should be trivial to get into if you have been using less, and the README even asks readers who find moor confusing to report it, which tells you the author treats less familiarity as the bar.

The tool was renamed. As of version 2.0.0 moor was called moar, and the rename release notes are linked from the README, with the behaviour otherwise unchanged.

The differences from less are mostly about what happens while you are reading. Search is incremental, find as you type, compared in the README to Chrome and Emacs. Filtering is incremental too, with the & key filtering the input interactively. Search becomes case sensitive when you add upper case characters to the search term, the Emacs convention. If the search string is a valid regular expression it is treated as one. Search history is deduplicated and persists across invocations, so repeating a search you made last week does not fill the list with duplicates.

Beyond search, the pager syntax highlights source code by default using Chroma, renders ANSI colour coded text so a git diff looks right, supports UTF-8 input and output, shows the position in the file, and can wrap on actual word boundaries when asked.

## Installing moor through the package managers you already use

moor is packaged for the usual suspects, and the README gives one command per ecosystem. Homebrew covers both macOS and Linux:

```sh
brew install moor
```

Upgrading later is a plain brew upgrade. Debian Forky and newer, and Ubuntu 26.04 Resolute and newer, ship it in their own repositories:

```sh
sudo apt install moor
```

MacPorts, Gentoo and Arch Linux each have their own invocation:

```sh
sudo port install moor
```

```sh
emerge --ask --verbose sys-apps/moor
```

```sh
pacman -S moor
```

If no package exists for your platform, the README asks you to consider packaging it, and gives two manual routes. A Go toolchain will install the current version into your GOPATH bin directory:

```sh
go install github.com/walles/moor/v2/cmd/moor@latest
```

Or you can take a release binary from the releases page and move it into place yourself:

```sh
chmod a+x moor-*-*-*
sudo mv moor-*-*-* /usr/local/bin/moor
```

Packagers are asked to include the man page, moor.1, in the package, and the repository keeps that page at the top level.

## Making moor the pager and setting its defaults

Moor is used as the default pager by several tools in the same author's projects: riff, a diff filter that highlights which line parts changed, px and ptop, which are ps and top for human beings, and ftop, which embeds moor through its embedding API.

To make it your pager, the README asks for one line in your shell profile:

```bash
export PAGER=/usr/local/bin/moor
```

Defaults for moor's own options come from the MOOR environment variable, which moor reads as extra command line options. The README gives this example:

```bash
export MOOR='--statusbar=bold --no-linenumbers'
```

The full option list is deliberately not in the README, because it changes, and the instruction is to run moor --help for an up to date list. That is a reasonable trade for a tool whose flags grow, and it is the only way to see what the current version supports.

Two other environment variables tune behaviour. PAGER_WRAP_COLUMNS, when set to a positive number, limits the maximum width for wrapping long lines. PAGER_LABEL lets other programs tell moor what name to display for standard input, so a pipeline can label the input sensibly.

## less compatibility, secure mode and the status bar

Moor keeps a set of less conventions, because the goal is to be a drop-in for people who already have habits. It reads the terminal capability formats declared in three variables when they are present: LESS_TERMCAP_md for bold in man pages, LESS_TERMCAP_us for underline in man pages, and LESS_TERMCAP_so for the status bar and the search hits. In those values both real escape characters and the word ESC in capitals are interpreted as escape characters, so a value like ESC[1m works.

There is also a secure mode. Setting LESSSECURE to 1 prevents moor from launching external programs or opening new files, which is the behaviour systemctl(1) requires from a pager. In that mode the v command, which opens the current file in an editor, is disabled.

The status bar itself is configurable, and the MOOR example above turns on a bold status bar and turns off line numbers. The tool also renders terminal hyperlinks properly, follows output as long as you are on the last line in the manner of tail -f, and word wraps on real word boundaries with --wrap or the w key.

One behaviour is worth reading twice because it is a security switch rather than a preference: LESSSECURE does not merely restrict, it changes what the v key does, and any script that pipes into a pager inherits the setting from its environment.

## Compressed input, ANSI colour and the background reader

Moor reads input in the background, which is what the README means by a snappy interface on slow or large input, and it uses multi-threaded search on top of that. For a file that is still being written, moor follows the output as long as the cursor is on the last line.

Input does not have to be plain. Moor transparently decompresses compressed text files, with the README listing.gz,.bz2,.xz,.zst and.zstd, and the same applies to compressed streams. The Go module list shows the decompression libraries behind this, including klauspost/compress and ulikunitz/xz, alongside Chroma for highlighting, rivo/uniseg for grapheme handling.

ANSI colour coded text is displayed as intended, so the output of a diff tool or a log with escape sequences is not stripped. Combined with the Chroma highlighting, the two features are complementary rather than competing: one handles colour that was already in the file, the other adds colour based on the file's content.

Mouse scrolling works out of the box, and the README links a separate document, MOUSE.md, for the trade-offs, which is the sort of detail that usually means there is a real trade-off rather than a free win.

## The Go version policy and the release rhythm

The go.mod file carries an unusual and useful comment explaining the toolchain policy: no newer than the most recently end-of-lifed Go release, so distro packagers building from source are not forced onto a toolchain their repositories do not have yet. The module targets go 1.25.0 and the path is versioned as github.com/walles/moor/v2, which is why the install command names the v2 module path.

That policy is a packaging decision with a cost. A project that pins to an end-of-life Go release gives up the toolchain improvements of newer versions, in exchange for the ability to build on the distributions that ship older compilers. For a pager that gets packaged into Debian, Ubuntu, Arch, Gentoo, MacPorts and Homebrew, that is the right trade, and it is also why a plain go install may produce a different binary from the one your distribution ships.

The releases themselves are frequent and specific. v2.19.4 on 2026-10-10 fixed flick-scrolling down freezing and then jumping, v2.19.3 on 2026-10-09 added mouse support out of the box in more terminals, and v2.19.2 on 2026-09-16 made prompts use the terminal's own cursor. The last push to the repository was on 2026-10-15. Patch level releases that fix visible behaviour are a good sign for a tool people keep open all day.

The repository also carries AGENTS.md, RACES.md for its concurrency work, MOUSE.md and WINDOWS-VM.md, and a test.sh and manual-test.sh pair, so the test story is visible in the tree.

## Where moor is the wrong tool, and what bat does instead

Moor is the wrong tool when the environment cannot run it. The README asks packagers to step in when there is no binary for a platform, which means an unusual or embedded target may be left without a pager, and the alternative is to keep using less.

It is also the wrong tool for a workflow that depends on less specific behaviour that moor has not reproduced. The README treats less familiarity as the adoption bar and asks for bug reports when moor is confusing, which is an admission that the two are not identical. A script that drives less with specific options, or a key binding a colleague has memorised, may not survive the switch.

The comparison the README itself makes is with bat, and the distinction is instructive. bat is a file preprocessor that sometimes pipes to a pager, while moor is the pager. bat inspects its input, formats it, and then hands it to moor or something else, so the two are not competing for the same job. Some of bat's preprocessing overlaps with what moor does internally, such as syntax highlighting and JSON formatting, but the fast interactive search that is central to moor cannot be simulated by preprocessing, because preprocessing happens once and search happens repeatedly.

So the real choice is between a pager that does the reading well and a preprocessor that prepares what is read. If your workflow pipes files through something before you page them, both can be in play at once.

## Conclusion

moor fits a workstation where less has become the bottleneck: it suits interactive log reading, diff review and any habit of setting PAGER to something better. It does not suit a server with no Go toolchain and no package for your distribution, or a workflow that depends on less specific key bindings. Check first that your terminal handles the mouse reporting moor uses, since the README documents that trade-off separately in MOUSE.md.

## FAQ

### How do I install moor on Linux?

Use the package for your distribution, for example sudo apt install moor on Debian Forky and newer, pacman -S moor on Arch, or emerge --ask --verbose sys-apps/moor on Gentoo. With a Go toolchain you can also run go install github.com/walles/moor/v2/cmd/moor@latest.

### How do I make moor my default pager?

Add export PAGER=/usr/local/bin/moor to your .bashrc. Default options for moor itself can be set through the MOOR environment variable, for example export MOOR='--statusbar=bold --no-linenumbers'.

### What is the difference between moor and bat?

The README states that bat is a file preprocessor that sometimes pipes to a pager, while moor is the pager itself. Syntax highlighting and JSON formatting overlap, but the incremental interactive search is specific to moor because preprocessing happens only once.

### Does moor read compressed files?

Yes. The README lists transparent decompression for .gz, .bz2, .xz, .zst and .zstd files and for compressed streams, and the dependency list includes klauspost/compress and ulikunitz/xz.

## Sources

- [Issues](https://github.com/walles/moor/issues)
- [README](https://github.com/walles/moor/blob/master/README.md)
- [Releases](https://github.com/walles/moor/releases)
- [walles/moor on GitHub](https://github.com/walles/moor)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/walles-moor
