中文

Ecosystem guide

Choose Node.js tools for local databases, colors, prompts, task output, progress, and terminal interfaces.

Updated

func handles the command model, typed input, and dependency injection without prescribing a CLI’s storage, presentation, or interaction choices. The built-in modules and packages below cover common requirements around it. Each group includes a practical default and alternatives for projects with different compatibility or API requirements.

Reading the comparison

The download column reports approximate npm downloads from 2026-07-31 through 2026-08-06, shortened with M (million) and K (thousand). It is useful as an adoption signal, but includes automated and transitive installs; it is not a count of active users or a quality ranking.

The bundle column is a representative increase from a minified, tree-shaken, single-file ESM CLI measured with esbuild. Values are rounded to the nearest KiB. Bundle size is only one selection criterion. Also consider maintenance activity, supported Node.js versions, ESM/CJS compatibility, documentation, API design, accessibility, testability, and whether the library matches the interaction model of the CLI. Measure the real application entry before making a size-sensitive release decision.

Local databases

For structured data owned by one CLI installation, start with Node.js’s built-in node:sqlite. func requires Node.js 24.15 or newer, so this default needs no database package, native add-on, or separate server. Its synchronous DatabaseSync API fits short commands, local indexes, caches, history, and tests that use :memory:.

import { Injectable } from 'func'
import type { OnDispose } from 'func'
import { DatabaseSync } from 'node:sqlite'

type Project = Readonly<{ path: string }>

@Injectable()
export class DatabaseService implements OnDispose {
  private readonly database = new DatabaseSync('data.sqlite', {
    timeout: 5_000,
  })
  private readonly findProjectStatement = this.database.prepare(
    'SELECT path FROM projects WHERE name = ?',
  )

  findProject(name: string) {
    return this.findProjectStatement.get(name) as Project | undefined
  }

  onDispose() {
    this.database.close()
  }
}

Register DatabaseService in the owning module’s providers and inject it into commands through their constructors. func creates the service only when a selected command needs it and calls onDispose() after the invocation.

Use prepared statements for values that come from users, and keep transactions short. When several local processes may access the same database, consider write-ahead logging, but do not place a WAL database on a network filesystem. Because every DatabaseSync operation blocks the current JavaScript thread, use a worker or an external database and driver for long-running queries, high write concurrency, or data shared across hosts.

Text colors and styles

Node.js provides util.styleText for basic ANSI styles without a dependency. The following packages are useful when a shared API, richer colors, or broader module compatibility matters.

PackageRecent weekly downloadsBest suited forRepresentative bundle increase
picocolors≈218MA small ESM/CJS API for common colors and emphasis; the default third-party choice for straightforward output2 KiB
ansis≈44.5MESM/CJS support together with HEX/RGB colors, templates, and automatic fallback4 KiB
chalk≈486MA mature chainable API, rich color support, and broad ecosystem familiarity8 KiB
kleur≈90.7MA compact chainable ESM/CJS API, especially when an existing project already uses it2 KiB

Start with picocolors for a new CLI that only needs common colors. Choose ansis for richer colors without giving up ESM/CJS support, or chalk when its established API and integrations matter more than the additional size.

Prompts, spinners, and task flows

PackageRecent weekly downloadsBest suited forRepresentative bundle increase
@clack/prompts≈18.0MProject creators and setup wizards that benefit from consistent prompts, logs, and spinners17 KiB
@inquirer/prompts≈34.6MBroader input types, modular imports, and custom prompt development28 KiB
listr2≈43.3MNested, concurrent, skippable, or dynamically updated groups of tasks79 KiB
ora≈83.5MOne or a few standalone asynchronous operations with explicit success, warning, and failure states58 KiB

Use @clack/prompts for a guided installation or configuration flow and @inquirer/prompts when the available prompt types or extension points are the deciding factor. ora fits an isolated operation; listr2 becomes more useful when several tasks must remain visible and have independent states.

Tables, progress, and highlighted output

PackageRecent weekly downloadsBest suited forRepresentative bundle increase
cli-table3≈32.1MANSI-aware tables with alignment, wrapping, or row and column spans34 KiB
cli-progress≈10.1MOne or several progress bars for work with a measurable total24 KiB
boxen≈27.7MBordered notices, summaries, and a small number of high-value messages49 KiB
log-update≈43.9MA low-level primitive for redrawing custom multi-line output in place34 KiB

cli-table3 is the general choice for report-style output, while cli-progress is more appropriate when completion can be expressed numerically. Choose boxen for emphasis rather than layout. Use log-update when a packaged spinner or progress renderer cannot express the required output.

Full terminal interfaces

A TUI framework is appropriate when the application needs keyboard navigation, focus management, persistent multi-region layout, or full-screen updates. It is unnecessary for a table, prompt, or single spinner.

PackageRecent weekly downloadsBest suited forRepresentative bundle increase
ink≈5.7MReact teams that want components, state, Flexbox-style layout, and component testing362 KiB
terminal-kit≈202KImperative keyboard, mouse, screen-buffer, drawing, and image featuresNo reliable single-file result
blessed≈1.4MMaintaining widget-based terminal applications already built on its DOM-like API264 KiB

Ink is the clearest starting point for a new React-based terminal application. Terminal Kit exposes a wider set of low-level terminal capabilities, but its dynamic resources require extra care when producing a single-file executable. Blessed remains relevant to existing applications; evaluate its maintenance and compatibility carefully before adopting it for a new project.

Used by well-known projects

These examples show how established projects use the same packages at different levels of interaction. They are references, not endorsements or substitutes for evaluating a library against the requirements of your own CLI.

PackageProjectsSources
@clack/promptsVite’s create-vite, OpenClaw, create-t3-app, and OpenCodeVite source, OpenClaw dependency
inkClaude Code, Gemini CLI, GitHub Copilot CLI, Cloudflare Wrangler, Prisma, Shopify CLI, and Canva CLIInk’s official project showcase

For a minimal invocation-scoped integration, see Interactive applications.