All packages
CLI 334/mo
@munesoft/

clix

The fastest way to turn a script into a CLI. Zero boilerplate, intuitive API, clean output.

Installation

$ npm install @munesoft/clix

Documentation

@munesoft/clix

Build a CLI in 5 lines. The fastest way to turn a script into a CLI tool.

js
import { cli } from "@munesoft/clix";

cli({
  greet: (name) => `Hello ${name}`
});
bash
node app.js greet John
# Hello John

Why clix?

Most CLI frameworks require boilerplate setup, config files, and long tutorials before you can run anything. clix takes a different approach: just map command names to functions and you're done.

| Feature | clix | commander | yargs | oclif | |---------|------|-----------|-------|-------| | Lines to first command | 3 | ~15 | ~10 | ~30+ | | Zero config | ✅ | ❌ | ❌ | ❌ | | Auto-generated help | ✅ | ✅ | ✅ | ✅ | | Async commands | ✅ | ✅ | ✅ | ✅ | | TypeScript-first | ✅ | ✅ | ⚠️ | ✅ | | ESM + CJS | ✅ | ✅ | ✅ | ⚠️ | | Subcommands | ✅ | ✅ | ✅ | ✅ | | Setup time | <2 min | ~10 min | ~10 min | ~30 min |


Installation

bash
npm install @munesoft/clix

Quickstart

Create app.js:

js
import { cli } from "@munesoft/clix";

cli({
  greet: (name) => `Hello ${name}`,
  add:   (a, b) => Number(a) + Number(b),
});

Run it:

bash
node app.js greet Alice    # Hello Alice
node app.js add 5 10       # 15
node app.js --help         # auto-generated help

That's it. No setup. No config. No program.command().argument().action().


Command Examples

Basic commands

js
cli({
  // String output
  say: (msg) => msg,

  // Math
  add: (a, b) => Number(a) + Number(b),

  // Object output (pretty-printed as JSON)
  info: () => ({ node: process.version, platform: process.platform }),
});

Flags and options

Flags are passed as the last argument to your function:

js
cli({
  say: (msg, flags) => flags.loud ? msg.toUpperCase() : msg,
});
bash
node app.js say hello           # hello
node app.js say hello --loud    # HELLO
node app.js serve --port=3000   # flags.port === 3000
node app.js serve --port 8080   # flags.port === 8080
node app.js run --debug         # flags.debug === true

Async commands

js
cli({
  fetch: async (url) => {
    const res = await fetch(url);
    return res.text();
  },

  delay: async (ms) => {
    await new Promise(r => setTimeout(r, Number(ms)));
    return "done";
  },
});

Subcommands

js
cli({
  // Space-separated subcommands
  "user create": (name) => `Created user: ${name}`,
  "user delete": (id)   => `Deleted user: ${id}`,

  // Or dot/colon notation
  "db.migrate": () => runMigrations(),
  "db:seed":    () => seedDatabase(),
});
bash
node app.js user create Alice
node app.js db.migrate

Command descriptions (shown in --help)

js
import { cli, describe } from "@munesoft/clix";

cli({
  greet: describe("Greet a user by name", (name) => `Hello ${name}`),
  add:   describe("Add two numbers",      (a, b) => Number(a) + Number(b)),
});

Aliases

js
cli(
  { greet: (name) => `Hello ${name}` },
  { aliases: { hi: "greet", hello: "greet" } }
);
bash
node app.js hi Alice      # Hello Alice
node app.js hello Alice   # Hello Alice

Global options

js
cli(commands, {
  name: "my-tool",
  version: "1.0.0",
  description: "My awesome CLI tool",
});
bash
node app.js --version   # 1.0.0
node app.js --help      # shows name, version, description

Custom output formatter

js
cli(commands, {
  formatter: (result) => {
    if (typeof result === "object") {
      return `Result: ${JSON.stringify(result)}`;
    }
    return String(result);
  },
});

Auto Help Generator

Running --help (or -h) automatically generates clean help from your commands:

my-tool v1.0.0
My awesome CLI tool

Usage:
  node app.js <command> [args] [--flags]

Available commands:
  greet  <name>     Greet a user by name
  add    <a> <b>    Add two numbers
  fetch  <url>

Global flags:
  --help     Show this help message
  --version  Show version number

No registration needed — clix reads your function parameter names automatically.


Error Handling

Unknown commands produce clean, actionable errors:

❌ Unknown command: xyz

Try: node app.js --help

Errors thrown by your commands are caught and displayed without crashing:

❌ Failed to connect: ECONNREFUSED

Add --verbose (or -v) to get the full stack trace.


TypeScript

clix is written in TypeScript and ships full type definitions:

ts
import { cli, CliOptions, CommandMap } from "@munesoft/clix";

const commands: CommandMap = {
  greet: (name: string) => `Hello ${name}`,
};

const options: CliOptions = {
  name: "greeter",
  version: "1.0.0",
};

cli(commands, options);

API Reference

cli(commands, options?)

Bootstraps the CLI. Reads process.argv, matches the command, and executes it.

| Parameter | Type | Description | |-----------|------|-------------| | commands | Record<string, Function> | Map of command names to handler functions | | options.name | string | CLI display name | | options.version | string | Version string (enables --version) | | options.description | string | Short description for help output | | options.aliases | Record<string, string> | Alias map { alias: "target" } | | options.formatter | (result) => string | Custom output formatter | | options.exit | (code) => void | Custom exit handler |

describe(description, fn)

Attaches a description to a command function for display in --help.

cliSync(commands, options?)

Synchronous wrapper around cli() for environments that cannot use top-level await.

parseArgs(argv)

Low-level argument parser. Returns { command, args, flags, raw }.


Use Cases

Scripts — Turn one-off scripts into proper tools:

js
cli({ backup: () => runBackup(), restore: (file) => runRestore(file) });

Automation — Build internal automation tools in minutes:

js
cli({
  deploy: async (env) => deploy(env),
  rollback: async (version) => rollback(version),
  status: async () => getStatus(),
});

Dev tools — Package developer utilities:

js
cli({
  "db seed":     () => seed(),
  "db migrate":  () => migrate(),
  "db reset":    () => reset(),
  lint:          () => runLint(),
  test:          (pattern) => runTests(pattern),
});

License

MIT © Munesoft