Primary Sources

Where terminal behavior is actually specified — and, more usefully, which documents to read and which to ignore.

The central fact: there is no single authoritative specification for a modern terminal. There is a formal standard nobody implements exactly (ECMA-48), a de-facto standard that documents reality (xterm's ctlseqs), a capability database that papers over the differences (terminfo), and a set of recent proposals that are becoming standard by adoption. Knowing which to trust for which question is a real skill.


The Tier List

TierDocumentVerdict
Read itXTerm Control Sequences (ctlseqs)The operative specification. Everything claims xterm compatibility.
Read itPaul Williams' VT500 parser state diagram (vt100.net)The state machine you will implement, drawn
Read itman 3 termios, man 4 tty, man 7 pty, man 2 ioctl_ttyShort, authoritative, on your machine
Read itkitty's protocol extension docsEverything post-2015
SkimECMA-48Formally correct; describes a world nobody implements
SkimPOSIX "General Terminal Interface"The termios semantics, formally
Referenceman 5 terminfo, man 5 termCapability names, when you need one
ReferenceDEC VT100/VT220/VT510 manualsWhen you need to know what DEC meant
ReferenceUnicode UAX #11 (East Asian Width), UAX #29 (grapheme clusters)Width and clustering, authoritatively

1. XTerm Control Sequences — the reference

Find it: shipped with xterm as ctlseqs.txt; also at invisible-island.net/xterm/ctlseqs/ctlseqs.html.

# It is probably already on your machine:
locate ctlseqs 2>/dev/null
ls /usr/share/doc/xterm/ctlseqs.txt* 2>/dev/null
man 7 xterm 2>/dev/null

Why it is the real spec: essentially every terminal claims TERM=xterm-256color, and programs therefore emit what xterm's terminfo entry advertises. What xterm does is the compatibility target, whatever ECMA-48 says.

How to read it: not front to back. Use it as a lookup — search for the final byte (J, m, h) or the mode number. Its structure is: C1 controls → VT100 sequences → CSI → DEC private modes → OSC → DCS. It is exhaustive, pedantic, and honest about which sequences are xterm inventions.

Note: Thomas Dickey has maintained xterm and this document since 1996. Where it says "this is a DEC feature" or "this is an xterm extension," believe it — the provenance annotations are more reliable than any secondary source.


2. vt100.net — the parser and the DEC manuals

vt100.net/emu/dec_ansi_parser — Paul Williams' state diagram for the VT500 parser.

This is the document for Section 2. It gives every state, every transition, and every action as a table you can transcribe directly into code. vte, termwiz, foot, kitty, and Ghostty all implement variants of it.

Read: the diagram, the state descriptions, and the notes on why ESC aborts unconditionally.

vt100.net/docs/ — scanned DEC manuals (VT100, VT220, VT320, VT510).

Use these when you need to know what DEC intended, especially for the private modes. The VT510 Programmer Information is the most complete. They are also the only place some behaviors are written down at all — DECAWM's deferred wrap, for instance.


3. The Manual Pages — already on your machine

The most under-read authoritative sources in the whole list.

PageCoversRead when
man 3 termiosEvery flag, every control character, tcgetattr/tcsetattr/cfmakerawSection 1 — read it fully, it is short
man 4 tty / man 4 tty_ioctlThe tty device and its ioctls (Linux)Looking up TIOCSCTTY, TIOCGWINSZ
man 2 ioctl_ttyThe same, better organized (Linux)The definitive ioctl list
man 7 ptyThe PTY model, /dev/ptmx, devptsBefore Lab 2
man 3 posix_openpt / grantpt / unlockpt / ptsnameThe allocation sequenceLab 2
man 3 openpty / forkptyThe BSD convenience wrappersAfter Lab 2, for the diff
man 2 setsid / setpgid / tcsetpgrpSessions and process groupsThe job-control chapter
man 7 signalSignal semantics, async-signal-safety, the safe-function listLab 3
man 2 poll / epoll / kqueueMultiplexingLab 3
man 5 terminfoCapability names and the database formatMilestone 14
man 3 tput / man 1 infocmpQuerying capabilities from the shellAny time
man 3 termios | wc -l          # ~600 lines. Read it. Once. Properly.
infocmp                        # your terminal's full capability list
infocmp -1 xterm-256color | head -40
tput clear | xxd               # what "clear" actually is on your terminal

Tip: Linux and macOS man pages differ meaningfully here — macOS's are BSD-derived and shorter. If you are on macOS, read the Linux man 2 ioctl_tty online as well; it is more complete, and the ioctls are largely the same.


4. ECMA-48 — read it, but do not implement it

ecma-international.org → "Control Functions for Coded Character Sets," 5th edition (1991).

The formal standard behind ANSI X3.64. It defines the grammar (CSI, parameters, intermediates, final bytes) rigorously, and that grammar is genuinely worth reading once — it is the thing your parser implements.

What it gets you: the structure of escape sequences; the C0 and C1 control definitions; the canonical names (CUU, CUD, ED, EL, SGR) that this book uses.

Why you must not implement it faithfully:

ECMA-48 saysReality
8-bit C1 controls (0x9B = CSI) are validIn UTF-8 they are continuation bytes. Honoring them corrupts text.
Dozens of sequences (SPA, EPA, DAQ, PLD, PLU, …)Nothing emits them
No mouse reporting, no OSC 8, no bracketed paste, no 256 colorsAll of which are mandatory in practice
SGR 21 is double underlineSeveral terminals used it for bold-off
Precise IRM/SIMD interactionsWidely ignored

The rule: use ECMA-48 for the grammar and the names. Use ctlseqs for the behavior.


5. POSIX — the termios semantics

IEEE Std 1003.1, "General Terminal Interface" (pubs.opengroup.org/onlinepubs/9699919799/).

The authoritative definition of canonical vs. non-canonical mode, VMIN/VTIME, the special characters, and — importantly — sessions, process groups, and controlling terminals. When a job control question is genuinely disputed, this is the answer.

Sections worth bookmarking:

  • General Terminal Interface — termios in full
  • Process Groups, Controlling Terminal, Terminal Access Control — the job-control rules, including the orphaned-process-group semantics that nothing else states clearly
  • The tcsetattr, tcsetpgrp, setsid pages

6. The Modern Proposals

Post-2015 protocol work, mostly driven by kitty, Ghostty, contour, foot, and WezTerm. These are becoming standard by adoption, which is how everything in this domain has always worked.

ProposalWhereSolves
Kitty keyboard protocolsw.kovidgoyal.net/kitty/keyboard-protocol/Key release; the Escape ambiguity; unrepresentable combinations
Kitty graphics protocolsw.kovidgoyal.net/kitty/graphics-protocol/Images, properly
Synchronized output (?2026)contour's SynchronizedOutput docTearing during full-screen redraws
Grapheme clustering (?2027)contour / Ghostty docsTerminal and program disagreeing about width
OSC 8 hyperlinksgist.github.com/egmontkob — the de-facto specClickable links without regex guessing
OSC 133 semantic promptsFinalTerm's original spec; iTerm2 and kitty docsThe terminal knowing where output begins
XTGETTCAP (DCS + q)xterm ctlseqsPrograms querying capabilities directly

Note: These live in project documentation rather than a standards body, and that is not a defect — it is how xterm's extensions became universal too. Adoption is the standardization process here. Check which terminals implement a proposal before depending on it; the ecosystem page has the current shape.


7. Unicode

DocumentUse
UAX #11 — East Asian WidthThe Wide/Fullwidth/Ambiguous classification behind your width table
UAX #29 — Text SegmentationGrapheme cluster boundaries, for mode 2027
UAX #9 — Bidirectional AlgorithmIf you ever attempt RTL, which fights the grid model
The Unicode Standard, §3.9The "maximal subpart" U+FFFD substitution rule your decoder implements
unicode-width crate docsThe Rust implementation and its deviations

The U+FFFD rule in §3.9 is the one people implement wrong, and it is what Lab 9 tests.


8. Reading Real Implementations

Often faster than any specification. Ranked by how pleasant they are to read:

CodebaseLanguageRead it for
vte (Alacritty's parser)RustThe cleanest parser implementation in existence. ~1,500 lines. Read this one.
alacritty_terminalRustThe screen model, done well and separately from the app
termwiz (WezTerm)RustA broader terminal library: parsing, input, surfaces
portable-pty (WezTerm)RustThe Unix/ConPTY abstraction, done right
footCA small, fast, extremely readable Wayland terminal
kittyC + PythonProtocol extensions, and the reference for most of them
GhosttyZigThe libghostty split: core vs. platform apps
st (suckless)C~2,500 lines for a whole terminal. Read it in an evening.
tmuxCThe multiplexer reference. tty.c and screen-write.c especially.
xtermCAuthoritative, and thirty years of accretion. Reference, do not emulate the style.

Tip: st is the single best "read a whole terminal in one sitting" codebase. It is small enough to hold in your head and does everything essential. Read it after Section 2, when you will recognize every function.


9. Papers and Long-Form Writing

PieceWhy
"The TTY demystified" (Linus Åkesson)The best short explanation of the tty layer ever written. Read it in week 1.
Julia Evans' terminal zines and postsExcellent, concrete, and correct
"A history of the TTY"Where the fossils come from
Thomas Dickey's xterm FAQAnswers the "why does xterm do X" questions definitively
Dan Luu, "Terminal latency"Why input latency varies so much between terminals

10. What to Read, in Order

If you read nothing else, read these five, in this order:

   1. "The TTY demystified"            — 30 min, week 1
   2. man 3 termios                    — 45 min, week 1
   3. vt100.net/emu/dec_ansi_parser    — 1 hour, week 4
   4. vte's source (Rust)              — 2 hours, week 4
   5. XTerm ctlseqs, as a lookup       — forever

Everything else is reference material for a specific question.


A Note on Contradictions

You will find sources disagreeing. When they do:

   1. What does XTERM do?          ← the compatibility target
   2. What do kitty/foot/Ghostty do?  ← the modern consensus
   3. What does ECMA-48 say?       ← the formal answer, often ignored
   4. What does DEC's manual say?  ← the original intent

   Implement (1). Note (2) if it differs. Document any deliberate deviation.

And when reality disagrees with all four — which happens — the answer is an experiment: printf the sequence into five terminals and diff the results. That is what differential testing is for, and it is the only source that cannot be out of date.


See also: The Terminal Ecosystem · The Hitchhiker's Guide