Core
Protocol definitions, ANSI helpers and shared types every CLI module builds on.
@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.
Protocols
The six capabilities the CLI is built from. Install an implementation, then call its `.actions`.
Terminal
Low-level terminal I/O: size, raw-input sessions, key streams and rendering.
const Terminal: Protocol<
TerminalDef.Context,
[options?: TerminalDef.Options],
TerminalDef.Actions
>
// name 'cli/terminal', subtype TERMINALThe 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.
import { Terminal } from '@ozaco/cli/core'
const { columns, rows } = yield* Terminal.actions.size()
yield* Terminal.actions.write('hello\n')Palette
Colors and glyphs, auto-detected from the environment and TTY.
const Palette: Protocol<
PaletteDef.Context,
[options?: PaletteDef.Options],
PaletteDef.Actions
>
// name 'cli/palette', subtype PALETTEResolves an ANSI color set and a unicode/ascii symbol set. Implemented by DefaultPalette / definePalette from @ozaco/cli/palette. Exposes colors() and symbols() actions.
Spinner
Live progress: single spinners, progress bars and nested task trees.
const Spinner: Protocol<
SpinnerDef.Context,
[options?: SpinnerDef.Options],
SpinnerDef.Actions
>
// name 'cli/spinner', subtype SPINNERImplemented 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.
Prompt
Interactive questions: text, password, number, confirm, select and more.
const Prompt: Protocol<
PromptDef.Context,
[options?: PromptDef.Options],
PromptDef.Actions
>
// name 'cli/prompt', subtype PROMPTImplemented 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.
Registry
The command registry: register command trees, then dispatch argv to them.
const Registry: Protocol<
RegistryDef.Context,
[options?: RegistryDef.Options],
RegistryDef.Actions
>
// name 'cli/registry', subtype REGISTRYImplemented 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.
Table
Streaming tables that redraw in place, or append-only in a pipe.
const Table: Protocol<
TableDef.Context,
[options?: TableDef.Options],
TableDef.Actions
>
// name 'cli/table', subtype TABLEImplemented 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.
ANSI & sizing
Escape-sequence helpers and the fallback terminal dimensions.
ansi
Cursor movement and screen-erase escape sequences.
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.
import { ansi } from '@ozaco/cli/core'
process.stdout.write(ansi.hideCursor)
process.stdout.write(ansi.cursorToColumn(0) + ansi.eraseLine)DEFAULT_COLUMNS
Fallback terminal width (80) when no size can be probed.
const DEFAULT_COLUMNS = 80DEFAULT_ROWS
Fallback terminal height (24) when no size can be probed.
const DEFAULT_ROWS = 24Errors
CoreErrors
The `cli:core.*` failure tags the CLI raises through `fail`.
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.
Context
KeyStreamContext
The decoded key stream bound for the duration of a `Terminal.session()`.
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.
Common types
Structural shapes shared across the terminal and prompt layers.
Size
Terminal dimensions in character cells.
interface Size {
columns: number
rows: number
}Key
A decoded keypress: logical name, raw sequence, modifiers and bytes.
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
}InputStream
Minimal readable-input shape (Node `ReadStream` or a test double).
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
}OutputStream
Minimal writable-output shape (Node `WriteStream` or a test double).
interface OutputStream {
write(data: string): unknown
columns?: number
rows?: number
isTTY?: boolean
}Protocol contracts
The `*Def` namespaces carrying each protocol’s option, context and action types.
TerminalDef
Types for the `Terminal` protocol: options, context, renderer and actions.
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? };interactivedefaults to the streams’isTTY. - •
Context— the resolved{ input, output, error, interactive, encoding }. - •
WrapAnsiOptions—{ hard?, wordWrap?, trim?, ambiguousIsNarrow? }forwrapAnsi. - •
Renderer—{ render(frame), clear(), done(frame?) }for in-place frames. - •
Actions—size,isInteractive,session,write,keys,stripAnsi,wrapAnsi,displayWidth,renderer.
PaletteDef
Types for the `Palette` protocol: colors, symbols, options and actions.
type PaletteDef = Plugin<PaletteDef.Context, [options?: PaletteDef.Options], PaletteDef.Actions>The PaletteDef namespace also exposes:
- •
Style—(text: string) => string, a single color/effect wrapper. - •
Colors—primary,success,error,warning,info,muted,accent, plusbold,dim,underline,inverse,strikethrough. - •
Symbols— glyphs likequestion,answered,error,pointer,checkboxOn/Off,barComplete/Incomplete, and thespinnerframe array. - •
Options—{ color?, unicode?, colors?, symbols? }(partial overrides). - •
Context— the resolved{ color, unicode, colors, symbols }. - •
Actions—colors()andsymbols().
SpinnerDef
Types for the `Spinner` protocol: start/bar/group options and their handles.
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/NodeBarOptionsandBarHandle— progress bars:update,advance,succeed,fail,stop. - •
GroupOptions/GroupHandle— a live tree spawningtask/barchildren. - •
TaskHandle— a tree node that can nest furthertask/barchildren. - •
Actions—start,bar,group.
PromptDef
Types for the `Prompt` protocol: per-prompt option shapes and actions.
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. - •
Actions—text,password,number,confirm,select,multiselect,autocomplete,path.
RegistryDef
Types for the `Registry` protocol: command shape, options and dispatch actions.
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.
TableDef
Types for the `Table` protocol: column config, options, handle and actions.
type TableDef = Plugin<TableDef.Context, [options?: TableDef.Options], TableDef.Actions>The TableDef namespace also exposes:
- •
Align—'left' | 'right' | 'center';Border—'none' | 'header' | 'full'. - •
Cell—string | 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? }. - •
Handle—row,rows,update,set,endfor streaming rows. - •
Actions—table(options), opening a streaming table handle.