Skip to content

je-es/cli

Repository files navigation


logo


  • Quick Start 🔥

    The simplest, fastest, most organized and stable way to build command line applications.

    • Setup

      install space first.

      • Create
        > space init <name> -t cli    # This will clone this repo and make some changes to suit your app.
        > cd <name>                   # Go to the project directory
        > space install               # Install the dependencies
      • Manage
        > space lint          # To lint  your app
        > space build         # To build your app
        > space test          # To test  your app
        > space start <args>  # To start your app
        # example
            > space start create MyApp -t web
        
        # output
            Creating MyApp as web
      line
  • Examples

    • Basic CLI

      cli('git', '1.0.0')
      .command({
          name        : 'commit',
          args        : [{ name: 'message', required: true }],
          options     : [{ name: 'amend', flag: '-a', type: 'boolean' }],
          action      : ({ args, options }) => {
          console.log(`Committing: ${args.message}`);
          }
      })
      .build()
      .run();
      git commit "fix bug" -a
      line
    • Multiple Arguments

      .command({
          name      : 'person',
          args      : [
              { name: 'name', required: true },
              { name: 'age', required: true, validate: (v) => !isNaN(Number(v)) }
          ],
          action    : ({ args }) => { console.log(`${args.name}, ${args.age} years old`); }
      })
      myapp person "John Doe" 30 
      line
    • With Validation

      .command({
          name      : 'start',
          options   : [{
              name        : 'port',
              flag        : '-p',
              type        : 'number',
              validate    : (v) => v >= 1000 && v <= 9999 || 'Port must be 1000-9999'
          }],
          action    : ({ options }) => { console.log(`Starting on port ${options.port}`); }
      })
      myapp start -p 3000    #
      myapp start -p 999     # ✗ validation error

  • Docs

    • Commands

      .command({
          name                  : 'create',
          aliases               : ['c', 'new'],            // short names
          description           : 'Create project',        // shown in help
          args                  : [...],                   // positional arguments
          options               : [...],                   // flags and options
          allowDynamicArgs      : true,                    // allow unknown arguments
          allowDynamicOptions   : true,                    // allow unknown options
          action                : (parsed) => { ... },     // command handler
          examples              : ['myapp create foo']     // usage examples
      })
      line
    • Arguments

      args: [
          {
              name            : 'project',
              required        : true,                // mandatory argument
              description     : 'Project name',
              default         : 'myapp',             // fallback value
              validate        : (v) => v.length > 0 || 'Name required'
          }
      ]
      line
    • Options

      options: [
          {
              name            : 'type',
              flag            : '-t',                // short form
              aliases         : ['--type'],          // long form
              type            : 'string',            // string | number | boolean
              required        : true,
              default         : 'npm',
              validate: (v) => ['npm','yarn'].includes(v) || 'Invalid type'
          }
      ]
      line
    • Dynamic Arguments & Options

      Enable allowDynamicArgs and allowDynamicOptions to handle unknown arguments and options.

      Perfect for commands like exec that need to pass through arbitrary arguments.

      cli('docker', '1.0.0')
      .command({
          name                : 'run',
          args                : [{ name: 'image', required: true }],
          options             : [
              { name: 'detach', flag: '-d', type: 'boolean' },
              { name: 'name', flag: '--name', type: 'string' }
          ],
          allowDynamicArgs    : true,   // capture unknown positional args
          allowDynamicOptions : true,   // capture unknown flags
          action              : ({ args, options, dynamicArgs, dynamicOptions }) => {
              console.log('Image:', args.image);
              console.log('Known options:', options);
              console.log('Extra args:', dynamicArgs);     // ['npm', 'start']
              console.log('Extra options:', dynamicOptions); # { p: '3000:3000', e: 'NODE_ENV=prod' }
          }
      })
      .build()
      .run();
      # All unknown args/options are captured
      docker run -d --name myapp node:18 -p 3000:3000 -e NODE_ENV=prod npm start
      
      # Result:
      # args.image          = 'node:18'
      # options.detach      = true
      # options.name        = 'myapp'
      # dynamicArgs         = ['npm', 'start']
      # dynamicOptions      = { p: '3000:3000', e: 'NODE_ENV=prod' }

      Use Cases

      • Command execution: npm exec, docker run, kubectl exec

      • Proxy commands: Pass arguments to underlying tools

      • Flexible APIs: Accept user-defined flags without pre-definition

      // Example: npm-like exec command
      .command({
          name                : 'exec',
          args                : [{ name: 'package', required: true }],
          allowDynamicArgs    : true,
          allowDynamicOptions : true,
          action              : ({ args, dynamicArgs, dynamicOptions }) => {
              // Run package with all extra args/options
              runPackage(args.package, dynamicArgs, dynamicOptions);
          }
      })
      myapp exec vite --port 3000 --host build --minify
      // args.package    = 'vite'
      // dynamicArgs     = ['build', '--minify']
      // dynamicOptions  = { port: '3000', host: true }
      line
    • Built-in Flags

      myapp --help         # show all commands
      myapp create --help  # show command help
      myapp --version      # show version
    • Validation

      // Argument validation
      args: [{
          name      : 'port',
          validate  : (v) => Number(v) > 0 || 'Port must be positive'
      }]
      
      // Option validation
      options: [{
          name      : 'env',
          flag      : '--env',
          validate  : (v) => ['dev','prod'].includes(v) || 'Invalid env'
      }]
      line
    • Type Conversion

      options: [
          { name: 'port', flag: '-p', type: 'number' },   // "3000" → 3000
          { name: 'verbose', flag: '-v', type: 'boolean' }, # flag  true
          { name: 'name', flag: '-n', type: 'string' }     // default
      ]
      line
    • Multiple Commands

      cli('myapp', '1.0.0')
      .command({
          name    : 'create',
          action  : () => { /* ... */ }
      })
      .command({
          name    : 'delete',
          action  : () => { /* ... */ }
      })
      .build()
      .run();
      myapp create
      myapp delete
      line
    • Aliases

      // Command aliases
      .command({
          name      : 'create',
          aliases   : ['c', 'new', 'init']
      })
      
      // Option aliases
      options: [{
          name      : 'force',
          flag      : '-f',
          aliases   : ['--force', '--overwrite']
      }]
      myapp create         # full name
      myapp c              # alias
      myapp new            # alias
      
      myapp create -f      # short flag
      myapp create --force # long flag
      line
    • Error Handling

      import { CLIError, ValidationError, CommandNotFoundError } from '@je-es/cli';
      
      .command({
      name: 'deploy',
          action: async () => {
              throw new CLIError('Deployment failed', 'DEPLOY_ERROR');
          }
      })


About

Build faster | Sleep better

Topics

Resources

License

Stars

Watchers

Forks