A lightweight TypeScript framework for building CLI tools.
npm install @avandar/acclimateA lightweight TypeScript framework for building type-safe command line
interfaces.
This library is not complete and is still missing a lot of functionality.
We do not recommend this library be used in production.
See the To Do section at the end for what is still missing.
``bash`
npm install acclimate
`ts
import { Acclimate } from "acclimate";
const cli = Acclimate.createCLI("demo-cli")
.description("A tiny demo CLI")
.action(() => {
console.log("Hello, world!");
});
Acclimate.run(cli);
`
Public exports from acclimate:
- Acclimate
#### Acclimate.createCLI(name)
Create a new CLI instance.
`ts`
Acclimate.createCLI(name: string): IAcclimateCLI
#### Acclimate.run(cli)
Run a CLI instance using process.argv.slice(2).
`ts`
Acclimate.run(cli: IAcclimateCLI): void
createCLI() returns an immutable builder. Each method returns a new CLI
instance with updated configuration.
#### cli.description(description)
`ts`
cli.description(description: string): IAcclimateCLI
#### cli.action(action)
Set the function executed when the CLI matches (after parsing).
`ts`
cli.action(
action: (args: FullCLIArgValues<...>) => void,
): IAcclimateCLI
#### cli.addPositionalArg(param)
Add a positional argument. Positional args are parsed in order.
`ts`
cli.addPositionalArg(param: CLIPositionalParam): IAcclimateCLI
#### cli.addOption(param)
Add an option local to this CLI level.
`ts`
cli.addOption(param: CLIOptionParam): IAcclimateCLI
#### cli.addGlobalOption(param)
Add an option that is available to this CLI and all sub-commands.
`ts`
cli.addGlobalOption(param: CLIOptionParam): IAcclimateCLI
#### cli.addCommand(commandName, commandCLI)
Add a sub-command (a nested CLI). If the first positional token matches a
command name, parsing continues using that command's CLI.
`ts`
cli.addCommand(
commandName: string,
commandCLI: IAcclimateCLI,
): IAcclimateCLI
#### cli.getCommandCLI(commandName)
Get a command CLI by name (throws if missing).
`ts`
cli.getCommandCLI(commandName: string): IAcclimateCLI
Acclimate uses config objects to describe positional args and options.
- Positional args: CLIPositionalParamstring
- name: (prefer camelCase to match runtime parsing)"string" | "number" | "boolean"
- type: boolean
- required: string
- description?: type
- defaultValue?: depends on (value: string) => value
- choices?: allowed values list
- parser?: (value) => true | string
- validator?:
- Options: CLIOptionParam--${string}
- name: (example: --dry-run)readonly ("--x" | "-x")[]
- aliases?: boolean
- required: type
- Same , defaultValue, choices, parser, validator fields as a
positional arg
- Positional args: validated and parsed in order; extra positional args
throw an error.
- Options: parsing starts at the first token that begins with -. Eachaction(args)
option consumes tokens until the next option; its raw value is the consumed
tokens joined with spaces.
- Option keys in : option names are camel-cased, so--dry-run
becomes dryRun.--flag
- Boolean flags: with no value parses as true (only thefalse
literal string parses as false).CLIError
- Errors: missing required args/options (and invalid values) throw
.
- Node.js 18+
- npm (bundled with Node)
- src/ — framework source code.examples/
- — small usage samples; basic.ts is runnable via npm run demo.tests/
- — Vitest suite.dist/
- — build output generated by tsup.
Install dependencies:
`bash`
npm install
- npm run dev — build in watch mode with tsup.npm run build
- — produce CJS/ESM bundles and type declarations in dist/.npm run demo
- — execute the examples/basic.ts sample with tsx.npm test
- — run the Vitest suite once.npm run test:watch
- — run tests in watch mode.npm run lint
- / npm run lint:fix — check or auto-fix with ESLint.npm run format
- / npm run format:fix — check or write Prettiernpm run type
formatting.
- - check typescript types
1. Start a build (optional during development):
`bash`
npm run dev
1. Run the sample CLI:
`bash`
npm run demo
1. Execute tests:
`bash`
npm test
The prepare script runs npm run build, so the package will compile
automatically when installed from a git dependency.
Matches examples/basic.ts.
`ts
import { Acclimate } from "acclimate";
const cli = Acclimate.createCLI("demo-cli").action(() => {
console.log("Hello, world!");
});
Acclimate.run(cli);
`
`ts
import { Acclimate } from "acclimate";
const cli = Acclimate.createCLI("greet")
.addPositionalArg({
name: "name",
type: "string",
required: true,
description: "Who to greet",
})
.addOption({
name: "--shout",
type: "boolean",
required: false,
aliases: ["-s"] as const,
description: "Uppercase the output",
defaultValue: false,
})
.action(({ name, shout }) => {
const message = Hello, ${name}!;
console.log(shout ? message.toUpperCase() : message);
});
Acclimate.run(cli);
`
`ts
import { Acclimate } from "acclimate";
const initCmd = Acclimate.createCLI("init")
.description("Initialize a project")
.action(({ verbose }) => {
console.log(init (verbose=${verbose}));
});
const root = Acclimate.createCLI("acme")
.addGlobalOption({
name: "--verbose",
type: "boolean",
required: false,
aliases: ["-v"] as const,
defaultValue: false,
})
.addCommand("init", initCmd);
Acclimate.run(root);
`
- [ ] Add semantic arguments: e.g. email (which has a default validator)
- [ ] Add default help command and --help option. This should show the CLIdescription
description and all param documentation.
- [ ] Make the actually get printed.askIfEmpty
- [ ] Show all CLI param descriptions if command is run with no arguments or if
there is a param-related error.
- [ ] Add helper functions to log to stdout in different colors
- [ ] Add logic for to enter an interactive mode to receive inputsaskIfEmptyAndRequired`.
for different params.
- [ ] Add an option to only