interactive-menu-builder

Interactive Menu Builder

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "interactive-menu-builder" with this command: npx skills add vamseeachanta/workspace-hub/vamseeachanta-workspace-hub-interactive-menu-builder

Interactive Menu Builder

Patterns for building professional multi-level interactive menus in bash scripts. Extracted from workspace-hub's workspace CLI and repository_sync tools.

When to Use This Skill

✅ Use when:

  • Building user-friendly CLI tools

  • Need navigation through multiple options

  • Complex tools with many sub-commands

  • Tools used by humans (not just automation)

  • Consolidating multiple scripts into one interface

❌ Avoid when:

  • Scripts meant for automation/CI

  • Simple single-purpose scripts

  • When a plain command-line interface is sufficient

Core Capabilities

  1. Basic Menu Structure

Single-level menu with numbered options:

#!/bin/bash

ABOUTME: Basic interactive menu pattern

ABOUTME: Simple numbered option selection

Colors

CYAN='\033[0;36m' GREEN='\033[0;32m' RED='\033[0;31m' NC='\033[0m'

show_menu() { clear echo -e "${CYAN}═══════════════════════════════════════${NC}" echo -e "${CYAN} Main Menu${NC}" echo -e "${CYAN}═══════════════════════════════════════${NC}" echo "" echo " 1) Option One" echo " 2) Option Two" echo " 3) Option Three" echo "" echo " 0) Exit" echo "" echo -e "${CYAN}═══════════════════════════════════════${NC}" echo "" }

handle_choice() { local choice="$1"

case "$choice" in
    1)
        echo "Running Option One..."
        # Implementation
        ;;
    2)
        echo "Running Option Two..."
        # Implementation
        ;;
    3)
        echo "Running Option Three..."
        # Implementation
        ;;
    0)
        echo "Goodbye!"
        exit 0
        ;;
    *)
        echo -e "${RED}Invalid option${NC}"
        ;;
esac

}

Main loop

while true; do show_menu read -p "Select option: " choice handle_choice "$choice" echo "" read -p "Press Enter to continue..." done

  1. Multi-Level Menu System

Hierarchical menu with breadcrumb navigation:

#!/bin/bash

ABOUTME: Multi-level menu system with navigation stack

ABOUTME: Pattern from workspace-hub workspace CLI

Navigation stack

declare -a MENU_STACK=("main") CURRENT_MENU="main"

Menu definitions

declare -A MENU_TITLES=( ["main"]="Main Menu" ["repo"]="Repository Management" ["repo_ops"]="Repository Operations" ["compliance"]="Compliance & Standards" ["tools"]="Development Tools" )

Go to submenu

push_menu() { local menu="$1" MENU_STACK+=("$menu") CURRENT_MENU="$menu" }

Go back

pop_menu() { if [[ ${#MENU_STACK[@]} -gt 1 ]]; then unset 'MENU_STACK[-1]' CURRENT_MENU="${MENU_STACK[-1]}" fi }

Display breadcrumb

show_breadcrumb() { local crumb="" for menu in "${MENU_STACK[@]}"; do [[ -n "$crumb" ]] && crumb+=" > " crumb+="${MENU_TITLES[$menu]}" done echo -e "${CYAN}$crumb${NC}" }

Main menu

show_main_menu() { clear echo -e "${CYAN}═══════════════════════════════════════════════════════${NC}" echo -e "${CYAN} Workspace Hub - Management Console${NC}" echo -e "${CYAN}═══════════════════════════════════════════════════════${NC}" echo "" show_breadcrumb echo "" echo " 1) Repository Management" echo " 2) Compliance & Standards" echo " 3) Development Tools" echo " 4) System Configuration" echo " 5) Help & Documentation" echo "" echo " 0) Exit" echo "" }

Repository submenu

show_repo_menu() { clear echo -e "${CYAN}═══════════════════════════════════════════════════════${NC}" show_breadcrumb echo -e "${CYAN}═══════════════════════════════════════════════════════${NC}" echo "" echo " 1) Repository Sync Manager" echo " 2) Configure Repository URLs" echo " 3) Check All Repository Status" echo " 4) Clone Repositories" echo "" echo " 0) Back" echo "" }

Handle navigation

handle_menu() { local choice="$1"

case "$CURRENT_MENU" in
    main)
        case "$choice" in
            1) push_menu "repo" ;;
            2) push_menu "compliance" ;;
            3) push_menu "tools" ;;
            4) run_system_config ;;
            5) run_help ;;
            0) exit 0 ;;
        esac
        ;;
    repo)
        case "$choice" in
            1) run_repo_sync ;;
            2) run_configure_urls ;;
            3) run_check_status ;;
            4) push_menu "repo_ops" ;;
            0) pop_menu ;;
        esac
        ;;
    # Add more menus...
esac

}

Display current menu

show_current_menu() { case "$CURRENT_MENU" in main) show_main_menu ;; repo) show_repo_menu ;; # Add more... esac }

Main loop

while true; do show_current_menu read -p "Select option: " choice handle_menu "$choice" done

  1. Table Display

Display data in formatted tables:

#!/bin/bash

ABOUTME: Table display functions for CLI menus

ABOUTME: Format data in aligned columns with headers

Print table header

print_table_header() { local -a headers=("$@") local format=""

# Build format string
for header in "${headers[@]}"; do
    format+="%-20s "
done

echo ""
printf "${CYAN}${format}${NC}\n" "${headers[@]}"
printf "${CYAN}%s${NC}\n" "$(printf '─%.0s' {1..80})"

}

Print table row

print_table_row() { local format="" local -a values=("$@")

for _ in "${values[@]}"; do
    format+="%-20s "
done

printf "${format}\n" "${values[@]}"

}

Display repository table

show_repo_table() { print_table_header "Repository" "Category" "Status" "Branch"

for repo in "${REPOS[@]}"; do
    local category=$(get_category "$repo")
    local status=$(get_status "$repo")
    local branch=$(get_branch "$repo")

    # Color-code status
    case "$status" in
        "Clean")      status="${GREEN}Clean${NC}" ;;
        "Modified")   status="${YELLOW}Modified${NC}" ;;
        "Untracked")  status="${RED}Untracked${NC}" ;;
    esac

    print_table_row "$repo" "$category" "$status" "$branch"
done

}

  1. Selection Lists

Let users select from a list:

#!/bin/bash

ABOUTME: Selection list patterns

ABOUTME: Single and multi-select from numbered lists

Single selection

select_single() { local prompt="$1" shift local -a options=("$@")

echo ""
for i in "${!options[@]}"; do
    echo "  $((i+1))) ${options[$i]}"
done
echo ""
echo "  0) Cancel"
echo ""

read -p "$prompt: " choice

if [[ "$choice" == "0" ]]; then
    return 1
elif [[ "$choice" -ge 1 && "$choice" -le ${#options[@]} ]]; then
    SELECTED="${options[$((choice-1))]}"
    return 0
else
    echo -e "${RED}Invalid selection${NC}"
    return 1
fi

}

Multi-selection

select_multiple() { local prompt="$1" shift local -a options=("$@") local -a selected=()

echo ""
echo "Enter numbers separated by spaces (or 'all' for all):"
echo ""

for i in "${!options[@]}"; do
    echo "  $((i+1))) ${options[$i]}"
done
echo ""

read -p "$prompt: " input

if [[ "$input" == "all" ]]; then
    SELECTED=("${options[@]}")
    return 0
fi

for num in $input; do
    if [[ "$num" -ge 1 && "$num" -le ${#options[@]} ]]; then
        selected+=("${options[$((num-1))]}")
    fi
done

SELECTED=("${selected[@]}")
[[ ${#SELECTED[@]} -gt 0 ]]

}

Usage

repos=("repo1" "repo2" "repo3" "repo4")

if select_single "Select repository" "${repos[@]}"; then echo "You selected: $SELECTED" fi

if select_multiple "Select repositories" "${repos[@]}"; then echo "You selected: ${SELECTED[*]}" fi

  1. Confirmation Dialogs

Request user confirmation:

#!/bin/bash

ABOUTME: Confirmation dialog patterns

ABOUTME: Yes/No prompts with defaults

Simple yes/no

confirm() { local prompt="${1:-Are you sure?}" local default="${2:-n}" # Default to no

if [[ "$default" == "y" ]]; then
    prompt+=" [Y/n]: "
else
    prompt+=" [y/N]: "
fi

read -p "$prompt" response
response="${response:-$default}"

[[ "${response,,}" == "y" || "${response,,}" == "yes" ]]

}

Confirmation with explanation

confirm_action() { local action="$1" local details="$2"

echo ""
echo -e "${YELLOW}⚠ Confirmation Required${NC}"
echo ""
echo "Action: $action"
[[ -n "$details" ]] && echo "Details: $details"
echo ""

confirm "Proceed?" "n"

}

Dangerous action confirmation

confirm_dangerous() { local action="$1" local confirm_word="${2:-DELETE}"

echo ""
echo -e "${RED}⚠ DANGEROUS OPERATION${NC}"
echo ""
echo "This action cannot be undone!"
echo "Action: $action"
echo ""
echo -e "Type '${YELLOW}${confirm_word}${NC}' to confirm:"

read -p "> " response
[[ "$response" == "$confirm_word" ]]

}

Usage

if confirm "Delete all logs?"; then rm -rf logs/* fi

if confirm_dangerous "Delete all repositories" "DELETE"; then # Perform dangerous action echo "Proceeding..." fi

  1. Progress Indicators

Show progress during operations:

#!/bin/bash

ABOUTME: Progress indicator patterns

ABOUTME: Spinners, bars, and status updates

Spinner

spinner() { local pid=$1 local message="${2:-Processing}" local spin='⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏' local i=0

while kill -0 "$pid" 2>/dev/null; do
    i=$(( (i+1) % ${#spin} ))
    printf "\r${CYAN}%s${NC} %s" "${spin:$i:1}" "$message"
    sleep 0.1
done

printf "\r${GREEN}✓${NC} %s\n" "$message"

}

Usage

long_running_task & spinner $! "Running long task..."

Progress bar

progress_bar() { local current=$1 local total=$2 local width=40 local percent=$((current * 100 / total)) local filled=$((current * width / total)) local empty=$((width - filled))

printf "\r["
printf "%${filled}s" | tr ' ' '█'
printf "%${empty}s" | tr ' ' '░'
printf "] %3d%% (%d/%d)" "$percent" "$current" "$total"

}

Usage

total=100 for i in $(seq 1 $total); do progress_bar $i $total sleep 0.05 done echo ""

Status updates

status_line() { local message="$1" printf "\r\033[K%s" "$message" # Clear line and print }

Completion markers

mark_done() { local message="$1" echo -e "${GREEN}✓${NC} $message" }

mark_fail() { local message="$1" echo -e "${RED}✗${NC} $message" }

mark_skip() { local message="$1" echo -e "${YELLOW}⊘${NC} $message" }

Complete Example: Multi-Level Menu System

Full implementation from workspace CLI:

#!/bin/bash

ABOUTME: Complete multi-level menu system

ABOUTME: Template for workspace-hub style CLI tools

set -e

─────────────────────────────────────────────────────────────────

Configuration

─────────────────────────────────────────────────────────────────

SCRIPT_NAME="$(basename "$0")" VERSION="1.0.0"

Colors

RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' MAGENTA='\033[0;35m' BOLD='\033[1m' NC='\033[0m'

Menu state

CURRENT_MENU="main" declare -a MENU_HISTORY=()

─────────────────────────────────────────────────────────────────

Utility Functions

─────────────────────────────────────────────────────────────────

clear_screen() { printf "\033c" }

print_header() { local title="$1" local width=60

echo ""
echo -e "${CYAN}$(printf '═%.0s' $(seq 1 $width))${NC}"
printf "${CYAN}%*s${NC}\n" $(((${#title}+width)/2)) "$title"
echo -e "${CYAN}$(printf '═%.0s' $(seq 1 $width))${NC}"
echo ""

}

print_breadcrumb() { if [[ ${#MENU_HISTORY[@]} -gt 0 ]]; then local path="" for menu in "${MENU_HISTORY[@]}"; do [[ -n "$path" ]] && path+=" > " path+="$menu" done path+=" > $CURRENT_MENU" echo -e "${BLUE}$path${NC}" echo "" fi }

print_option() { local num="$1" local text="$2" local desc="${3:-}"

printf "  ${BOLD}%2s)${NC} %-25s" "$num" "$text"
[[ -n "$desc" ]] && printf "${CYAN}%s${NC}" "$desc"
echo ""

}

wait_key() { echo "" read -p "Press Enter to continue..." }

navigate_to() { MENU_HISTORY+=("$CURRENT_MENU") CURRENT_MENU="$1" }

navigate_back() { if [[ ${#MENU_HISTORY[@]} -gt 0 ]]; then CURRENT_MENU="${MENU_HISTORY[-1]}" unset 'MENU_HISTORY[-1]' fi }

─────────────────────────────────────────────────────────────────

Menu Displays

─────────────────────────────────────────────────────────────────

show_main_menu() { clear_screen print_header "Workspace Hub Management Console"

echo "  ${BOLD}Workspace Management:${NC}"
echo ""
print_option 1 "Repository Management" "Git operations"
print_option 2 "Compliance & Standards" "Code standards"
print_option 3 "Development Tools" "Dev utilities"
print_option 4 "System Configuration" "Setup"
echo ""
echo "  ${BOLD}Information:${NC}"
echo ""
print_option 5 "Help & Documentation"
print_option 6 "About"
echo ""
print_option 0 "Exit"
echo ""

}

show_repo_menu() { clear_screen print_header "Repository Management" print_breadcrumb

print_option 1 "Sync All Repositories" "Pull/push all"
print_option 2 "Clone Missing Repos" "Download new"
print_option 3 "Check Status" "Git status"
print_option 4 "Branch Operations" "Branch management"
echo ""
print_option 0 "Back"
echo ""

}

show_compliance_menu() { clear_screen print_header "Compliance & Standards" print_breadcrumb

print_option 1 "Propagate Configuration" "Sync settings"
print_option 2 "Verify Compliance" "Check standards"
print_option 3 "Install Hooks" "Git hooks"
echo ""
print_option 0 "Back"
echo ""

}

─────────────────────────────────────────────────────────────────

Action Handlers

─────────────────────────────────────────────────────────────────

run_sync_repos() { echo "" echo -e "${CYAN}Syncing all repositories...${NC}" # Implementation echo -e "${GREEN}✓ Sync complete${NC}" wait_key }

run_check_status() { echo "" echo -e "${CYAN}Checking repository status...${NC}" # Implementation wait_key }

─────────────────────────────────────────────────────────────────

Menu Handlers

─────────────────────────────────────────────────────────────────

handle_main_menu() { local choice="$1" case "$choice" in 1) navigate_to "repo" ;; 2) navigate_to "compliance" ;; 3) navigate_to "tools" ;; 4) run_system_config ;; 5) run_help ;; 6) run_about ;; 0) echo "Goodbye!"; exit 0 ;; *) echo -e "${RED}Invalid option${NC}"; sleep 1 ;; esac }

handle_repo_menu() { local choice="$1" case "$choice" in 1) run_sync_repos ;; 2) run_clone_repos ;; 3) run_check_status ;; 4) navigate_to "branches" ;; 0) navigate_back ;; *) echo -e "${RED}Invalid option${NC}"; sleep 1 ;; esac }

handle_compliance_menu() { local choice="$1" case "$choice" in 1) run_propagate_config ;; 2) run_verify_compliance ;; 3) run_install_hooks ;; 0) navigate_back ;; *) echo -e "${RED}Invalid option${NC}"; sleep 1 ;; esac }

─────────────────────────────────────────────────────────────────

Main Loop

─────────────────────────────────────────────────────────────────

main() { while true; do case "$CURRENT_MENU" in main) show_main_menu read -p "Select option: " choice handle_main_menu "$choice" ;; repo) show_repo_menu read -p "Select option: " choice handle_repo_menu "$choice" ;; compliance) show_compliance_menu read -p "Select option: " choice handle_compliance_menu "$choice" ;; *) echo "Unknown menu: $CURRENT_MENU" CURRENT_MENU="main" ;; esac done }

main "$@"

Best Practices

  1. Consistent Navigation
  • 0 always goes back/exits

  • Numbers 1-9 for options

  • Use q as alternative to 0 for exit

  1. Clear Visual Hierarchy
  • Headers separate sections

  • Indentation shows grouping

  • Colors indicate meaning

  1. Feedback on Actions
  • Show progress during operations

  • Confirm completion

  • Display errors clearly

  1. Graceful Error Handling
  • Invalid input shouldn't crash

  • Show helpful error messages

  • Allow retry

Resources

  • Dialog Tool - TUI dialogs

  • Whiptail - Alternative TUI

  • Gum - Modern CLI toolkit

Version History

  • 1.0.0 (2026-01-14): Initial release - extracted from workspace-hub CLI tools

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

echarts

No summary provided by upstream source.

Repository SourceNeeds Review
General

pandoc

No summary provided by upstream source.

Repository SourceNeeds Review
General

mkdocs

No summary provided by upstream source.

Repository SourceNeeds Review
General

gis

No summary provided by upstream source.

Repository SourceNeeds Review