npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ideascol/cli-maker

v1.11.0

Published

A simple library to help create CLIs

Downloads

273

Readme

@ideascol/cli-maker

A library to help create CLIs with support for command parameters and interactive prompts.

Quick start

npx @ideascol/cli-maker

Installation

To install the library, use npm:

npm install -g @ideascol/cli-maker

Create your own CLI

cli-maker

Usage

To use the library, import the CliMaker class and create a new instance of it. Then, you can add commands and prompts to the CLI.


const { CLI, ParamType } = require('@ideascol/cli-maker');

const cli = new CLI("mycli", "A simple CLI", {
  interactive: true,
  version: '0.0.1',
  branding: true, // Show GitHub star message (default: true)
  introAnimation: {
    enabled: true,           // Show intro once per machine (unless overridden)
    preset: 'retro-space',   // Presets: retro-space, hacker, vaporwave, radar, pixel, steampunk, sonar
    title: 'mycli',          // Defaults to the CLI name
    subtitle: 'A simple CLI',// Defaults to the CLI description
    // Override any preset field if you want:
    // frames: ['✦', '✹', '✸', '✺'],
    // speedMs: 90,
    // loops: 2,
    // lines: ['Built with cli-maker'],
    // introMode: 'always',
    // asciiArt: ['custom ascii...'],
  },
});

let commandExample = {
  name: 'all-params',
  description: 'Show all params',
  params: [
    {
      name: 'favorite_fruit',
      description: 'select your favorite fruit',
      required: true,
      type: ParamType.List,
      options: ['manzana', 'pera', 'uva']
    },
    {
      name: 'url',
      description: 'The URL of your website',
      type: ParamType.Url,
      required: true
    },
    {
      name: "is_ok",
      description: "Is the user ok? (true or false)",
      type: ParamType.Boolean,
    },
    {
      name: 'email',
      description: 'The email',
      type: ParamType.Email,
      required: true
    },
    {
      name: 'age',
      description: 'The age of the user',
      type: ParamType.Number,
    },
    {
      name: 'metadata',
      description: 'List of tags',
      type: ParamType.List,
      options: ["tag1", "tag2"],
    },
    {
      name: 'tags',
      description: '(["tag1", "tag2"] or {"key1": "value1", "key2": "value2"})',
      type: ParamType.Custom,
      required: false,
    }
  ],
  action: (args) => {
    console.log('EXAMPLE DATA');
    console.log(args);
  }
}

cli.command(commandExample);

cli.parse(process.argv);

Intro animation (first run)

Set introAnimation.enabled to true to display a small animated header the first time someone runs your CLI. A marker file is stored in ~/.cli-maker/<your-cli>-intro.json so the intro is only shown once by default. You can customize the frames, title, subtitle, and extra lines or disable the persistence with showOnce: false.

To force the intro on any run (ignoring the stored marker), run your CLI with --intro-always. To skip it once, use --no-intro.

You can also configure this behavior via introAnimation.introMode:

  • introMode: 'always' to always show.
  • introMode: 'never' to never show.
  • Omit it (default) to show once with the stored marker.
  • Text animates progressively by default; set animateText: false to disable.

Available presets for introAnimation.preset:

  • retro-space (naves y escáner)
  • hacker (cursor parpadeante)
  • vaporwave (frames ✦ ✺ ✹ ✸)
  • radar (barras en arco)
  • pixel (bloques ░▒▓█)
  • steampunk (engranes ⚙)
  • sonar (ondas ◉◎)
  • rainbow (bordes y frames multicolor)

Setup command (step by step interactive)

You can generate a setup command for global variables:

import { CLI, ParamType } from '@ideascol/cli-maker';

const cli = new CLI('mycli', 'Demo CLI');

// Simplified method: setupCommand automatically infers the CLI name
cli.setupCommand({
  name: 'setup', // optional, defaults to 'setup'
  description: 'Configure global preferences', // optional
  steps: [
    { name: 'api_key', description: 'API key', required: true, type: ParamType.Text },
    { name: 'environment', description: 'Select environment', type: ParamType.List, options: ['dev', 'staging', 'prod'], required: true },
    { name: 'telemetry', description: 'Allow metrics', type: ParamType.Boolean, defaultValue: true },
    { name: 'secret', description: 'Secret key', type: ParamType.Password, required: true },
  ],
  encryption: {
    enabled: true,
    prompt: 'Passphrase para cifrar/descifrar',
  },
});

cli.parse(process.argv);

Alternatively, you can still use the standalone createSetupCommand function:

import { CLI, ParamType, createSetupCommand } from '@ideascol/cli-maker';

const cli = new CLI('mycli', 'Demo CLI');
const setup = createSetupCommand('mycli', { /* options */ });
cli.command(setup);

The stored config is saved in ~/.cli-maker/<cli>-config.json (puedes cambiarlo con configFileName). Uses the previous value as default if exists, and validates according to ParamType. Password fields are asked with hidden input and are stored in base64 (with __b64 marker) to avoid leaving them in plain text. If a previous value exists, it is masked.

To read the configuration in code:

import { CLI, ParamType } from '@ideascol/cli-maker';

const cli = new CLI('mycli', 'Demo CLI');

// First, define your setup command
cli.setupCommand({
  steps: [
    { name: 'api_key', description: 'API key', type: ParamType.Password, required: true },
    { name: 'environment', description: 'Environment', type: ParamType.List, options: ['dev', 'prod'] },
  ],
  encryption: { enabled: true },
});

// Then use the CLI methods to access config
cli.command({
  name: 'deploy',
  description: 'Deploy to server',
  params: [],
  action: async () => {
    // Method 1: Load all config (automatically prompts for passphrase if Password fields exist)
    const config = await cli.loadConfig();
    console.log(config.api_key, config.environment);

    // Method 2: Get a specific value (automatically prompts for passphrase if it's a Password field)
    const apiKey = await cli.getConfigValue('api_key'); // Will prompt for passphrase
    const env = await cli.getConfigValue('environment'); // No passphrase needed (not a Password field)
    
    // Optional: Provide passphrase programmatically to avoid prompt
    const apiKeyWithPass = await cli.getConfigValue('api_key', 'my-passphrase');
  }
});

Standalone functions (still available for advanced use cases):

import { loadSetupConfig, getRawConfig, getConfigValue } from '@ideascol/cli-maker';

// Load with decryption (requires steps and passphrase)
const config = loadSetupConfig('mycli', steps, { passphrase: 'my-pass' });

// Get raw config (no decryption)
const rawConfig = getRawConfig('mycli');

// Get specific value (no decryption)
const environment = getConfigValue('mycli', 'environment');

Utility Functions

prompt and hiddenPrompt

You can use prompt and hiddenPrompt utility functions in your command actions:

import { prompt, hiddenPrompt } from '@ideascol/cli-maker';

cli.command({
  name: 'login',
  description: 'Login to the service',
  params: [],
  action: async () => {
    const username = await prompt('Enter your username: ');
    const password = await hiddenPrompt('Enter your password (hidden): ');
    
    console.log(`Logging in as ${username}...`);
    // Your login logic here
  }
});
  • prompt(question: string): Prompts the user for visible input
  • hiddenPrompt(question: string): Prompts the user for hidden input (password-like, input is not displayed)

CLI Static Methods

The CLI class also provides static methods for prompting users, which can be used anywhere without creating a CLI instance:

import { CLI } from '@ideascol/cli-maker';

// Prompt for visible input
const name = await CLI.askQuestion('What is your name? ');
console.log(`Hello, ${name}!`);

// Prompt for hidden input (password-like)
const secret = await CLI.askHiddenQuestion('Enter your secret key: ');
console.log(`Secret received (length: ${secret.length})`);
  • CLI.askQuestion(question: string): Static method to prompt for visible input
  • CLI.askHiddenQuestion(question: string): Static method to prompt for hidden input (shows asterisks)

Password Type in Interactive Mode

When using ParamType.Password in interactive mode, the input is automatically hidden from the screen, providing a secure way to collect sensitive information:

cli.command({
  name: 'secure-command',
  description: 'Command with password parameter',
  params: [
    {
      name: 'secret',
      description: 'Your secret key',
      required: true,
      type: ParamType.Password
    }
  ],
  action: (args) => {
    console.log('Secret received (length):', args.secret.length);
  }
});