
Cac
Install when you or your agent are implementing or reviewing TypeScript/JavaScript CLIs with the cac parser—commands, variadic args, help/version, and edge cases like boolean negation and -- passthrou
Install
npx skills add https://github.com/cacjs/cac --skill cacWhat is this skill?
- Five-step build flow: command shape, positional args, scoped options, help/version, parse strategy
- Documents required vs optional vs variadic positional patterns (<arg>, [arg], ...)
- Covers CAC-specific behavior: default commands, boolean negation, dot-nested options, -- passthrough
- Shows global vs per-command option attachment for expressive verb-based CLIs
- pnpm add cac install path with minimal working TypeScript example
Adoption & trust: 1 installs on skills.sh; 3.1k GitHub stars; trending (+100% hot-view momentum).
Recommended Skills
Lark Drivelarksuite/cli
Lark Sharedlarksuite/cli
Lark Minuteslarksuite/cli
Tzstxixu-me/skills
Runcomfy Cliagentspace-so/runcomfy-agent-skills
Caveman Helpjuliusbrussee/caveman
Journey fit
Primary fit
CLI authoring is core Build work for indie devs shipping developer tools, internal scripts, and npm-distributed binaries alongside their product. Backend subphase fits command grammars, parse flows, and shared options—the structural layer beneath UX polish in frontend.
SKILL.md
READMESKILL.md - Cac
# CAC Use CAC to build small, expressive CLIs with a compact command grammar: ```ts import { cac } from 'cac' const cli = cac('my-cli') cli .command('build <entry> [...files]', 'Build project files') .option('--minify', 'Minify output') .action((entry, files, options) => { console.info({ entry, files, options }) }) cli.help() cli.version('1.0.0') cli.parse() ``` Install with `pnpm add cac`. ## Build CLIs This Way 1. Choose the command shape first. - Use global parsing only for tiny CLIs. - Use `cli.command(...)` for verb-based CLIs. - Use a default command when the main behavior should run without an explicit verb. 2. Model positional arguments before options. - `<arg>` is required. - `[arg]` is optional. - `...` is variadic and may only appear on the final positional argument. 3. Attach options at the narrowest useful scope. - Use `cli.option(...)` for flags shared by multiple commands. - Use `command.option(...)` for command-specific flags. 4. Add `help()` and `version()` for user-facing tools. 5. Use plain `cli.parse()` for simple flows; use `cli.parse(argv, { run: false })` plus `await cli.runMatchedCommand()` when you need centralized or async error handling. ## Syntax and Parsing | Need | CAC form | Result | | --- | --- | --- | | Required arg | `build <entry>` | action receives `entry` | | Optional arg | `build [entry]` | action receives `undefined` when omitted | | Variadic arg | `build <entry> [...rest]` | final action arg is an array | | Boolean flag | `--open` | accepts both `--open` and `--no-open` automatically | | Optional option value | `--scale [level]` | value or `true` | | Required option value | `--out <dir>` | missing value throws | | Global option | `cli.option('--cwd <dir>', ...)` | available to all commands | | Command option | `command.option('--watch', ...)` | scoped to one command | | Repeated option | `--include a --include b` | becomes `['a', 'b']` | | Dot-nested option | `--env.API_SECRET xxx` | becomes `options.env.API_SECRET` | | Passthrough args | `-- pnpm test` | stored in `options['--']` | Kebab-case option names are read in camelCase: ```ts cli.option('--clear-screen', 'Clear screen') // read options.clearScreen ``` Only the first segment is camel-cased, so `--env.API_SECRET` becomes `options.env.API_SECRET`. Bare booleans already accept negation: ```ts cli.option('--open', 'Open browser') // --open -> { open: true } // --no-open -> { open: false } ``` Declare an explicit negated option only when the negated form should appear in help, should default to `true`, or must pair with a required-value option: ```ts cli .option('--no-config', 'Disable config file') .option('--config <path>', 'Use a custom config file') ``` For array-valued options, prefer repeated flags: ```bash --include a --include b --include c ``` CAC parses that as: ```ts { include: ['a', 'b', 'c'] } ``` Do not model array input as `--include a,b,c` and split the string manually unless the CLI intentionally documents comma-separated syntax. If consumers should always receive an array, use `type: []` so even one `--include a` becomes `['a']`. ## Scenario References Use the reference that matches the user's task: | Scenario | Reference | | --- | --- | | Parse args plus global options | [basic-usage](references/basic-usage.md) | | Parse explicit argv outside normal Node flow | [browser](references/browser.md) | | Add examples to command help | [command-examples](references/command-examples.md) | | Add command-scoped options | [command-options](references/command-options.md) | |