Skip to content

Terminal profiles

Terminals disagree about how wide a character is. Not many characters — but enough that a bordered box lines up in one terminal and drifts by a column in another. A terminal profile is a named set of answers to exactly those questions, recorded with the session so a replay counts the way the session did.

import { fileURLToPath } from 'node:url';
import { expect, test } from 'termwright/test';
const appPath = fileURLToPath(new URL('../app.js', import.meta.url));
test('renders CJK-wide layout', async ({ terminal }) => {
const app = await terminal.launch({
command: [process.execPath, appPath],
terminalProfile: 'cjk-wide',
});
await expect(app).toMatchCellSnapshot();
});
SwitchWhat it decides
ambiguousWidthwhether East Asian Ambiguous characters take one column or two
reflowCursorLineOnResizewhether the cursor’s line reflows on resize (wrapped lines always do)

All profiles use Unicode 15 extended grapheme clusters. Two policies cover the supported ambiguous-width behaviors:

ProfileAnswers
defaultEast Asian Ambiguous characters take one column
cjk-wideEast Asian Ambiguous characters take two columns

A profile reproduces width and resize policy. It does not emulate a named terminal as a whole.

That distinction matters when a test fails on a user’s machine but not in CI: the profile tells you which answers your assertions assumed, which is a real lead. It cannot tell you that a specific terminal is or is not affected.

A live session, replay, screenshot, and Runner pane count characters with the same profile. Termwright records the selected profile in the trace and reuses it during replay.

Replay uses the same profile and grapheme model as the live session.