paratext
Coming from…

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:

passingrate
paratext1 / 425.0%
ansi-escapes itself (control)4 / 4100.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 hyperlink text (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.json without 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.

On this page