Task Launcher is a bash based CLI script that can be used to run a series of commonly run commands with a shorter alias.
For example, if you regularly run the following commands to build and run your project:
cd ~/projects/my_project/src
npm build-dev
npm start
You could create a Task Launcher task called build-and-run
that contains these commands, and run them from anywhere in your shell by simply calling tl build-and-run
.
Task Launcher also includes an interactive menu for all the tasks you’ve created, allowing you to execute the tasks available by entering their numeric input.
The menu includes support for sub-menus, allowing you to group related tasks together, and can prompt for user input to provide variable data to your tasks.
To start using Task Launcher, clone this repo:
git clone https://github.com/SiJiL82/bash-task-launcher.git
If you want to create a task launcher with tasks for your existing project (for example to speed up common developer tasks),
clone this repo inside your project.
You can change the launcher command to one relative to your project, which allows you to have a Task Launcher config specifically for your project.
To do so, simply rename the tl
file to whatever you want the command to be to call your launcher.
For example, if you’re working on "My Cool Website", you could rename tl
to mcw
which will allow you to call the launcher tasks with mcw build-and-run
.
To view available tasks the launcher can call, run any of tl -h
, tl h
, tl help
or tl --help
:
To run a task directly, simply call tl
followed by the task name:
To launch the interactive menu, call tl m
or tl menu
:
You can then launch any of the tasks, or enter any of the sub menus by entering the numeric indicator next to the task description:
Task Launcher can be called from any location in your terminal - you don’t need to launch it from the location you’ve cloned it to every time.
To install the launcher, simply run it from the location you’ve cloned it to once, and it will self install via symlink into /usr/local/bin
Note: This may require sudo
access and will attempt to elevate permissions if required.
cd ~/projects/bash-task-launcher
./tl
To stop Task Launcher being available to run anywhere in your shell, simply remove the symlink from /usr/local/bin
Note: This may require sudo
access
sudo rm /usr/local/bin/tl
Task Launcher includes autocomplete files for both bash
and zsh
shells that list all the available tasks.
Note: Despite being a bash based CLI script, it will work when being called from other shells, as long as bash exists on the system
To enable the autocomplete prompts follow the steps relevant to the shell you’re using:
-
Get the full path to the
autocomplete
folder in the cloned repo on your machine
e.g.:/home/USER_NAME/projects/bash-task-launcher/autocomplete
-
Edit your
~/.zshrc
file -
Add the line
fpath=(path_found_above $fpath)
-
e.g.:
fpath=(/home/USER_NAME/projects/bash-task-launcher/autocomplete $fpath)
-
-
Restart your terminal.
Now when you type tl
followed by a space on the terminal, you should get a list of available commands to choose from.
The list will update as you type, filtering down to relevant commands.
-
Get the full path to the
autocomplete/tl.bash
file on your machine.-
e.g.:
/home/USER_NAME/projects/bash-task-launcher/autocomplete/sd.bash
-
-
Edit your
~/.bashrc
file -
Add the line
source path_found_above
-
e.g.:
source /home/USER_NAME/projects/bash-task-launcher/autocomplete/tl.bash
-
-
Restart your terminal
Now when you type tl
followed by a space and press TAB twice, a list of available commands will be shown.
If you start typing a task name and then press TAB and only one available command is available, it will be autocompleted for you.
e.g.: If you have a task named example
, type tl exa
and press TAB and it will autocomplete to tl example
After adding any tasks to the Task Launcher, you’ll need to update the autocomplete files so they include your new tasks.
Simply run tl build-autocomplete
to regenerate them.
Don’t forget to commit these files along with your task definitions if you’ve forked this repository / added it to an existing project that’s in source control
To create your own task for the Task Launcher, first decide on the task name.
This should be short, so it’s quick to type on the CLI, but still accurately describe what the task will do.
Task names must be unique across the entire launcher - tasks on different sub menus cannot share names.
Note: Your task name can only contain the charactes a-z
(lowercase only) and the -
character.
You cannot separate words in your task name with spaces or underscores.
Tasks are listed on the menu in the order they appear in the files in. To re-order the menu(s), simply re-order the task definitions in the task config files.
Edit the file in task_configs
that contains the menu or sub-menu that your task relates to.
You can add all task and sub-menu definitions to a single file (such as task_configs/main
) if you wish, however it is recommended to create a separate file for each sub-menu to keep the configs tidy and easy to maintain.
Copy the template below into the file you’re adding the task to:
example:menu() (echo MAIN_MENU)
example:describe() (echo 'This is the task description')
example() {
# Enter your commands here
}
Replace the example
task name with your new task name, for each of the example:menu
, example:describe
and example
functions.
For example:
build-and-run:menu() (echo MAIN_MENU)
build-and-run:describe() (echo 'Build and start the web application')
build-and-run() {
cd ~/projects/my_project/src
npm build-dev
npm start
}
If your task needs to be in a sub-menu, replace MAIN_MENU
with the name of your sub-menu.
Enter a suitable description for the task, so it’s clear what the task does.
Keep the description short and concise, as very long descriptions will make the interactive menu unwieldy.
Enter the commands you want your task to run in the main task function.
Save the file and test it by running tl task-name
When your new task is complete, update the autocomplete files to include it
To prevent the initial menu screen from becoming overwhelming to the user, you can create sub-menus to group related tasks together intuitively.
Note: A task being in a sub-menu does not affect how it is called on the CLI in any way
It is recommended to create tasks in a sub-menu in a separate file to keep the config files from becoming difficult to maintain.
However, if you want your sub-menu option to appear on the main menu, you should create the sub-menu task in the task_configs/main
file.
Task Launcher supports any level of nested sub-menus - to create a nested sub-menu, simply define the :menu
function with the name of the menu you wish your sub-menu to appear on.
Edit the file in task_configs
that contains the menu you want your sub-menu option to appear on.
For example, to include it on the main menu, edit task_configs/main
.
Note: This is purely for maintainability - you can add the definition to any file you like!
Copy the template below into the file:
example-menu:menu() (echo MAIN_MENU)
example-menu:meta() (echo NO-RUNNER)
example-menu:describe() (echo 'This is the menu description')
example-menu() {
menu "$(tasks:menuitems EXAMPLE_MENU)"
}
Replace the example-menu
task name with your new menu task name (e.g.: npm-tools-menu
) for each of example-menu:menu
, example-menu:meta
, example-menu:describe
and example-menu
Do not edit the :meta
definition. This is required to prevent the sub-menu task being listed as an available task to run.
Enter a suitable description for your sub-menu.
Inside the menu definition function, replace EXAMPLE_MENU
with the name of your new menu (e.g.: NPM_TOOLS_MENU
).
For example:
npm-tools-menu:menu() (echo MAIN_MENU)
npm-tools-menu:meta() (echo NO-RUNNER)
npm-tools-menu:describe() (echo 'NPM Tools')
npm-tools-menu() {
menu "$(tasks:menuitems NPM_TOOLS_MENU)"
}
Update any tasks that you want to appear on the sub-menu, setting their :menu
definition to match the name you have just assigned above.
For example:
build-and-run:menu() (echo NPM_TOOLS_MENU)
build-and-run:describe() (echo 'Build and start the web application')
build-and-run() {
cd ~/projects/my_project/src
npm build-dev
npm start
}
There are a few useful functions available in the shared-functions
file that can be used in your task definitions to improve the user experience.
Prints an information message to the user in blue text.
Usage:
example:menu() (echo EXAMPLE_MENU)
example:describe() (echo 'An example task')
example() {
print_info "To print information to the user, use 'print_info'"
}
Prints a warning message to the user in red text.
Usage:
example:menu() (echo EXAMPLE_MENU)
example:describe() (echo 'An example task')
example() {
print_warning "To print a warning to the user, use 'print_warning'"
}
Prints a message to the user in yellow text, and waits for them to enter input.
An optional default can be provided that the user can accept by pressing enter immediately.
Usage:
example:menu() (echo EXAMPLE_MENU)
example:describe() (echo 'Prompt the user')
example() {
input=$(prompt "Do you like this question?")
echo "You said '$input'"
}
example-default:menu() (echo EXAMPLE_MENU)
example-default:describe() (echo 'Prompt the user with a default response')
example-default() {
input=$(prompt "Do you like this question?" "No")
echo "You said '$input'"
}
Task functions can accept arguments to be used within the script, so when called on the CLI the user can provide the argument.
On the interactive menu however, the user must be prompted to enter the argument value.
If you would like users to have the option to either provide the argument on the CLI, or be prompted to enter it, you can use arg_or_prompt
instead of prompt
.
Usage:
example:menu() (echo EXAMPLE_MENU)
example:describe() (echo 'An example task')
example() {
name=$(arg_or_prompt "$1" "Enter your name")
echo "Hello $name"
}
Prints a list of options for the user to chose from.
Returns the option item selected - not the numerical position of the item.
Usage:
example-options:menu() (echo MAIN_MENU)
example-options:describe() (echo 'An example task with options')
example-options() {
local -r options=("One" "Two" "Three" "Four" "Five" "Six" "Seven" "Eight" "Nine" "Ten")
local -r choice=$(prompt_options options)
print_info "You chose: $choice"
}
Allows the user to provide the option they wish to chose as a CLI argument.
The value they provide will be checked to see if it is in the option values you provide, and prompt them to chose a new value if not.
Usage:
example-options:menu() (echo MAIN_MENU)
example-options:describe() (echo 'An example task with options')
example-options() {
local -r options=("One" "Two" "Three" "Four" "Five" "Six" "Seven" "Eight" "Nine" "Ten")
local -r choice=$(arg_or_prompt_options options "$1")
print_info "You chose: $choice"
}
If you find anything not working correctly, please raise an issue
If you need any help getting Task Launcher up and running, creating a task for it, or have an idea for an improvement (that you can’t make your self) please create a new discussion and I’ll do my best to help, or point you towards something that might solve your issue.
Because I know eventually it’ll get asked - the prompt I’m using in the screenshots is Oh My Posh.
My config is available here - feel free to copy it!