<!-- Generated by scripts/ax-docs.mts from the JSDoc in registry/ouro/ax/. Do not edit; run `pnpm run docs`. -->

# ax-terminal

What a terminal shows a person, with a plain fallback off a terminal: colour, status marks, the time something took, next steps and a progress line for anything slow. Colour is on only for a terminal; `NO_COLOR` always turns it off, and `FORCE_COLOR` turns it on for a capture. Off a terminal, the marks are words and nothing is redrawn, so a pipe, a log or an agent gets plain text with no escape codes.

```sh
npx shadcn@latest add ourostack/ouro-ui/ax-terminal#v1.3.10
```

It installs `lib/ouro/ax/terminal.ts`, with `ax-outcome`, `ax-voice`. Its tests are `ax-terminal-tests`. Every item runs on Node 22.18 or later as it is copied: the files import each other as `./<file>.ts`. The [Ouro AX guide](ax.md) shows how they fit together.

## Exports

### `createProgress`

Progress for anything slow, on stderr. On a terminal, a spinner line with the step, its place and the time so far, drawn only once a step has run past a short delay, redrawn in place and wiped when it ends, with spaces rather than escape codes. Off a terminal or in CI, one plain line for a step still running after the slow mark, and nothing else. With `off`, nothing.

```ts
function createProgress(stream: ProgressStream, options: ProgressOptions): Progress
```

### `FRAMES`

The spinner's frames, on a terminal.

```ts
const FRAMES: readonly string[]
```

### `hasAnsi`

Whether text holds an escape character: what the X-ray looks for in piped output.

```ts
function hasAnsi(text: string): boolean
```

### `Mark`

```ts
type Mark = "passed" | "failed" | "errored" | "warned" | "skipped" | "planned";
```

### `markOf`

A state's mark: its symbol in its colour on a terminal, else its word, so a reader without colour still tells a failure from a pass.

```ts
function markOf(state: Mark, style: TerminalStyle): string
```

### `MARKS`

A state's mark, as a symbol on a terminal and as a word elsewhere, and its colour.

```ts
const MARKS: Readonly<Record<Mark, { symbol: string; word: string; color: keyof Paint }>>
```

### `nextStepsText`

The next steps, under a `Next` heading: each step's reason, then its command on the line below, indented and alone, so it can be copied whole. An empty string for an empty list.

```ts
function nextStepsText(steps: readonly NextStep[], style: TerminalStyle): string
```

### `paint`

The colours, as functions that wrap text in their escape codes when the style has colour, and return it unchanged when it doesn't.

```ts
function paint(style: Pick<TerminalStyle, "color">): Paint
```

### `Paint`

```ts
type Paint = Record<"bold" | "dim" | "red" | "green" | "yellow" | "cyan", (text: string) => string>;
```

### `Progress`

One running step: start it, then stop it when it ends.

```ts
interface Progress {
  start(label: string, at?: { index: number; total: number }): void;
  stop(): void;
}
```

### `ProgressOptions`

```ts
interface ProgressOptions {
  env: Readonly<Record<string, string | undefined>>;
  off?: boolean;
  slowMs?: number;
  delayMs?: number;
  frameMs?: number;
  timers?: Timers;
}
```

### `ProgressStream`

Where progress goes: stderr, so stdout keeps only the result.

```ts
interface ProgressStream {
  write(text: string): unknown;
  isTTY?: boolean;
}
```

### `stripAnsi`

The text with its ANSI escape sequences taken out.

```ts
function stripAnsi(text: string): string
```

### `terminalStyle`

The style for one stream: a terminal gets colour and symbols; a pipe, or a terminal in CI (the `CI` variable set), gets words and no colour. `NO_COLOR` (set and not empty) always turns colour off, and `FORCE_COLOR` or `CLICOLOR_FORCE` turns colour and symbols on off a terminal and in CI, for a screenshot or a capture.

```ts
function terminalStyle(stream: { isTTY?: boolean | undefined; }, env: Readonly<Record<string, string | undefined>>): TerminalStyle
```

### `TerminalStyle`

What a terminal shows a person, with a plain fallback off a terminal: colour, status marks, the time something took, next steps and a progress line for anything slow. Colour is on only for a terminal; `NO_COLOR` always turns it off, and `FORCE_COLOR` turns it on for a capture. Off a terminal, the marks are words and nothing is redrawn, so a pipe, a log or an agent gets plain text with no escape codes.

```ts
interface TerminalStyle {
  tty: boolean;
  color: boolean;
  symbols: boolean;
}
```

### `Timers`

The clock and timers progress uses; tests pass held ones.

```ts
interface Timers {
  now(): number;
  setTimeout(fn: () => void, ms: number): unknown;
  clearTimeout(handle: unknown): void;
  setInterval(fn: () => void, ms: number): unknown;
  clearInterval(handle: unknown): void;
}
```

### `timeText`

How long something took, for a person: tenths of a second under a minute (`0.4s`, `14.2s`), then minutes and seconds (`1m 05s`).

```ts
function timeText(ms: number): string
```
