Skip to content
imlokeshPublic

About

Type-safe CLI builder and argument parser for Bun and Node.js: prompts for missing required options, validates input and generates help from one config object.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

20 Commits

Folders and files

Repository files navigation

Clide

Clide ("Command Line Guide") is a simple CLI parser for bun and nodejs. It can auto prompt for required options and displays help text for commands and options.

Install

bun add @imlokesh/clide
# or
npm install @imlokesh/clide

Quick Start

Suppose you want to accept a port parameter from the command line. It's as easy as this.

// index.ts
import clide from "@imlokesh/clide";

const program = await clide({
  options: {
    port: { type: "number", required: true },
  }
});

console.log(program.options.port);

Full Example

Create a CLI with global options, commands, and validation.

// index.ts
import clide from "@imlokesh/clide";

const program = await clide({
  description: "A friendly CLI tool",
  defaultCommand: "greet",
  options: {
    verbose: { type: "boolean", short: "v", description: "Enable verbose logs" },
  },
  commands: {
    greet: {
      description: "Greet a user",
      options: {
        name: { type: "string", short: "n", default: "World" },
        shout: { type: "boolean", short: "s" },
      },
    },
  },
});

if (program.command === "greet") {
  let msg = `Hello, ${program.options.name}`;
  if (program.options.shout) msg = msg.toUpperCase();
  console.log(msg);
}

Commands

Commands allow you to group options and behavior. Options defined inside a command are isolated to that command.

commands: {
  build: {
    options: { minify: { type: "boolean" } }
  },
  deploy: {
    options: { target: { type: "string" } }
  }
}

Default Command

You can define a defaultCommand to run when no command is specified. This is useful for single-purpose CLIs or tools with a primary action. For example, bun index.ts automatically runs bun run index.ts command).

const program = await clide({
  defaultCommand: "start",
  commands: {
    start: {
      description: "Start the server",
      options: { port: { type: "number", default: 3000 } }
    }
  }
});

console.log(JSON.stringify(program, null, 2));

When a user runs the CLI without a command, Clide treats it as an invocation of the default command:

$ cli

# {
#   "options": {
#     "port": 3000
#   },
#   "globalOptions": {},     
#   "commandOptions": {      
#     "port": 3000
#   },
#   "isDefaultCommand": true,
#   "command": "start"       
# }

Options Configuration

Options are typed, validated, and can be configured globally or per-command.

options: {
  // String with choices
  format: {
    type: "string",
    choices: ["json", "text"],
    default: "text",
  },
  
  // Number with validation
  port: {
    type: "number",
    env: "PORT", 
    validate: (n) => n > 1000 || "Port must be > 1000", // Return string for custom error
  },

  // Boolean (Negatable)
  color: {
    type: "boolean",
    default: true,
    negatable: true, // Auto-generates --no-color flag
  },
  
  // Required (Triggers Prompt)
  token: {
    type: "string",
    required: true,
    hidden: true, // Hides from help menu
  }
}

Option Precedence

Clide resolves option values in the following order (highest priority first):

  1. Command Line Flag (--port 3000)
  2. Environment Variable (PORT=3000)
  3. Default Value (default: 8080)

If an option is required and no value is found in any of these three places, Clide will trigger an interactive prompt (unless disabled).

Input Features

Short Flag Stacking

Clide supports stacking boolean short flags. If the last flag in the stack expects a value, it captures the next argument.

# Equivalent to: --verbose --force --user admin
$ cli -vfu admin

Positional Arguments & Terminator

To accept loose arguments (values without flags), enable allowPositionals.

Clide also supports the standard POSIX -- terminator. Everything following -- is always captured as a positional argument, regardless of the allowPositionals setting. This stops the parser from interpreting subsequent arguments as flags or commands.

# "-file.txt" is captured as a positional argument, not a flag
$ cli -- -file.txt
// program.positionals -> ["-file.txt"]

Strict Ordering

Global options must appear before the command, and command options after the command.

# ✅ Correct
$ cli --verbose build --minify

# ❌ Incorrect (Global flag after command)
$ cli build --minify --verbose

Prompts & Interactivity

If a required option is missing, Clide automatically prompts the user for input using readline.

Custom Prompts

You can override the default prompt behavior (e.g., to use inquirer or prompts) using promptAsync.

import clide, { type ClideOption, type OptionScope, type ClideProgram } from "@imlokesh/clide";

await clide({
  /* config */
  promptAsync: async (name: string, option: ClideOption, scope: OptionScope, program: Readonly<ClideProgram>) => {
    // Implement your custom prompt logic here
    return "user-value"; 
  }
});

Help & Error Handling

Auto-Generated Help

Clide automatically injects a --help, -h option for the main program and every command.

$ bun index.ts --help

It intelligently handles conflicts: if you define a custom option with short: "h", Clide will only use --help for the help menu, freeing up -h for your option.

Error Handling

By default, if an argument parsing error occurs (e.g., unknown option, missing value), Clide will:

  1. Print the error message in red.
  2. Display the help menu.
  3. Exit the process with code 1.

You can override this behavior using throwOnError: true to catch errors manually.

API Reference

Return Object

The clide function returns a program object containing parsed data.

const program = await clide(config);

program.command          // (string) Name of the selected command
program.options          // (object) Merged map of all active options (global + command)
program.globalOptions    // (object) Only global options
program.commandOptions   // (object) Only command-specific options
program.positionals      // (string[]) Array of positional args (if allowed or forced by --)
program.isDefaultCommand // (boolean) True if the default command was inferred

Config Options

Option Type Description
description string CLI description for help text.
commands object Definitions for subcommands.
options object Global option definitions.
defaultCommand string Command to run if none specified.
allowPositionals boolean Enable parsing of loose arguments.
throwOnError boolean If true, throws error object instead of printing help and exiting.
disableHelp boolean Disables auto-generated --help.
disablePrompts boolean Disables interactive prompts for missing required options.

License

MIT

About

Type-safe CLI builder and argument parser for Bun and Node.js: prompts for missing required options, validates input and generates help from one config object.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages