Search
⌘K

Task Runner

Simple task/script runner with auto-discovery of scripts from a directory and with arrows+enter launcher UX.

Example Usage

It's common in a project to have a lot of development tasks that you execute with the CLI in your local machine.
This Task Runner will help you to automate those tasks.

Features:

  • Auto-Discovery of scripts from task/scripts directory to populate the launcher
  • Easy Launcher UX: Select script with Arrow up/down and press Enter to execute
  • Support all script languages: Script are simple scripts files, they can be anything that can be launched in the machine

Imagine that your project has this file tree structure:

. your-project
├── docker
   ├── docker-compose.yml
├── next-js
   ├── ...
├── task
   ├── run.sh
   └── scripts
       ├── 0--MISC--make-scripts-executable.sh
       ├── 2--DEV--LAUNCH-docker-container--DB.sh
       ├── 2--DEV--LAUNCH-docker-container--OTHER-SERVICE.sh
       ├── 2--DEV--STOP--docker-container--ALL.sh
       └── 2--DEV--STOP+DESTROY-VOLUME--docker-container--ALL.sh

When you need to run a task:

  • You first go to the root of the project directory with the CLI
  • Then run task/run.sh in the CLI to launch the script launcher
  • Select the script with arrows and press enter to run
  • Done!

First Time Install

  1. Follow Auto Install or Manual Install instructions to get the files in your project
  2. Make task/run.sh executable
    Run chmod +x task/run.sh
  3. Make task/scripts/* executable
    Run chmod +x task/scripts/*

Run a script

  1. Go to the root of the project directory.
  2. Run the script launcher
    ./task/run.sh
  3. Select the script with arrows and press enter.

Add new script

  1. Create a script file in the task/scripts directory (or duplicate an existing one)

  2. Rename the file as you'd like it to be called in the launcher UI

  3. Code it

  4. Make it executable
    Run chmod +x SCRIPT_FILE_PATH

  5. Now if you run ./task/run.sh you will see the new script in the launcher

Dependencies

No dependencies

Auto Install

npx shadcn@latest add https://shadcn-registry-ts.vercel.app/r/util-dev-task-runner.json

Manual Install

run.sh
#!/bin/bash

readonly THIS_FILE_PATH="${BASH_SOURCE[0]}"
readonly THIS_FILE_DIR="$(dirname "${THIS_FILE_PATH}")"
readonly SCRIPTS_DIR="$THIS_FILE_DIR/scripts"

SCRIPTS_FILES=()
SCRIPT_NAMES=()

getScripts() {
  if [ ! -d "$SCRIPTS_DIR" ]; then
    echo "[ERROR:SCRIPTS_DIR_NOT_FOUND] Directory $SCRIPTS_DIR not found."
    exit 1
  fi

  for file in "$SCRIPTS_DIR"/*; do
    if [ -f "$file" ] && [ -x "$file" ]; then
      SCRIPTS_FILES+=("$file")
      SCRIPT_NAMES+=("$(basename "$file")")
    fi
  done

  if [ ${#SCRIPTS_FILES[@]} -eq 0 ]; then
    echo "[ERROR:EMPTY_SCRIPTS_DIR] No executable script found in $SCRIPTS_DIR"
    exit 1
  fi
}

runScript() {
  # get props
  local SCRIPT_TO_RUN_NAME="$1"

  # get script file path
  local SCRIPT_TO_RUN_FILE=""

  for i in "${!SCRIPT_NAMES[@]}"; do
    if [[ "${SCRIPT_NAMES[$i]}" == "$SCRIPT_TO_RUN_NAME" ]]; then
      SCRIPT_TO_RUN_FILE="${SCRIPTS_FILES[$i]}"
      break
    fi
  done

  # ensure file exists
  if [ ! -f "$SCRIPT_TO_RUN_FILE" ]; then
    echo "[ERROR:SCRIPT_FILE_NOT_FOUND] Script file: $SCRIPT_TO_RUN_FILE not found."
    exit 1
  fi

  # run script
  echo ""
  echo "=========================================="
  echo "Executing Script..."
  echo "Script: ${SCRIPT_TO_RUN_FILE}"
  echo "=========================================="
  echo ""
  "$SCRIPT_TO_RUN_FILE"
}

# Menu interattivo robusto con frecce
showMenu() {

  # local state
  local index=0
  local total=${#SCRIPT_NAMES[@]}
  goPrev() {
    ((index--))
    if [ $index -lt 0 ]; then 
      index=$((total-1)); 
    fi
  }
  goNext() {
    ((index++))
    if [ $index -ge $total ]; then 
      index=0; 
    fi
  }

  # draw console
  drawMenu() {
    clear
    echo "Use arrows ↑↓ and press Enter to run a script:"
    for i in "${!SCRIPT_NAMES[@]}"; do
      if [ $i -eq $index ]; then
        echo "> ${SCRIPT_NAMES[$i]}"
      else
        echo "  ${SCRIPT_NAMES[$i]}"
      fi
    done
  }

  # run
  local KEY_CODE_ESCAPE=$'\x1b'
  local KEY_CODE_UP=$'\x1b[A'
  local KEY_CODE_DOWN=$'\x1b[B'
  local KEY_CODE_ENTER=""

  while true; do
    # re-render
    drawMenu

    # on user key press -> do stuff
    local key1=""

    IFS= read -rsn1 key1  # primo carattere

    if [[ $key1 == $KEY_CODE_ESCAPE ]]; then
      local key2=""
      IFS= read -rsn2 key2  # leggi sequenza escape
      local key="$key1$key2"

      if [[ $key == $KEY_CODE_UP ]]; then  # freccia su
        goPrev
      elif [[ $key == $KEY_CODE_DOWN ]]; then  # freccia giù
        goNext
      fi
    
    elif [[ $key1 == $KEY_CODE_ENTER ]]; then  # invio
      local SCRIPT_NAME="${SCRIPT_NAMES[$index]}"
      runScript "$SCRIPT_NAME"
      break
    fi
  done
}

# ================================
# MAIN
# ================================

getScripts
showMenu
readme.md
# Task Runner

A simple task runner.  

Features: 
- **Auto-Discovery of scripts** from `task/scripts` directory to populate the launcher
- **Easy Launcher UX**: Select script with Arrow up/down and press Enter to execute
- **All script languages support**: Script are simple scripts files, they can be anything that can be launched in the machine

## Run a script

1. Run the script launcher  
    ```bash 
    ./task/run.sh
    ```
2. Select the script with arrows and press enter

## Add new script

1. Duplicate an existing script and rename it, then write the script.  
2. Assumes that the current working directory is the root of the project inside the code
3. Make it executable  
    ```bash
    ./task/run.sh
    # select
    0--MISC--make-scripts-executable.sh
    ```
0--MISC--make-scripts-executable.sh
#!/bin/bash

echo "Running with CWD: $(pwd)"

echo "MAKE SCRIPTS EXECUTABLE"

chmod +x ./task/scripts/*
1-demo-bash.sh
#!/bin/bash

echo "Running with CWD: $(pwd)"
echo ""
echo "ciao"
1-demo-node.js
#!/usr/bin/env node

console.log(`Running with CWD: ${process.cwd()}`);
console.log("");
console.log("ciao");

Test

No test

Command Palette

Search for a command to run...