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

@gud/cli

v1.0.0-beta.7

Published

A framework for building flexible and extensible CLIs

Readme

Gud CLI

GitHub NPM
Version License:
Apache-2.0

Build delightful command-line tools that your users will actually enjoy using.

Gud CLI is a modern TypeScript framework that makes creating interactive CLI applications effortless. Instead of forcing users to memorize complex commands, your CLI can guide them through an intuitive, conversational experience.

npm install @gud/cli

Why Gud CLI?

  • 🎯 User-first design – Missing a required option? Gud CLI automatically prompts for it instead of showing cryptic error messages.
  • 📁 Intuitive organization – Commands are just files in folders. Want nested commands? Create nested folders. It's that simple.
  • 🔧 TypeScript-powered – Full type safety with intelligent autocompletion for options and parameters.
  • 🔌 Extensible – Plugin system and lifecycle hooks let you customize everything without touching core logic.

Table of Contents

Quick Start

1. Create your CLI entry point

// src/cli.ts
#!/usr/bin/env node
import { run } from '@gud/cli';

// Uses ./commands by default
run();

2. Add your first command

// src/commands/hello.ts
import { command } from '@gud/cli';

export default command({
  description: 'Say hello to someone',
  options: {
    name: {
      description: 'Who to greet',
      type: 'string',
      default: 'World',
    },
  },
  handler: async ({ options, client }) => {
    // Prompts if you pass the prompt option
    const name = await options.name({
      prompt: "What's your name?",
    });
    
    client.log(`Hello, ${name}! 👋`);
  },
});

3. Run it

$ tsx src/cli.ts hello
? What's your name? › Alice
Hello, Alice! 👋

What makes it different?

Interactive by default

Traditional CLIs fail hard when options are missing:

$ mycli deploy
Error: Missing required option --environment

Gud CLI can guide users through required options:

$ mycli deploy
? Enter environment › 
❯ dev
  staging  
  prod

Add the command menu plugin to prompt for missing subcommands too.

File-based routing

Organize commands like you organize code:

commands/
├── hello.ts           # mycli hello
├── users/
│   ├── list.ts        # mycli users list
│   ├── create.ts      # mycli users create
│   └── [id]/
│       ├── show.ts    # mycli users 123 show
│       └── delete.ts  # mycli users 123 delete
└── deploy/
    └── [env].ts       # mycli deploy prod

TypeScript-first

Get full intellisense and type checking:

export default command({
  options: {
    port: { type: 'number', default: 3000 },
    watch: { type: 'boolean' }
  },
  handler: async ({ options }) => {
    const port = await options.port(); // TypeScript knows this is number
    const watch = await options.watch(); // TypeScript knows this is boolean | undefined
  }
});

Examples

Interactive deployment

// commands/deploy.ts
export default command({
  options: {
    environment: {
      type: 'string',
      choices: ['dev', 'staging', 'prod'],
      required: true
    },
    confirm: { type: 'boolean', default: false }
  },
  handler: async ({ options, client }) => {
    // Prompts "Enter environment" because required: true
    const env = await options.environment();
    
    const confirmed = await options.confirm({
      prompt: `Deploy to ${env}?`,
    });
    
    if (!confirmed) {
      client.log('Deployment cancelled');
      return;
    }
    
    client.log(`🚀 Deploying to ${env}...`);
  }
});

Parameterized commands

// commands/users/[id]/delete.ts
export default command({
  description: 'Delete a user by ID',
  options: {
    force: { type: 'boolean', description: 'Skip confirmation' }
  },
  handler: async ({ params, options, client }) => {
    const userId = params.id; // 123 from the command: users 123 delete
    const force = await options.force();
    
    if (!force) {
      const confirmed = await client.confirm(
        `Really delete user ${userId}?`
      );
      if (!confirmed) return;
    }
    
    // Delete user logic here
    client.log(`✅ User ${userId} deleted`);
  }
});

Advanced Features

Plugins

Extend functionality with plugins:

import { run, help, logger } from '@gud/cli';

run({
  plugins: [
    help(), // Adds --help support
    logger(), // Logs command execution
    yourCustomPlugin()
  ]
});

Lifecycle Hooks

Hook into command execution:

import { run } from '@gud/cli';

run({
  hooks: {
    beforeCommand: ({ command, data }) => {
      console.log(`Executing: ${command.commandName}`);
    },
    afterCommand: ({ command, data }) => {
      console.log(`Finished: ${command.commandName}`);
    }
  }
});

Flexible Option Handling

export default command({
  options: {
    username: {
      type: 'string',
      conflicts: ['email'],
    },
    email: {
      type: 'string', 
      conflicts: ['username'],
    }
  },
  handler: async ({ options, client }) => {
    let account = await options.username();

    if (!account) {
      account = await options.email({
        prompt: 'Enter your email',
        validate: (value) => {
          if (!value?.includes('@')) {
            return 'Must be a valid email';
          }
          return true;
        },
      });
    }

    client.log(`Querying account: ${account}`);
  }
});

Built for Scale

Gud CLI grows with your project:

  • Simple scripts: Just run() and a single command file
  • Complex tools: Nested commands, plugins, custom validation
  • Team CLIs: Shared plugins, consistent patterns, full TypeScript support

Whether you're building a quick utility or the next great developer tool, Gud CLI gives you the structure and flexibility you need.

Migration Guide

From Commander.js

// Before (Commander)
program
  .command('hello')
  .option('-n, --name <name>', 'name to greet')
  .action((options) => {
    console.log(`Hello ${options.name || 'World'}`);
  });

// After (Gud CLI)
export default command({
  options: {
    name: {
      alias: ['n'],
      type: 'string',
      description: 'Name to greet',
      default: 'World',
    },
  },
  handler: async ({ options }) => {
    const name = await options.name();
    console.log(`Hello ${name}`);
  },
});

From yargs

// Before (yargs)
yargs(hideBin(process.argv))
  .command(
    'deploy <env>',
    'Deploy to environment',
    {
      env: { describe: 'Environment name', type: 'string' },
    },
    (argv) => {
      console.log(`Deploying to ${argv.env}`);
    },
  );

// After (Gud CLI) - file: commands/deploy/[env].ts
export default command({
  description: 'Deploy to environment',
  handler: async ({ params }) => {
    console.log(`Deploying to ${params.env}`);
  }
});

Community

Reference