0Z4C0
// navigation
// @ozaco/cli

Core

Protocol definitions, ANSI helpers and shared types every CLI module builds on.

import from@ozaco/cli/core

@ozaco/cli/core is the contract layer of the CLI package. It declares six std:plugin protocols — Terminal, Palette, Spinner, Prompt, Registry and Table — plus the types, tags and low-level helpers they share. It ships no behavior of its own; concrete implementations live in the sibling entries (@ozaco/cli/terminal/bun, @ozaco/cli/palette, @ozaco/cli/spinner, and so on).

A protocol is an abstract capability: you install one implementation into the current effect scope, then call its actions from anywhere downstream. Because every module depends only on these protocols — never on a specific backend — the terminal can be swapped for a test double, the palette for a themed one, without touching call sites.

Alongside the protocols, core exposes ansi (cursor and erase escape sequences), the CoreErrors failure tags, the registered Symbol subtype tags that identify each protocol, and the structural Key/Size/InputStream/OutputStream types used across the package. The per-protocol *Def namespaces carry the full option, context and action shapes.

01

Protocols

The six capabilities the CLI is built from. Install an implementation, then call its `.actions`.

const

Terminal

Low-level terminal I/O: size, raw-input sessions, key streams and rendering.

signature
const Terminal: Protocol<
  TerminalDef.Context,
  [options?: TerminalDef.Options],
  TerminalDef.Actions
>
// name 'cli/terminal', subtype TERMINAL

The foundation the interactive modules render through. Implemented by BunTerminal from @ozaco/cli/terminal/bun. Actions cover size, isInteractive, session, write, keys, stripAnsi, wrapAnsi, displayWidth and renderer.

example
import { Terminal } from '@ozaco/cli/core'

const { columns, rows } = yield* Terminal.actions.size()
yield* Terminal.actions.write('hello\n')
const

Palette

Colors and glyphs, auto-detected from the environment and TTY.

signature
const Palette: Protocol<
  PaletteDef.Context,
  [options?: PaletteDef.Options],
  PaletteDef.Actions
>
// name 'cli/palette', subtype PALETTE

Resolves an ANSI color set and a unicode/ascii symbol set. Implemented by DefaultPalette / definePalette from @ozaco/cli/palette. Exposes colors() and symbols() actions.

const

Spinner

Live progress: single spinners, progress bars and nested task trees.

signature
const Spinner: Protocol<
  SpinnerDef.Context,
  [options?: SpinnerDef.Options],
  SpinnerDef.Actions
>
// name 'cli/spinner', subtype SPINNER

Implemented by DefaultSpinner from @ozaco/cli/spinner. Actions start, bar and group return handles that update in place while interactive and degrade to plain lines otherwise.

const

Prompt

Interactive questions: text, password, number, confirm, select and more.

signature
const Prompt: Protocol<
  PromptDef.Context,
  [options?: PromptDef.Options],
  PromptDef.Actions
>
// name 'cli/prompt', subtype PROMPT

Implemented by DefaultPrompt from @ozaco/cli/prompt. Actions text, password, number, confirm, select, multiselect, autocomplete and path each run a full-screen editor over the terminal session.

const

Registry

The command registry: register command trees, then dispatch argv to them.

signature
const Registry: Protocol<
  RegistryDef.Context,
  [options?: RegistryDef.Options],
  RegistryDef.Actions
>
// name 'cli/registry', subtype REGISTRY

Implemented by DefaultRegistry from @ozaco/cli/command. Actions register, run and get compile command specs into a path-identified plugin tree and route argv[0] to the matching command.

const

Table

Streaming tables that redraw in place, or append-only in a pipe.

signature
const Table: Protocol<
  TableDef.Context,
  [options?: TableDef.Options],
  TableDef.Actions
>
// name 'cli/table', subtype TABLE

Implemented by DefaultTable from @ozaco/cli/table. The single table action opens a handle whose row/rows/update/set/end feed a live, auto-fitting table.

02

ANSI & sizing

Escape-sequence helpers and the fallback terminal dimensions.

const

ansi

Cursor movement and screen-erase escape sequences.

signature
const ansi: {
  esc: string // ESC (U+001B)
  csi: string // Control Sequence Introducer, ESC + '['
  cursorUp(count?: number): string
  cursorDown(count?: number): string
  cursorForward(count?: number): string
  cursorBackward(count?: number): string
  cursorToColumn(column?: number): string // absolute, 0-based
  eraseLine: string
  eraseDown: string
  hideCursor: string
  showCursor: string
}

Cursor helpers return an empty string for non-positive counts, so callers need not guard. Used by the renderer and every interactive module to repaint frames.

example
import { ansi } from '@ozaco/cli/core'

process.stdout.write(ansi.hideCursor)
process.stdout.write(ansi.cursorToColumn(0) + ansi.eraseLine)
const

DEFAULT_COLUMNS

Fallback terminal width (80) when no size can be probed.

signature
const DEFAULT_COLUMNS = 80
const

DEFAULT_ROWS

Fallback terminal height (24) when no size can be probed.

signature
const DEFAULT_ROWS = 24
03

Errors

const

CoreErrors

The `cli:core.*` failure tags the CLI raises through `fail`.

signature
const CoreErrors: {
  Unsupported: 'cli:core.unsupported'
  Cancelled: 'cli:core.cancelled'
  NotInteractive: 'cli:core.not-interactive'
  Missing: 'cli:core.missing'
}

Built with createTags, so each kebab-case name becomes a PascalCase key mapping to a dotted tag. Prompts fail with Cancelled on Ctrl-C and NotInteractive when there is no TTY and no usable fallback.

04

Subtype tags

Registered symbols that identify each protocol subtype.

const

TERMINAL

Subtype tag for the `Terminal` protocol.

signature
const TERMINAL: unique symbol // Symbol.for('cli:core:terminal')
const

SPINNER

Subtype tag for the `Spinner` protocol.

signature
const SPINNER: unique symbol // Symbol.for('cli:core:spinner')
const

PALETTE

Subtype tag for the `Palette` protocol.

signature
const PALETTE: unique symbol // Symbol.for('cli:core:palette')
const

PROMPT

Subtype tag for the `Prompt` protocol.

signature
const PROMPT: unique symbol // Symbol.for('cli:core:prompt')
const

REGISTRY

Subtype tag for the `Registry` protocol.

signature
const REGISTRY: unique symbol // Symbol.for('cli:core:registry')
const

TABLE

Subtype tag for the `Table` protocol.

signature
const TABLE: unique symbol // Symbol.for('cli:core:table')
05

Context

const

KeyStreamContext

The decoded key stream bound for the duration of a `Terminal.session()`.

signature
const KeyStreamContext: Context<Stream<Key, void>> // 'cli:keys'

Set by session() and read by Terminal.actions.keys(). Prompts subscribe to it to receive keypresses; outside a session it is unset.

06

Common types

Structural shapes shared across the terminal and prompt layers.

iface

Size

Terminal dimensions in character cells.

signature
interface Size {
  columns: number
  rows: number
}
iface

Key

A decoded keypress: logical name, raw sequence, modifiers and bytes.

signature
interface Key {
  // 'up'/'down'/'left'/'right', 'return', 'backspace', 'delete', 'tab',
  // 'escape', 'space', 'home', 'end', 'pageup', 'pagedown', a printable char,
  // or 'unknown'
  name: string
  sequence: string
  ctrl: boolean
  meta: boolean
  shift: boolean
  raw: Uint8Array
}
iface

InputStream

Minimal readable-input shape (Node `ReadStream` or a test double).

signature
interface InputStream {
  on(event: string, listener: (...args: AnyType[]) => void): this
  off(event: string, listener: (...args: AnyType[]) => void): this
  setRawMode?(mode: boolean): unknown
  resume?(): unknown
  pause?(): unknown
  isTTY?: boolean
}
iface

OutputStream

Minimal writable-output shape (Node `WriteStream` or a test double).

signature
interface OutputStream {
  write(data: string): unknown
  columns?: number
  rows?: number
  isTTY?: boolean
}
07

Protocol contracts

The `*Def` namespaces carrying each protocol’s option, context and action types.

ns

TerminalDef

Types for the `Terminal` protocol: options, context, renderer and actions.

signature
type TerminalDef = Plugin<TerminalDef.Context, [options?: TerminalDef.Options], TerminalDef.Actions>

The TerminalDef namespace also exposes:

  • Encoding'utf8' | 'hex' | 'binary' | 'ascii' | 'base64'.
  • Options{ input?, output?, error?, interactive?, encoding? }; interactive defaults to the streams’ isTTY.
  • Context — the resolved { input, output, error, interactive, encoding }.
  • WrapAnsiOptions{ hard?, wordWrap?, trim?, ambiguousIsNarrow? } for wrapAnsi.
  • Renderer{ render(frame), clear(), done(frame?) } for in-place frames.
  • Actionssize, isInteractive, session, write, keys, stripAnsi, wrapAnsi, displayWidth, renderer.
ns

PaletteDef

Types for the `Palette` protocol: colors, symbols, options and actions.

signature
type PaletteDef = Plugin<PaletteDef.Context, [options?: PaletteDef.Options], PaletteDef.Actions>

The PaletteDef namespace also exposes:

  • Style(text: string) => string, a single color/effect wrapper.
  • Colorsprimary, success, error, warning, info, muted, accent, plus bold, dim, underline, inverse, strikethrough.
  • Symbols — glyphs like question, answered, error, pointer, checkboxOn/Off, barComplete/Incomplete, and the spinner frame array.
  • Options{ color?, unicode?, colors?, symbols? } (partial overrides).
  • Context — the resolved { color, unicode, colors, symbols }.
  • Actionscolors() and symbols().
ns

SpinnerDef

Types for the `Spinner` protocol: start/bar/group options and their handles.

signature
type SpinnerDef = Plugin<SpinnerDef.Context, [options?: SpinnerDef.Options], SpinnerDef.Actions>

The SpinnerDef namespace also exposes:

  • StartOptions{ message?, frames?, interval?, color? }.
  • Handle — a single spinner: update, succeed, fail, warn, info, stop.
  • BarOptions / NodeBarOptions and BarHandle — progress bars: update, advance, succeed, fail, stop.
  • GroupOptions / GroupHandle — a live tree spawning task/bar children.
  • TaskHandle — a tree node that can nest further task/bar children.
  • Actionsstart, bar, group.
ns

PromptDef

Types for the `Prompt` protocol: per-prompt option shapes and actions.

signature
type PromptDef = Plugin<PromptDef.Context, [options?: PromptDef.Options], PromptDef.Actions>

The PromptDef namespace also exposes:

  • Base{ message, description? }, extended by every prompt option type.
  • Choice<T>{ value, label?, hint?, disabled? } for list prompts.
  • Validate<T>(value: T) => string | undefined (return a message to reject).
  • TextOptions, PasswordOptions, NumberOptions, ConfirmOptions, SelectOptions<T>, MultiSelectOptions<T>, AutocompleteOptions<T>, PathOptions.
  • Actionstext, password, number, confirm, select, multiselect, autocomplete, path.
ns

RegistryDef

Types for the `Registry` protocol: command shape, options and dispatch actions.

signature
namespace RegistryDef {
  interface Command { name: string; description?: string | undefined }
  interface Options { name?; version?; description? }
  interface Context {
    name: string
    version?: string | undefined
    description?: string | undefined
    commands: Map<string, RegistryDef.Command>
  }
  interface Actions {
    register(command: RegistryDef.Command): Future<void>
    run(argv?: string[]): Future<void>
    get(name: string): Future<RegistryDef.Command | undefined>
  }
}

Command is kept structural (just name/description) so core needn’t depend on cli:command. register compiles a command spec and runs its setup; run selects argv[0] and dispatches the rest to it.

ns

TableDef

Types for the `Table` protocol: column config, options, handle and actions.

signature
type TableDef = Plugin<TableDef.Context, [options?: TableDef.Options], TableDef.Actions>

The TableDef namespace also exposes:

  • Align'left' | 'right' | 'center'; Border'none' | 'header' | 'full'.
  • Cellstring | number | boolean | null | undefined; Row — a tuple or a keyed record.
  • Column{ header?, key?, width?, min?, max?, align?, color?, format? }.
  • Options{ columns, border?, gutter?, head?, window? }.
  • Handlerow, rows, update, set, end for streaming rows.
  • Actionstable(options), opening a streaming table handle.