Coming from ansi-escapes
An ansi-escapes alternative with a drop-in path: import ansiEscapes from paratext, graded 4 / 4 by ansi-escapes' own test suite — then hyperlinks, images and the working directory that project to plain text for pipes and agents instead of raw escape bytes.
paratext is an ansi-escapes alternative you adopt by changing one import. The package root is ansi-escapes 7's surface — the CSI half that moves the cursor and erases the screen, and the OSC half that talks to the terminal program — and ansi-escapes' own test suite is the grade.
Migrate from ansi-escapes in one import
- import ansiEscapes, { cursorTo, eraseLines, link, image, beep } from 'ansi-escapes';
+ import ansiEscapes, { cursorTo, eraseLines, link, image, beep } from 'paratext';Everything else stays. The CSI half — cursorTo, cursorMove, the cursor, erase and
scroll members, clearScreen, clearTerminal, the alternate screen and synchronized output
— is byte-exact with ansi-escapes 7.3.0, including the Terminal.app spelling of save and
restore. It does not degrade, because the incumbent's does not: a cursor move silently
dropped would corrupt the screen of a program that relied on it.
The OSC half — link, image, setCwd and beep — gives the incumbent's exact bytes
on a terminal believed to understand them, and a static projection everywhere else. That is
the one deliberate difference, and it is covered under what you gain.
Two names are declared and empty: iTerm and ConEmu. ansi-escapes hangs
iTerm.setCwd, iTerm.annotation and ConEmu.setCwd off them, and paratext does not yet;
importing them loads, and calling a member is a TypeScript compile error rather than a
surprise at run time. The top-level setCwd carries both terminals' working-directory
sequences, so only iTerm.annotation has no replacement — keep ansi-escapes for that call.
Is paratext compatible with ansi-escapes?
Graded, not claimed. ansi-escapes' own suite, vendored at 7.3.0 and unmodified apart from the
import specifier, runs against paratext beside a control that runs it against real
ansi-escapes:
| passing | rate | |
|---|---|---|
paratext | 4 / 4 | 100.0% |
| ansi-escapes itself (control) | 4 / 4 | 100.0% |
From Compatibility, which npm run compat:page generates from the
oracle's last run; that page is the authority. The suite is small — four cases — and three
of them assert CSI: default export and clearTerminal check the cursor and clear
sequences, and synchronized output checks ESC [ ? 2026 h and l. The fourth, named export(s), checks that a named export and the default's member are the same object. Until
paratext implemented the CSI half, this row was 1 / 4. The same page grades the
paratext/terminal-link and paratext/term-img paths against those packages' suites.
What you gain over ansi-escapes
No terminal answers "do you support OSC 1337", so emitting the bytes and hoping is what puts
\u001B]1337;File=inline=1;… across the screen of anyone who piped your output to a file.
paratext never hopes:
- Every capability has a static projection.
emit()returns it whenever support is absent or unknown: an image becomes its caption, a notification a printed line, a hyperlinktext (url). On a pipe, that projection is what an agent reads. - The fallback is required. A capability without one is refused at registration; there is no opt-out.
- A capability is data. Plain objects, no functions, so a capability travels through
JSON, is diffable, and is validated against
paratext/schema.jsonwithout running its author's code.
import { emit, processRuntime } from 'paratext';
emit(processRuntime(), 'link', { text: 'Docs', url: 'https://x.dev' });
// a terminal that supports it: the OSC 8 hyperlink
// a pipe: Docs (https://x.dev)When to switch from ansi-escapes
- Your CLI emits hyperlinks, images or notifications, and its output is ever piped, logged or read by an agent.
- You want new terminal capabilities registered as data rather than waiting for a release.
If your program depends on an OSC sequence reaching a pipe byte for byte, keep ansi-escapes for that call. The registry, the schema and the plugin host are on paratext.
Compatibility
How paratext's three drop-ins are graded — each incumbent's own test suite, unedited — the current grades, and the differences that remain.
Coming from terminal-link
A terminal-link alternative with a drop-in path: import terminalLink from paratext/terminal-link, graded 8 / 8 by terminal-link's own test suite, with two cases excluded by name — then zero dependencies, and hyperlinks that project to plain text for pipes and agents.