When we say “CLI” we’re talking about a program that we can run at the command line by simply typing the command name and its parameters.
When modern languages like Ruby, Python or Go are not available or not allowed due to compliance rules, Bash scripting is the way to go if you want to build a custom CLI and be sure that it runs on a variety of systems.
bash) is one of many available (yet the most commonly used) Unix shells. Bash stands for "Bourne Again SHell", and is a replacement/improvement of the original Bourne shell (
Here we are building a modular CLI with a configuration file and (sub-) commands including help and usage instructions using Bash compliant scripts.
A name to command them all via parameters
First we choose a name and think about the commands and its parameters. The CLI in this example should deploy a series of applications to a Kubernetes Cluster via Helm in the end. Your use case could be something different ;)
We call the CLI
bagcli which stands for Brot and Games CLI and have a final view of the command line in our minds — this should be the output of calling
bagcli without a command or when a command is misspelled.
Brot and Games CLI
Usage: bagcli [command]
bagcli deploy should have its own usage instructions which should also be shown if the parameter
<project_name> is missing.
$ ./bagcli deployCommand: deployUsage:
Modular directory structure
Next we decide upon the directory structure for our CLI. Since we are building a modular CLI with one file for each (sub-) command, we need a clean directory structure.
│ └── deploy
The resulting Bash scripts and files in detail
bagcliis the entrypoint script which loads the config and decides upon the command/parameters which file to execute from the
bagcli deploy <project_name>processes the command and the parameter and calls
commands/deployhas its own help and usage instructions. It takes the parameter
commonholds all the functions which all the scripts need (eg. for logging).
config.templateis like the name says a template for easy configuration of the CLI by the end-user. Users are instructed to
cp config.template configand update the file according to their needs. The file
configshould be ignored by version systems like Git due to possible sensitive data.
Following is a basic implementation of the core files:
The final result is an extensible CLI
bagcli with currently one command
bagcli deploy implemented.
It can be easily extended by
cp commands/deploy commands/my_command and editing the
commands/my_command file to fit your needs. Don’t forget to hook it up in the case statement in the
bagcli file (entrypoint for all commands).
There is also a GitHub repository where you can find an up-to-date version with better error handling and other improvements.
You can use it as a blueprint or skeleton for your projects.
Thanks for reading.