Coming from ansi-escapes
An ansi-escapes alternative for the OSC half — hyperlinks, images, title, clipboard, notifications, bell — where every capability has a static projection for pipes and agents. Graded 1 / 4 by ansi-escapes' own suite, the ceiling for an OSC-only package; no drop-in is claimed.
paratext is an ansi-escapes alternative for its OSC half: the escapes that address the terminal program — hyperlinks, inline images, the window title, the clipboard, desktop notifications, the working directory and the bell. The CSI half — the cursor, erasing, scrolling, the alternate screen — is out of scope. paratext does not claim to be an ansi-escapes drop-in.
Migrate from ansi-escapes: the OSC members only
The root is call-compatible with ansi-escapes for the four OSC members of its surface:
- import ansiEscapes, { link, image, setCwd, beep } from 'ansi-escapes';
+ import ansiEscapes, { link, image, setCwd, beep } from 'paratext';The CSI names are still declared, as undefined, so a module that imports them loads
rather than dying on an ESM named import — and TypeScript types them so that calling one is
a compile error. If your program moves the cursor or erases lines with ansi-escapes, keep
ansi-escapes for those calls; in the burgee family that half belongs to flagstaff, which
draws the grid, and closeout, which puts it back.
Is paratext compatible with ansi-escapes?
For the OSC half only, and the grade shows the boundary. ansi-escapes' own suite, vendored
and unmodified apart from the import specifier, runs against paratext beside a control that
runs it against the real package:
| passing | rate | |
|---|---|---|
paratext | 1 / 4 | 25.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. Three of the suite's four cases assert CSI,
which paratext does not implement, so 1 / 4 is the ceiling on this row — complete for the
OSC half, and not a compatibility claim. 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.
The registry, the schema and the plugin host are on paratext.