Termost
A framework to build your next CLI application: Get the most of your termin...
README
💻 Termost
Get the most of your terminal
✨ Features
Termost allows building command line tools in a minute thanks to its:
Fluent syntax to express your CLI configurations with instructions such as:
Subcommand support
Long and short option support
User input support
Task support
Shareable output between instructions
Auto-generated help and version metadata
TypeScript support to foster a type-safe API
Built-in helpers to make stdin/stdout management a breeze (including exec, and message helpers...)
🚀 Quickstart
Install the library:
- ``` shell
- # Npm
- npm install termost
- # Pnpm
- pnpm add termost
- # Yarn
- yarn add termost
- ```
Once you're done, you can play with the API:
- ``` ts
- #!/usr/bin/env node
- import { helpers, termost } from "termost";
- type ProgramContext = {
- globalFlag: string;
- };
- type DebugCommandContext = {
- localFlag: string;
- };
- const program = termost<ProgramContext>("CLI example", {
- onException(error) {
- console.error(`Error logic ${error.message}`);
- },
- onShutdown() {
- console.log("Clean-up logic");
- },
- });
- program.option({
- key: "globalFlag",
- name: { long: "global", short: "g" },
- description:
- "A global flag/option example accessible by all commands (key is used to persist the value into the context object)",
- defaultValue:
- "A default value can be set if no flag is provided by the user",
- });
- program
- .command({
- name: "build",
- description:
- "A custom command example runnable via `bin-name build` (command help available via `bin-name build --help`)",
- })
- .task({
- label: "A label can be displayed to follow the task progress",
- async handler() {
- await fakeBuild();
- },
- });
- program
- .command<DebugCommandContext>({
- name: "debug",
- description: "A command to play with Termost capabilities",
- })
- .option({
- key: "localFlag",
- name: "local",
- description: "A local flag accessible only by the `debug` command",
- defaultValue: "local-value",
- })
- .task({
- handler(context, argv) {
- helpers.message(`Hello, I'm the ${argv.command} command`);
- helpers.message(`Context value = ${JSON.stringify(context)}`);
- helpers.message(`Argv value = ${JSON.stringify(argv)}`);
- },
- });
- const fakeBuild = async () => {
- return new Promise((resolve) => {
- setTimeout(resolve, 3000);
- });
- };
- ```
Depending on the command, the output will look like this (bin-nameis the program name automatically retrieved from the package.json>name):
✍️ Usage
Here's an API overview:
command({ name, description })
The API creates a new subcommand context.Please note that the root command context is shared across subcommands but subcommand's contexts are scoped and not accessible between each other.
- ``` ts
- ```
input({ key, label, type, skip, ...typeParameters })
The API creates an interactive prompt.It supports several types:
- ``` ts
- ```
option({ key, name, description, defaultValue, skip })
The API defines a contextual CLI option.The option value can be accessed through its property from the current context.
- ``` ts
- ```
task({ key, label, handler, skip })
The executes a handler (either a synchronous or an asynchronous one).The output can be either:
Displayed gradually if no is provided
Displayed until the promise is fulfilled if a property is specified (in the meantime, a spinner with the label is showcased)
- ``` ts
- ```
🤩 Built with Termost
Quickbundle The zero-configuration bundler powered by ESBuild
💙 Acknowledgements
This project is built upon solid open-source foundations. We'd like to thank:
enquirer for managing inputinternals
listr2 for managing taskinternals
📖 License
MIT