# Coming from term-img

> A term-img alternative with a drop-in path for image bytes: import terminalImage from paratext/term-img, graded 12 / 18 by term-img's own test suite — all six misses pass a file path, which paratext declines to read — then zero dependencies and no node:fs.

Source: https://paratext.interlace.tools/docs/coming-from/term-img

**paratext** is a **term-img alternative** you adopt by changing one import — and, if you
pass file paths, one argument. `paratext/term-img` is term-img 7's API for image **bytes**,
and term-img's own test suite is the grade. It is not a complete drop-in, and this page says
exactly where it stops.

## Migrate from term-img: one import, and bytes instead of a path

```diff
- import terminalImage, { UnsupportedTerminalError } from 'term-img';
+ import terminalImage, { UnsupportedTerminalError } from 'paratext/term-img';
+ import { readFile } from 'node:fs/promises';

- console.log(terminalImage('unicorn.jpg', { width: '50%' }));
+ console.log(terminalImage(await readFile('unicorn.jpg'), { width: '50%' }));
```

If you already pass a `Uint8Array` or a `Buffer`, the import line is the whole migration.
Everything else stays: `width`, `height`, `preserveAspectRatio` and `fallback`; a missing or
empty image throws a `TypeError`; an unsupported terminal calls your `fallback` or throws
`UnsupportedTerminalError`, with term-img's message and `name`. Support is term-img's own
terminal table — iTerm2 3+, WezTerm 20220319+, Konsole 22.04+, Rio 0.1.13+, VS Code 1.80+ —
read from the environment, in term-img's order: the argument is checked, then the terminal,
then the bytes.

A **path** handed to a supported terminal throws a `TypeError` that says to read the file
first. It throws at exactly the point term-img would have called `fs.readFileSync`, so a path
handed to an *unsupported* terminal still reaches your `fallback`, as it does upstream.

## Is paratext compatible with term-img?

Partly, and graded rather than claimed. term-img's own suite, vendored at 7.1.0 and
unmodified apart from the import specifier, runs against `paratext/term-img` beside a control
that runs it against real term-img:

| | passing | rate |
| :-- | --: | --: |
| `paratext/term-img` | 12 / 18 | 66.7% |
| term-img itself (control) | 18 / 18 | 100.0% |

From [Compatibility](https://burgee.interlace.tools/docs/compatibility), which `npm run compat:page` generates from the
oracle's last run; that page is the authority. The six failing cases are the same six every
run — `iTerm2 support`, `WezTerm support`, `Konsole support`, `Rio support`, `VSCode support`
and `handles options parameter correctly` — and every one of them hands a file path to a
terminal the suite has just declared supported. paratext takes bytes only, so that `node:fs`
stays out of a package that otherwise touches nothing but strings. Passing them would mean
reading a file, which is the dependency this package declines; so 12 / 18 is this row's
ceiling, and a caller who passes paths has one edit to make.

## What you gain over term-img

- **Zero dependencies.** term-img 7.1.0 depends on `ansi-escapes` and `iterm2-version`.
- **No filesystem access.** The caller owns the read, so the package never opens a file on
  your behalf.
- **iTerm2 10 and later are recognised.** term-img reads iTerm2's major version from its
  first character, so it would read `10.2.1` as `1` and refuse the terminal; the façade
  parses the whole number. Nothing in the suite tells the two apart, so this is a fix that
  costs no compatibility.
- **A caption instead of a throw, when you want one.** paratext's root `image()` — ansi-escapes'
  signature, plus `caption` — projects an image to its caption wherever support is absent or
  unknown, so a pipe or an agent reads text rather than an exception or raw escape bytes.

```js
import { image } from 'paratext';

image(bytes, { caption: 'Build graph' });
// iTerm2, on a TTY: the inline image
// a pipe:           Build graph
```

## When to switch from term-img

- You already hold the image as bytes, or can read it yourself in one line.
- Your output is also piped or read by an agent, and an image should become its caption
  there.

If your program hands term-img a path in many places and you cannot touch them, stay on
term-img for now. The registry, the schema and the plugin host are on [paratext](/docs).
