prompt

js/tty/prompt.ts

fino:tty/prompt — interactive command-line prompts with non-interactive defaults.

PromptSession wraps the low-level fino:tty helpers and centralizes the policy for CI or redirected input: prompts either return explicit defaults or throw instead of blocking forever. The prompt surface intentionally covers simple text, yes/no, and select questions only. Hidden input, multiline editing, cancellation, fuzzy search, and full-screen terminal UI behavior are outside this module's current contract.

import { PromptSession } from 'fino:tty/prompt';

const prompt = new PromptSession();
const project = await prompt.text({ label: 'Project name', defaultValue: 'app' });
const install = await prompt.confirm({ label: 'Install dependencies', defaultValue: true });
const template = await prompt.select({
  label: 'Template',
  options: [{ label: 'HTTP server', value: 'server' }, 'empty'],
  defaultValue: 'server',
});

Interfaces

interface TextPromptOptions {

Options for a text prompt.

defaultValue is returned when the user submits an empty line and is also used automatically in non-interactive sessions. validate may return an error message to retry the prompt, or null/undefined to accept the value.

import { PromptSession } from 'fino:tty/prompt';

const prompt = new PromptSession();
const options = {
  label: 'Project name',
  defaultValue: 'app',
  validate: (value) => value ? null : 'Name is required',
};
await prompt.text(options);

Properties

label: string

Label shown before the input field.

const options = { label: 'Project name' };
defaultValue?: string

Value used for empty input and non-interactive mode.

const options = { label: 'Project name', defaultValue: 'app' };
validate?: (value: string) => string | null | undefined

Optional validator that returns an error message when input is invalid.

const options = {
  label: 'Port',
  validate: (value: string) => Number(value) > 0 ? null : 'Enter a port',
};

interface ConfirmPromptOptions {

Options for a yes/no prompt.

defaultValue controls the hint (Y/n or y/N) and is returned when the user submits an empty line. In non-interactive mode it is required.

import { PromptSession } from 'fino:tty/prompt';

const prompt = new PromptSession();
const options = {
  label: 'Install dependencies',
  defaultValue: true,
};
await prompt.confirm(options);

Properties

label: string

Question shown before the yes/no hint.

const options = { label: 'Continue' };
defaultValue?: boolean

Boolean returned for empty input and non-interactive mode.

const options = { label: 'Overwrite', defaultValue: false };

interface SelectPromptOptions {

Options for a select prompt.

Options may be strings, where label and value are the same, or objects with separate display labels and returned values. In non-interactive mode, defaultValue is returned without checking that it appears in options.

import { PromptSession } from 'fino:tty/prompt';

const prompt = new PromptSession();
const options = {
  label: 'Template',
  options: [{ label: 'HTTP server', value: 'server' }, 'empty'],
  defaultValue: 'server',
};
await prompt.select(options);

Properties

label: string

Heading printed above the numbered choices.

const options = { label: 'Template', options: ['empty'] };
options: Array<{ label: string; value: string; } | string>

Choices accepted by number, exact label, or exact value.

const options = {
  label: 'Template',
  options: [{ label: 'HTTP server', value: 'server' }, 'empty'],
};
defaultValue?: string

Value returned for empty input and non-interactive mode.

const options = {
  label: 'Template',
  options: ['empty'],
  defaultValue: 'empty',
};

interface PromptSessionOptions {

Constructor options for PromptSession.

Tests and CLI tools can inject custom read/write functions to avoid touching process stdio. When isInteractive is false, prompts return defaults or throw instead of reading from stdin.

import { PromptSession } from 'fino:tty/prompt';

const options = {
  isInteractive: false,
  readLine: async () => null,
  write: async () => {},
  writeError: async () => {},
};
const prompt = new PromptSession(options);

Properties

isInteractive?: boolean

Override automatic TTY detection.

const options = { isInteractive: false };
readLine?: (prompt: string) => Promise<string | null>

Function used to read one prompted line.

const options = { readLine: async (prompt: string) => 'answer' };
write?: (text: string) => Promise<void>

Function used for normal prompt output.

const options = { write: async (text: string) => {} };
writeError?: (text: string) => Promise<void>

Function used for validation and choice errors.

const options = { writeError: async (text: string) => {} };

Classes

class PromptSession {

Stateful prompt runner for text, confirm, and select questions.

import { PromptSession } from 'fino:tty/prompt';

const prompt = new PromptSession();
const name = await prompt.text({ label: 'Project name', defaultValue: 'app' });
const install = await prompt.confirm({ label: 'Install dependencies', defaultValue: true });

Properties

isInteractive: boolean

Whether this session may ask questions on stdin/stdout.

import { PromptSession } from 'fino:tty/prompt';

const prompt = new PromptSession({ isInteractive: false });
prompt.isInteractive; // false

Constructors

constructor(options: PromptSessionOptions = {})

Create a prompt session.

By default the session is interactive only when both stdin and stdout are TTYs. Inject readLine, write, and writeError in tests or command flows that need deterministic prompt behavior.

import { PromptSession } from 'fino:tty/prompt';

const prompt = new PromptSession({
  isInteractive: true,
  readLine: async () => 'yes',
  write: async () => {},
  writeError: async () => {},
});

Methods

async text(options: TextPromptOptions): Promise<string>

Ask for a text value, repeating until optional validation passes.

Empty input resolves to defaultValue when provided. In non-interactive mode, this method returns defaultValue or throws if no default exists.

import { PromptSession } from 'fino:tty/prompt';

const prompt = new PromptSession();
const name = await prompt.text({ label: 'Name', defaultValue: 'app' });
async confirm(options: ConfirmPromptOptions): Promise<boolean>

Ask a yes/no question and return the selected boolean value.

Accepts y, yes, n, and no case-insensitively. Empty input uses defaultValue when available.

import { PromptSession } from 'fino:tty/prompt';

const prompt = new PromptSession();
const proceed = await prompt.confirm({ label: 'Continue', defaultValue: true });
async select(options: SelectPromptOptions): Promise<string>

Ask the user to choose one labeled option and return its value.

The user may enter a one-based number, an exact label, or an exact value. In non-interactive mode, this method returns defaultValue or throws if no default exists.

import { PromptSession } from 'fino:tty/prompt';

const prompt = new PromptSession();
const template = await prompt.select({
  label: 'Template',
  options: [{ label: 'HTTP server', value: 'server' }, 'empty'],
  defaultValue: 'server',
});

Functions

function createDefaultPrompt(): PromptSession

Create a PromptSession using the process standard input and output.

This is a convenience wrapper for new PromptSession(). The returned session follows the same automatic TTY detection and non-interactive default policy.

import { createDefaultPrompt } from 'fino:tty/prompt';

const prompt = createDefaultPrompt();
const name = await prompt.text({ label: 'Name', defaultValue: 'app' });