oscli

Flags

Parse typed flags before your handler runs and bypass prompts in CI.

Flags are resolved before your handler runs. Define them once in createCLI(), then read typed values from cli.flags anywhere in the flow.

Chain order

Set the type first, then add metadata and defaults.

Flag chain order
b.flag()
  .string() // or .boolean() or .number()
  .label()
  .choices()
  .default()
  .optional()

Builder types

These are the available flag builders.

Prop

Type

Define typed flags

Use literal choices when you want a union type in cli.flags.

src/cli.ts
import { createCLI } from "@oscli-dev/oscli";

export const cli = createCLI((b) => ({
  description: "create-db",
  flags: {
    ttl: b.flag().string().label("TTL").default("1h"),
    json: b
      .flag()
      .boolean()
      .label("JSON output")
      .default(false),
    env: b
      .flag()
      .string()
      .choices(["dev", "staging", "prod"] as const)
      .label("Environment"),
  },
  prompts: {
    name: b.text().label("Database name"),
  },
}));

await cli.run(async () => {
  cli.log("info", `env: ${cli.flags.env ?? "dev"}`);
  await cli.prompt.name();
});

Prompt bypass

Every prompt can be bypassed with a matching flag. Validation still runs.

src/cli.ts
export const cli = createCLI((b) => ({
  description: "prompt bypass",
  prompts: {
    project: b.text().label("Project").default("my-app"),
    teamSize: b.number().label("Team size").min(1).max(10),
    approved: b.confirm().label("Continue?"),
  },
}));

await cli.run(async () => {
  await cli.prompt.project();
  await cli.prompt.teamSize();
  await cli.prompt.approved();
});

This command runs without interactive input:

Shell
bun run src/cli.ts --project oscli --teamSize 3 --approved

Global flags

These flags are reserved by oscli.

Prop

Type

Do not define custom flags named yes, no-color, or json. Those names are reserved by oscli.

Prompt bypass shapes

Prompt bypass flags are generated automatically from your prompt definitions.

Prop

Type

On this page