Creating CLIs with Ink, React and a bit of magic

April 29, 2019

Little more than a month ago I released Ink - a library for building command-line interfaces using React components. It was very well received by the community, way beyond my expectations. Incredible projects like npm, Jest, Gatsby, Parcel and Tap have either started using Ink or at least have it on their radar. Like I said last time, I'm grateful and happy either way!

But in my opinion, there was one piece missing. That missing piece would reduce, if not eliminate, a barrier to start using Ink. That missing piece would help developers using Ink not just with building a user interface for your CLI, but a CLI itself. I want to introduce that missing piece today and it's called Pastel.

Pastel is a framework for effortlessly building CLIs with Ink and React. It's inspired by a very old project of mine called Ronin and ZEIT's Next. Similar to Next, Pastel's API is a filesystem. Just create any file inside commands folder and it will become a separate command in your CLI. Need nested commands? No problem, just create a sub-folder and put the commands there.

Here's how your Pastel project will look:

my-beautiful-cli/
    - package.json
    - commands/
        - index.js
        - login.js
        - deploy.js

In this case, Pastel will scan commands folder and generate 3 different commands:

  • my-beautiful-cli (executed by commands/index.js)
  • my-beautiful-cli login (executed by commands/login.js)
  • my-beautiful-cli deploy (executed by commands/deploy.js)

Now let's dive into the magical (and my favorite) part - writing commands. Here's an example command that greets you with a name passed via --name option.

import React from 'react';
import PropTypes from 'prop-types';
import {Text} from 'ink';

/// This command says hello
const Hello = ({name}) => <Text>Hello, {name}!</Text>;

Hello.propTypes = {
    /// Name of the person to say hi to
    name: PropTypes.string.isRequired
};

export default Hello;

Pastel will automatically do all of this for you:

  • Generate options that this command accepts based on propTypes
  • Add descriptions to the command itself and its options by parsing the nearby comments, which start with 3 slashes (///)
  • Build a help message (--help)
  • Ensure that user provides all options, which have isRequired flag
  • Bundle each command separately to speed up your CLI start time by loading only necessary dependencies (code splitting in the terminal, wow)

Now let's check out the help message of this command and then run it:

$ hello --help
hello

This command says hello

Options:

    --help     Show help
    --version  Show version
    --name     Name of the person to say hi to

$ hello --name=Jane
Hello, Jane!

When you don't need to care about setting up options, help messages, validation and multiple commands, you can get back to doing what you truly enjoy - coding and creating your CLI. Pastel is a zero-config and zero-API tool, that gives you all of this for free. So why not try it out today?

Check out Pastel at https://github.com/vadimdemedes/pastel and let me know what you think! You can find me on Twitter.


I want to give a shout-out to wonderful projects like Parcel, yargs, Babel and a bunch of Sindre's modules 😀. Without them, Pastel simply wouldn't happen. Thank you ❤️