clilyruntime-aware CLI docs
Getting started

First command

Define a typed command tree with global flags, child args, and completion output.

This example mirrors the structure used across the repository examples.

import { clily } from '@clily/core'
import * as v from 'valibot'

const globalFlags = v.object({
  verbose: v.optional(v.boolean(), false),
  profile: v.optional(v.picklist(['dev', 'staging', 'prod']), 'dev'),
})

const deployArgs = v.object({
  apiKey: v.string(),
  dryRun: v.optional(v.boolean(), false),
})

const run = clily({
  name: 'release',
  version: '0.1.0',
  description: 'Release automation',
  completion: true,
  flags: globalFlags,
  children: {
    deploy: {
      description: 'Deploy the current build artifact.',
      args: deployArgs,
      handler: async (args) => {
        console.log(args.profile, args.apiKey, args.verbose, args.dryRun)
      },
    },
  },
})

await run()

What happens here

  1. flags define global options inherited by child handlers.
  2. children.deploy.args define subcommand-specific input.
  3. The deploy handler receives a merged object containing both flag output and child arg output.
  4. completion: true exposes the default completion command.

Run it

node --experimental-strip-types src/index.ts deploy --api-key=sk_live_demo

Add shell completion

node --experimental-strip-types src/index.ts completion zsh

If you need deeper control over the completion command name or supported shells, see shell completions.

On this page