Getting started
Install oscli, define one flow, and ship a typed CLI in a few lines.
oscli is a TypeScript-first CLI framework published on npm. You define
prompts and flags once with a builder API, run your flow, then read typed
values from cli.storage and cli.flags.
Install
Use the package manager you already use.
npm install @oscli-dev/oscliYour first CLI
Start with the smallest possible CLI. This example stays under 10 lines and is complete.
import { createCLI } from "@oscli-dev/oscli";
const cli = createCLI(() => ({ description: "my tool" }));
await cli.run(async () => {
cli.success("Done.");
});Use this shape when you want a single-command CLI with no prompts yet.
Build a prompt-driven CLI
Add prompts, run them once, and read the resolved values from cli.storage.
import { createCLI } from "@oscli-dev/oscli";
const cli = createCLI((b) => ({
description: "project setup",
prompts: {
project: b.text().label("Project").default("my-app"),
framework: b
.select({ choices: ["react", "vue", "svelte"] as const })
.label("Framework"),
approved: b.confirm().label("Continue?").default(true),
},
}));
await cli.run(async () => {
cli.intro("project setup");
await cli.prompt.project();
await cli.prompt.framework();
await cli.prompt.approved();
cli.success(`Created ${cli.storage.project}`);
cli.outro("Done.");
});Grow the same CLI
You can add JSON mode and return a machine-readable result without changing the rest of the flow.
const cli = createCLI((b) => ({
description: "project setup",
prompts: {
project: b.text().label("Project"),
},
json: true,
}));
await cli.run(async () => {
await cli.prompt.project();
cli.setResult({ project: cli.storage.project });
});Run that command with --json to suppress decorative output and print only the
JSON result.
Suggested layout
You do not need a special folder structure, but this is a clean starting point.
Setup flow
Use this order when you are starting a new CLI.
Install the package
Add @oscli-dev/oscli to your project.
Define prompts and flags
Put your builder definitions inside createCLI() so types are
inferred once and reused everywhere.
Run the flow
Call await cli.run(...), resolve prompts, and read values
from cli.storage and cli.flags.
oscli installs cleanly with npm, pnpm, Yarn, and Bun. The
published package targets Node 18+ at runtime.
Read next
Use these pages next.
Prompts
All prompt builders, confirm modes, validation, and transforms.
Flags
Typed flags, prompt bypass, and reserved globals.
Theme
Theme presets, overrides, and per-prompt color.
Visual primitives
Boxes, tables, progress, links, trees, and diffs.
Testing
Run the same CLI in Vitest without touching stdin.
Non-interactive and CI
TTY detection, no-color behavior, exit codes, and automation.