Est. 1973 Intermediate

Nroff

The original Unix text-formatting language for terminals and line printers, still used today to render man pages, built around embedded dot-commands and a powerful macro and register system.

Created by Joe Ossanna (with Brian Kernighan)

Paradigm Markup; macro-based, procedural document formatting
Typing Untyped (text markup with numeric and string registers)
First Appeared 1973
Latest Version Maintained through the GNU groff implementation (groff 1.23.0, 2023)

Nroff (from “new roff”) is one of the foundational text-formatting languages of Unix. It takes a plain-text source file interleaved with formatting requests — terse, two-letter commands that begin with a dot in the first column, like .br, .ce, or .sp — and renders it into neatly laid-out text suitable for fixed-width devices such as terminals and line printers. Its near-twin, troff, applies the same markup to typesetters and other proportional, graphical output devices. More than half a century after it was written, nroff is still in daily use by nearly every Unix and Linux machine on Earth, because it is the language in which man pages are written and rendered.

A note on names. “Nroff” rarely exists today as a standalone program. On modern systems the command nroff is almost always a wrapper around groff (GNU roff), the free reimplementation that emulates the original AT&T behavior. When this page refers to “nroff,” it means both the historical formatter and the living markup-and-macro language that groff continues to interpret.

History & Origins

The roff family descends from RUNOFF, written by Jerome H. Saltzer in 1964 for MIT’s Compatible Time-Sharing System (CTSS). The name is a programmer’s joke on the everyday phrase “I’ll run off a copy.” RUNOFF’s idea — embed terse formatting commands directly in the text and let a program lay it out — proved durable, and the program was reimplemented and shortened to roff when Douglas McIlroy brought it to early Unix on the PDP-11 around 1971. That first Unix roff formatted the manual pages for the earliest editions of Unix and, when the Bell Labs patent department adopted it, became the first Unix program with a paying outside client.

roff was deliberately simple and quite limited. Joe Ossanna — a member of the Unix team — set out to build something far more capable, and the result, written around 1973, was nroff, the “new roff.” (Sources differ slightly on the exact first-appearance date: the canonical roff histories place nroff and troff in 1973, while some references list an initial nroff release as early as June 1972 with Version 2 Unix. What is certain is that the system took its mature form in the early-to-mid 1970s.) When the patent department funded a Graphic Systems CAT phototypesetter, Ossanna wrote a parallel program, troff (“typesetter roff”), to drive it. Crucially, nroff and troff shared a single markup language, so the same source file could be formatted for a cheap terminal with nroff or a phototypesetter with troff.

Ossanna’s first versions were written in PDP-11 assembly language. In 1975 he rewrote both programs in C, which made them portable and far easier to extend. After Ossanna’s untimely death in 1977, Brian Kernighan inherited the project. Kernighan documented the system thoroughly, extended its capabilities, and around the late 1970s to early 1980s produced device-independent troff (ditroff), which decoupled formatting from any single output device by emitting a neutral intermediate format that device-specific postprocessors then converted — the architecture that all modern implementations still use.

Design Philosophy

Nroff embodies a set of ideas that are characteristically Unix:

  • Markup is embedded in the text, in band. There is no separate stylesheet or document model. Formatting requests live directly in the source, each on its own line beginning with a control character (. by convention) in column one. Everything else is treated as text to be filled and adjusted.
  • A small core, extended by macros. The built-in request set is low-level — break a line, center, indent, set a tab, define a register. Higher-level structure (titles, paragraphs, footnotes, page headers) is built up out of user-defined macros, and reusable bundles of those macros became the famous macro packages.
  • Programmable, not just declarative. Nroff is genuinely a little programming language. It has number registers (named numeric variables), string registers (named text), conditionals (.if, .ie/.el), arithmetic, traps that fire at given vertical positions on a page, and diversions that capture formatted output for later placement — the machinery used to implement footnotes and floating tables.
  • Composable through pipes. Rather than build mathematics, tables, and diagrams into the formatter, the Unix team wrote preprocessors that emit nroff/troff requests. A document flows through a pipeline — tbl | eqn | nroff — each stage handling what it does best.

Key Features

FeaturePurpose
Requests (.br, .sp, .ce, .fi/.nf, .in)Low-level formatting: line breaks, spacing, centering, fill/no-fill mode, indentation
Macros (.de/..)Define reusable named command sequences — the foundation of every document style
Number registers (.nr)Named numeric variables for counters, measurements, and conditional logic
String registers (.ds)Named strings for reused text such as titles and running heads
Conditionals & loops (.if, .ie, .el, .while in groff)Programmable formatting decisions
Traps & diversions (.wh, .di)Trigger macros at page positions; capture output for footnotes and floats
Macro packages (man, mdoc, ms, me, mm, mom)Ready-made document structures layered on the primitives
Preprocessors (eqn, tbl, pic, refer, soelim)Translate equations, tables, diagrams, and citations into roff requests

A short, self-contained example using only built-in requests:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
.\" Lines beginning with .\" are comments
.ce 2
The Title
On Two Centered Lines
.sp
.ti 0.5i
This paragraph begins with a temporary indent of half an inch.
Text in fill mode is collected and laid out to the line length
automatically, so these source line breaks do not matter.
.br
This sentence starts on a new line because of the explicit break.

And a glimpse of nroff as a programming language — defining a macro and using a number register:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
.\" Define a macro .PP for a paragraph
.de PP
.sp
.ti 0.3i
..
.\" A number register used as a counter
.nr SC 0 1
.PP
This is the first paragraph.
.nr SC +1
.PP
Section counter is now \n(SC.

The Macro Packages

Almost no one writes long documents with nroff’s bare requests; instead they use a macro package that supplies meaningful, document-oriented commands. The historically important ones include:

  • man and the newer mdoc — the macros for writing Unix manual pages. When you read man ls, you are reading nroff/troff source marked up with these macros.
  • ms — Ossanna and Kernighan’s “manuscript” macros for papers and reports, one of the oldest packages.
  • me — the Berkeley macros, distributed with BSD Unix.
  • mm — AT&T’s Memorandum Macros, aimed at business and technical memos.
  • mom — a modern, friendly macro set introduced with groff.

These packages are the reason the same underlying language can produce something as terse as a man page or as elaborate as a typeset technical report.

Evolution

Nroff and troff were proprietary AT&T software, which limited their reach as Unix splintered into many vendors. The decisive turn came in 1989–1990, when James Clark wrote groff (GNU roff), a clean C++ reimplementation modeled on ditroff. groff’s first release (0.3.1) appeared in June 1990, and it bundled not just the formatter but the whole ecosystem — the nroff and troff front ends, the preprocessors (eqn, tbl, pic, soelim), and the standard macro packages. Because groff is free software and faithfully emulates the AT&T behavior while adding extensions, it displaced the original on Linux and the BSDs and is today the implementation virtually everyone actually runs. Other modern descendants include the Heirloom Documentation Tools (a modernized fork of the genuine AT&T troff) and neatroff.

The language itself has stayed remarkably stable. The request set, register model, macro mechanism, and preprocessor pipeline that Ossanna and Kernighan defined in the 1970s are the same ones groff interprets in releases like groff 1.23.0 (2023). Backward compatibility is a point of pride: source written for V7 Unix troff still formats.

Current Relevance

Nroff’s everyday importance is almost invisible precisely because it is so universal: it formats the manual pages. Every time a Unix or Linux user runs man, a roff macro file is fed through groff’s nroff mode and rendered to the terminal. That single use case guarantees the language a permanent place in the running software of the world, and it means the man/mdoc macros remain a living, actively edited dialect.

Beyond man pages, the toolchain retains a devoted following among people who value plain-text, version-controllable, pipeline-friendly publishing. Writers use ms, me, or mom with eqn, tbl, and pic to produce PDFs and PostScript with fine typographic control and no binary file formats. It is a niche compared to LaTeX or modern markup, but a durable and self-contained one.

Why It Matters

Nroff sits at the headwaters of computer-based document preparation. It established conventions that echo through everything that came after: separating content from presentation via embedded markup, building rich behavior from a small set of primitives plus user-defined macros, and composing specialized tools through pipes rather than building a monolith. The troff system it anchors gave the world the man page, helped typeset some of the most influential books and papers in computing — including the Unix documentation itself — and proved that a tiny, programmable formatting language could outlast nearly every word processor of its era. Joe Ossanna, who died before he could see how far his “new roff” would travel, is fairly called the father of the entire roff lineage; the language is still quietly doing its job on the machine in front of you.


Sources include the Wikipedia articles on nroff, troff, Joe Ossanna, and groff; the roff(7) manual page on the history of roff typesetting; and the GNU Troff Manual.

Timeline

1964
Jerome H. Saltzer writes RUNOFF for MIT's Compatible Time-Sharing System (CTSS), the ancestor of the entire roff family; the name comes from the phrase 'I'll run off a document'
1971
Douglas McIlroy adapts roff for early Unix on the PDP-11; roff is used to format the man pages for the first editions of Unix and becomes the system's first outside client (the Bell Labs patent department)
1973
Joe Ossanna writes nroff ('new roff'), a far more capable formatter for terminals and line printers, originally in PDP-11 assembly language; troff ('typesetter roff') for the Graphic Systems CAT phototypesetter follows alongside it
1975
Ossanna re-writes nroff and troff in C, greatly improving portability; the two programs share a common markup so most source files format under either
1977
Joe Ossanna dies; Brian Kernighan takes over development and continues to extend and document the troff/nroff system
1979
Kernighan develops device-independent troff (ditroff), reportedly around 1979–1981, separating formatting from device-specific output via an intermediate format and postprocessors, the model that modern implementations follow
1990
James Clark releases the first version of GNU groff (0.3.1), a free C++ reimplementation of the troff/nroff system that becomes the standard on Linux and other Unix-like systems
2023
groff 1.23.0 is released, continuing active maintenance of the nroff/troff language and macro packages more than fifty years after the original

Notable Uses & Legacy

Unix and Linux manual pages

Virtually every man page on Unix-like systems is written in nroff/troff markup using the 'man' (or modern 'mdoc') macro package; running 'man' invokes nroff (today via groff) to render those pages for the terminal.

GNU groff

The GNU project's groff is the dominant living implementation of the nroff/troff language. It ships with most Linux distributions and is the engine behind man-page rendering, the 'mom', 'ms', and 'me' macro packages, and a range of technical publishing tasks.

Bell Labs technical publishing

At its origin nroff and troff produced camera-ready copy for Bell Labs papers, patent applications, and the Unix documentation itself; the Unix Programmer's Manual and many early CS books were typeset with this toolchain.

The 'ms', 'me', and 'mm' document macro packages

Layered macro packages built on nroff/troff — ms (manuscripts), me (Berkeley), and mm (AT&T Memorandum Macros) — provided structured document formatting for reports, papers, and memos long before word processors, and remain usable today.

Preprocessor pipeline (eqn, tbl, pic, refer)

Nroff anchors a classic Unix pipeline in which preprocessors translate higher-level notations — eqn for mathematics, tbl for tables, pic for diagrams, refer for bibliographies — into nroff/troff requests before formatting.

Language Influence

Influenced By

RUNOFF roff

Influenced

troff ditroff groff Heirloom troff

Running Today

Run examples using the official Docker image:

docker pull
Last updated: