#!/bin/bash # Get script directory for commands-db.json location SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" DB_FILE="$SCRIPT_DIR/commands-db.json" # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[0;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' MAGENTA='\033[0;35m' BOLD='\033[1m' DIM='\033[2m' NC='\033[0m' # No Color # ASCII Banner show_banner() { echo -e "${CYAN}" echo " ____ __ ____ __ __" echo " / __ )____ ______/ /_ / __ )__ ______/ /___/ /_ __" echo " / __ / __ \`/ ___/ __ \\ / __ / / / / __ / __ / / / /" echo " / /_/ / /_/ (__ ) / / / / /_/ / /_/ / /_/ / /_/ / /_/ /" echo "/_____/\\__,_/____/_/ /_/ /_____/\\__,_/\\__,_/\\__,_/\\__, /" echo " /____/" echo -e "${YELLOW} Your Intelligent CLI Assistant for Bash${NC}" echo "" } show_help() { show_banner echo -e "${BOLD}${YELLOW}QUICK START${NC}" echo -e " ${GREEN}bash-helper ask \"find large files\"${NC} # Ask a question" echo -e " ${GREEN}bash-helper category files${NC} # Browse by category" echo -e " ${GREEN}bash-helper explain \"tar -czf\"${NC} # Explain a command" echo "" echo -e "${BOLD}${YELLOW}MODES${NC}" echo -e " ${CYAN}Natural Language Queries:${NC}" echo -e " ${GREEN}ask${NC} \"query\" Ask in natural language (database)" echo -e " ${GREEN}task${NC} \"description\" Describe what you want to do (database)" echo -e " ${GREEN}ai${NC} \"complex query\" AI-powered NL2SH model (advanced) 🤖" echo "" echo -e " ${CYAN}Browse & Explore:${NC}" echo -e " ${GREEN}category${NC} NAME Browse by category (files/text/network/system)" echo -e " ${GREEN}explain${NC} \"command\" Explain what a command does" echo "" echo -e " ${CYAN}Direct Lookup:${NC}" echo -e " ${GREEN}COMMAND [FILTER]${NC} Show flags for command (e.g., ls size)" echo -e " ${GREEN}-i${NC}, ${GREEN}--interactive${NC} Interactive fzf mode" echo -e " ${GREEN}-l${NC}, ${GREEN}--list${NC} List all commands" echo "" echo -e "${BOLD}${YELLOW}CATEGORIES${NC} (20+ tasks)" echo -e " ${CYAN}files${NC} File operations (compress, find, permissions, symlinks)" echo -e " ${CYAN}text${NC} Text processing (search, replace, compare, count)" echo -e " ${CYAN}network${NC} Network ops (download, ports, ping)" echo -e " ${CYAN}system${NC} System monitoring (cpu, memory, processes)" echo "" echo -e "${BOLD}${YELLOW}EXAMPLES${NC}" echo -e " ${DIM}# Natural language${NC}" echo " bash-helper ask \"compress folder\"" echo " bash-helper ask \"search text in files\"" echo " bash-helper task \"monitor cpu usage\"" echo "" echo -e " ${DIM}# Browse and learn${NC}" echo " bash-helper category network" echo " bash-helper explain \"find . -name '*.txt'\"" echo "" echo -e " ${DIM}# Original modes (still work)${NC}" echo " bash-helper ls size # Direct flag lookup" echo " bash-helper # Interactive fzf mode" echo "" echo -e "${BOLD}${YELLOW}REQUIREMENTS${NC}" echo -e " ${GREEN}✓${NC} jq (for natural language queries)" echo -e " ${GREEN}✓${NC} fzf (for interactive mode only)" echo "" echo -e "${BOLD}${YELLOW}AI MODE${NC} 🤖" echo -e " ${GREEN}✓ NL2SH model detected!${NC} Use AI for complex queries:" echo -e " ${GREEN}bash-helper ai \"find python files modified last week\"${NC}" echo -e " ${GREEN}bash-helper ai \"count lines in all js files\"${NC}" echo "" echo " Other models available: llama3.2, qwen2.5" echo " To switch models, edit mode_ai() function" echo "" echo -e "${YELLOW}Database:${NC} $DB_FILE" echo -e "${YELLOW}Version:${NC} 2.1.0 (90+ commands, AI-powered)" echo "" } # Check if jq is available check_jq() { if ! command -v jq &> /dev/null; then echo -e "${RED}Error: jq is not installed${NC}" echo "jq is required for database search features." echo "Install it with: sudo apt install jq" echo "" echo "You can still use the original modes:" echo " bash-helper COMMAND [FILTER]" echo " bash-helper --interactive" return 1 fi return 0 } # Check if database exists check_database() { if [ ! -f "$DB_FILE" ]; then echo -e "${RED}Error: Database file not found${NC}" echo "Expected location: $DB_FILE" echo "" echo "You can still use the original modes for direct command lookup." return 1 fi return 0 } # Search database by keywords search_by_keywords() { local query="$1" local max_results="${2:-3}" if ! check_jq || ! check_database; then return 1 fi # Convert query to lowercase for matching local query_lower=$(echo "$query" | tr '[:upper:]' '[:lower:]') # Search and score tasks based on keyword matches jq -r --arg query "$query_lower" --argjson max "$max_results" ' .tasks[] | # Calculate score based on keyword matches . as $task | ($query | split(" ") | map(select(length > 2))) as $query_words | ( [ $query_words[] as $word | ( (.keywords | map(select(. | ascii_downcase | contains($word))) | length) * 2 + (if (.description | ascii_downcase | contains($word)) then 1 else 0 end) + (if (.command | ascii_downcase | contains($word)) then 1 else 0 end) ) ] | add // 0 ) as $score | select($score > 0) | {score: $score, task: .} ' "$DB_FILE" | jq -s --argjson max "$max_results" 'sort_by(-.score) | .[0:$max] | .[] | .task' } # Display a task with full details show_task() { local task_json="$1" local id=$(echo "$task_json" | jq -r '.id') local desc=$(echo "$task_json" | jq -r '.description') local cmd=$(echo "$task_json" | jq -r '.command') local category=$(echo "$task_json" | jq -r '.category') echo "" echo -e "${BLUE}═══════════════════════════════════════════════════════════${NC}" echo -e "${GREEN}Task:${NC} $desc" echo -e "${CYAN}Category:${NC} $category" echo -e "${BLUE}═══════════════════════════════════════════════════════════${NC}" echo "" echo -e "${YELLOW}Command:${NC}" echo -e " ${MAGENTA}$cmd${NC}" echo "" # Show flags explanation if available local flags=$(echo "$task_json" | jq -r '.flags_explained // empty') if [ -n "$flags" ]; then echo -e "${YELLOW}Flags explained:${NC}" echo "$task_json" | jq -r '.flags_explained | to_entries[] | " \(.key) : \(.value)"' echo "" fi # Show examples local examples=$(echo "$task_json" | jq -r '.examples // empty') if [ -n "$examples" ]; then echo -e "${YELLOW}Examples:${NC}" echo "$task_json" | jq -r '.examples[] | " \(.desc)\n → \(.cmd)\n"' fi # Show related tasks local related=$(echo "$task_json" | jq -r '.related // empty') if [ -n "$related" ] && [ "$related" != "null" ]; then echo -e "${YELLOW}Related tasks:${NC}" echo "$task_json" | jq -r '.related[]' | while read -r rel_id; do local rel_desc=$(jq -r --arg id "$rel_id" '.tasks[] | select(.id == $id) | .description' "$DB_FILE") if [ -n "$rel_desc" ] && [ "$rel_desc" != "null" ]; then echo " • $rel_desc (id: $rel_id)" fi done echo "" fi echo -e "${BLUE}═══════════════════════════════════════════════════════════${NC}" } # Show compact task result (for multiple results) show_task_compact() { local task_json="$1" local number="$2" local desc=$(echo "$task_json" | jq -r '.description') local cmd=$(echo "$task_json" | jq -r '.command') echo -e "${CYAN}${number}.${NC} ${GREEN}$desc${NC}" echo -e " ${MAGENTA}$cmd${NC}" echo "" } # Ask mode - search database and show results mode_ask() { local query="$1" if [ -z "$query" ]; then echo -e "${RED}Error: No query provided${NC}" echo "Usage: bash-helper ask \"your question\"" return 1 fi echo -e "${CYAN}Searching for:${NC} \"$query\"" # Search database local results=$(search_by_keywords "$query" 5) if [ -z "$results" ]; then echo "" echo -e "${YELLOW}No matches found for: \"$query\"${NC}" echo "" echo "Try:" echo " • Using different keywords" echo " • Browse by category: bash-helper category files" echo " • List all commands: bash-helper --list" return 1 fi # Count results local count=$(echo "$results" | jq -s 'length') if [ "$count" -eq 1 ]; then # Single result - show full details show_task "$results" else # Multiple results - show compact list echo "" echo -e "${GREEN}Found $count matches:${NC}" echo "" local i=1 echo "$results" | jq -c '.' | while read -r task; do show_task_compact "$task" "$i" i=$((i+1)) done echo -e "${YELLOW}Tip:${NC} Use more specific keywords to narrow results" fi } # Category mode - browse tasks by category mode_category() { local cat_name="$1" if ! check_jq || ! check_database; then return 1 fi if [ -z "$cat_name" ]; then echo -e "${YELLOW}Available categories:${NC}" echo "" jq -r '.categories | to_entries[] | " \(.key) : \(.value.name)"' "$DB_FILE" echo "" echo "Usage: bash-helper category NAME" return 1 fi # Get category info local cat_data=$(jq --arg cat "$cat_name" '.categories[$cat]' "$DB_FILE") if [ "$cat_data" = "null" ]; then echo -e "${RED}Category not found:${NC} $cat_name" echo "" echo "Available categories:" jq -r '.categories | keys[]' "$DB_FILE" | sed 's/^/ /' return 1 fi local cat_title=$(echo "$cat_data" | jq -r '.name') local task_ids=$(echo "$cat_data" | jq -r '.tasks[]') echo "" echo -e "${BLUE}═══════════════════════════════════════════════════════════${NC}" echo -e "${CYAN}Category:${NC} ${GREEN}$cat_title${NC}" echo -e "${BLUE}═══════════════════════════════════════════════════════════${NC}" echo "" local i=1 for task_id in $task_ids; do local task=$(jq --arg id "$task_id" '.tasks[] | select(.id == $id)' "$DB_FILE") if [ -n "$task" ] && [ "$task" != "null" ]; then show_task_compact "$task" "$i" i=$((i+1)) fi done } # AI mode - use NL2SH model for complex queries mode_ai() { local user_query="$1" if [ -z "$user_query" ]; then echo -e "${RED}Error: No query provided${NC}" echo "Usage: bash-helper ai \"your complex query\"" echo "" echo "Example:" echo " bash-helper ai \"find all python files modified in last week\"" return 1 fi # Check if ollama is available if ! command -v ollama &> /dev/null; then echo -e "${RED}Error: Ollama is not installed${NC}" echo "" echo "Install Ollama:" echo " curl -fsSL https://ollama.com/install.sh | sh" echo "" echo "For now, try: bash-helper ask \"$user_query\"" return 1 fi # Check if NL2SH model is available if ! ollama list | grep -q "westenfelder/NL2SH"; then echo -e "${YELLOW}NL2SH model not found. Available models:${NC}" ollama list echo "" echo "Pull NL2SH model with:" echo " ollama pull westenfelder/NL2SH" return 1 fi echo "" echo -e "${CYAN}🤖 AI Assistant - Using NL2SH Model${NC}" echo -e "${BLUE}═══════════════════════════════════════════════════════════${NC}" echo -e "${YELLOW}Query:${NC} $user_query" echo -e "${BLUE}═══════════════════════════════════════════════════════════${NC}" echo "" echo -e "${DIM}Generating bash command...${NC}" echo "" # Query the NL2SH model local response=$(ollama run westenfelder/NL2SH "$user_query" 2>/dev/null) if [ -z "$response" ]; then echo -e "${RED}Error: No response from AI model${NC}" echo "" echo "Try a simpler query or use: bash-helper ask \"$user_query\"" return 1 fi # Display the generated command echo -e "${GREEN}Generated Command:${NC}" echo -e " ${MAGENTA}$response${NC}" echo "" # Extract the base command for explanation local base_cmd=$(echo "$response" | awk '{print $1}') # Try to provide explanation if command -v "$base_cmd" &> /dev/null || type "$base_cmd" 2>/dev/null | grep -q "shell builtin"; then echo -e "${YELLOW}Command Info:${NC}" if type "$base_cmd" 2>/dev/null | grep -q "shell builtin"; then help "$base_cmd" 2>/dev/null | head -3 else man "$base_cmd" 2>/dev/null | col -b | grep -A 2 "^NAME" | tail -2 fi echo "" fi echo -e "${DIM}Note: Always review AI-generated commands before running them!${NC}" echo "" echo -e "${BLUE}═══════════════════════════════════════════════════════════${NC}" } # Explain mode - parse and explain a command mode_explain() { local cmd_line="$1" if [ -z "$cmd_line" ]; then echo -e "${RED}Error: No command provided${NC}" echo "Usage: bash-helper explain \"command with flags\"" echo "" echo "Example:" echo " bash-helper explain \"tar -czf archive.tar.gz folder/\"" return 1 fi # Extract the base command local base_cmd=$(echo "$cmd_line" | awk '{print $1}') echo "" echo -e "${BLUE}═══════════════════════════════════════════════════════════${NC}" echo -e "${YELLOW}Command:${NC} ${MAGENTA}$cmd_line${NC}" echo -e "${BLUE}═══════════════════════════════════════════════════════════${NC}" echo "" # Get syntax from man page SYNOPSIS section if command -v "$base_cmd" &> /dev/null || type "$base_cmd" 2>/dev/null | grep -q "shell builtin"; then echo -e "${CYAN}${BOLD}SYNTAX:${NC}" if type "$base_cmd" 2>/dev/null | grep -q "shell builtin"; then # For builtins, get the first line of help local syntax=$(help "$base_cmd" 2>/dev/null | head -1 | sed 's/^[[:space:]]*//') if [ -n "$syntax" ]; then echo -e " ${GREEN}$syntax${NC}" else echo -e " ${GREEN}$base_cmd [options]${NC}" fi else # For regular commands, extract SYNOPSIS section from man page local synopsis=$(man "$base_cmd" 2>/dev/null | col -b | sed -n '/^SYNOPSIS/,/^DESCRIPTION/p' | head -15 | tail -n +2 | head -n -1 | sed 's/^[[:space:]]*/ /') if [ -n "$synopsis" ]; then echo -e "${GREEN}$synopsis${NC}" else # Fallback: try to get usage from command itself local usage=$("$base_cmd" --help 2>&1 | grep -i "usage" | head -1 | sed 's/^[Uu]sage: / /') if [ -n "$usage" ]; then echo -e " ${GREEN}$usage${NC}" else echo -e " ${GREEN}$base_cmd [options]${NC}" fi fi fi echo "" fi # Try to find in database local found_in_db=false if check_jq && check_database; then local task=$(jq --arg cmd "$base_cmd" '.tasks[] | select(.command | contains($cmd))' "$DB_FILE" 2>/dev/null | jq -s '.[0]' 2>/dev/null) if [ -n "$task" ] && [ "$task" != "null" ] && [ "$task" != "" ]; then local desc=$(echo "$task" | jq -r '.description // empty' 2>/dev/null) if [ -n "$desc" ]; then echo -e "${GREEN}Description:${NC} $desc" echo "" found_in_db=true # Show flags if available local flags=$(echo "$task" | jq -r '.flags_explained // empty' 2>/dev/null) if [ -n "$flags" ] && [ "$flags" != "null" ]; then echo -e "${YELLOW}Flag explanations:${NC}" echo "$task" | jq -r '.flags_explained | to_entries[] | " \(.key) : \(.value)"' 2>/dev/null echo "" fi fi fi fi # Fall back to man page if not found in database if [ "$found_in_db" = false ]; then if command -v "$base_cmd" &> /dev/null || type "$base_cmd" 2>/dev/null | grep -q "shell builtin"; then echo -e "${YELLOW}Getting help from man page...${NC}" echo "" if type "$base_cmd" 2>/dev/null | grep -q "shell builtin"; then help "$base_cmd" 2>/dev/null | head -20 else man "$base_cmd" 2>/dev/null | col -b | head -30 fi else echo -e "${RED}Command not found:${NC} $base_cmd" fi fi echo "" echo -e "${BLUE}═══════════════════════════════════════════════════════════${NC}" } show_flags() { CMD_NAME=$1 FILTER=$2 echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" echo -e "${YELLOW}Flags for: ${GREEN}$CMD_NAME${NC}" if [ -n "$FILTER" ]; then echo -e "${YELLOW}Filter: ${GREEN}$FILTER${NC}" fi echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" echo "" # Try to get flags from man page if type "$CMD_NAME" 2>/dev/null | grep -q "shell builtin"; then # Shell builtin - use help command if [ -n "$FILTER" ]; then help "$CMD_NAME" 2>/dev/null | grep -E '^\s*-' | grep -i "$FILTER" else help "$CMD_NAME" 2>/dev/null | grep -E '^\s*-' fi elif command -v "$CMD_NAME" &> /dev/null; then # External command - use man page # Extract the OPTIONS section from man page local man_output=$(man "$CMD_NAME" 2>/dev/null | col -b) if [ -z "$man_output" ]; then echo -e "${RED}No manual page available for: $CMD_NAME${NC}" return 1 fi # Try to extract just the OPTIONS/FLAGS section local options_section=$(echo "$man_output" | sed -n '/^OPTIONS/,/^[A-Z][A-Z]/p' | head -100) if [ -z "$options_section" ]; then # Fallback: get all lines that look like flags options_section=$(echo "$man_output" | grep -E '^\s*-' | head -50) fi if [ -n "$FILTER" ]; then echo "$options_section" | grep -i "$FILTER" | head -30 else echo "$options_section" | head -30 fi else echo -e "${RED}Could not find help for: $CMD_NAME${NC}" echo "" echo "Make sure the command is installed or check the spelling." return 1 fi echo "" echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" } list_commands() { echo "Available commands:" echo "" for cmd in "${COMMANDS[@]}"; do CMD_NAME=${cmd%%:*} DESC=${cmd#*:} printf " %-10s - %s\n" "$CMD_NAME" "$DESC" done } get_command_description() { local search_cmd=$1 for cmd in "${COMMANDS[@]}"; do CMD_NAME=${cmd%%:*} DESC=${cmd#*:} if [ "$CMD_NAME" = "$search_cmd" ]; then echo "$DESC" return 0 fi done echo "Command help" } # Command definitions for interactive mode COMMANDS=( # File Operations "ls:List directory contents" "cd:Change the current directory" "pwd:Print the name of the current working directory" "cp:Copy files and directories" "mv:Move or rename files and directories" "rm:Remove files or directories" "mkdir:Create a new directory" "rmdir:Remove an empty directory" "touch:Create empty file or update timestamp" "cat:Concatenate and display files" "less:View file contents with pagination" "head:Display first lines of a file" "tail:Display last lines of a file" "chmod:Change file permissions" "chown:Change file owner" "ln:Create links between files" "file:Determine file type" "stat:Display file status" # Text Processing "grep:Search for patterns in files" "sed:Stream editor for text manipulation" "awk:Pattern scanning and text processing" "cut:Remove sections from lines of files" "sort:Sort lines of text" "uniq:Report or filter out repeated lines" "tr:Translate or delete characters" "wc:Count lines, words, and characters" "diff:Compare files line by line" # File Search "find:Search for files in directory hierarchy" "locate:Find files by name quickly" "which:Show full path of commands" "whereis:Locate binary, source, and manual pages" # Compression "tar:Archive files" "gzip:Compress files" "gunzip:Decompress gzip files" "zip:Package and compress files" "unzip:Extract compressed zip files" # Network "ping:Test network connectivity" "curl:Transfer data from URLs" "wget:Download files from the web" "ssh:Secure shell remote login" "scp:Secure copy files between hosts" "netstat:Network statistics" "ss:Socket statistics" "ip:Show/manipulate routing and devices" "ifconfig:Configure network interfaces" # System Info "top:Display system processes" "htop:Interactive process viewer" "ps:Report process status" "df:Show disk space usage" "du:Estimate file space usage" "free:Display memory usage" "uname:Print system information" "uptime:Show how long system has been running" # Process Management "kill:Send signal to a process" "pkill:Kill processes by name" "killall:Kill processes by name" "bg:Put job in background" "fg:Bring job to foreground" "jobs:List active jobs" # System Control "sudo:Execute command as another user" "systemctl:Control systemd services" "service:Control system services" "reboot:Reboot the system" "shutdown:Shut down the system" # Package Management "apt:Package manager (Debian/Ubuntu)" "apt-get:APT package handling utility" "dpkg:Debian package manager" "snap:Snap package manager" # User Management "useradd:Create new user" "userdel:Delete user account" "passwd:Change user password" "su:Switch user" "whoami:Print current username" "w:Show who is logged in" "who:Show who is logged in" # Misc Utilities "echo:Display a line of text" "date:Display or set system date and time" "cal:Display calendar" "history:Show command history" "alias:Create command aliases" "export:Set environment variables" "env:Display environment variables" "man:Display manual pages" "watch:Execute command periodically" ) # Parse arguments MODE="" QUERY="" INTERACTIVE=false COMMAND="" FILTER="" if [ $# -eq 0 ]; then INTERACTIVE=true else case "$1" in -h|--help) show_help exit 0 ;; -l|--list) list_commands exit 0 ;; -i|--interactive) INTERACTIVE=true ;; ask) MODE="ask" QUERY="$2" ;; task) MODE="task" QUERY="$2" ;; explain) MODE="explain" QUERY="$2" ;; category) MODE="category" QUERY="$2" ;; ai) MODE="ai" QUERY="$2" ;; -*) echo "Unknown option: $1" echo "Use --help for usage information" exit 1 ;; *) COMMAND=$1 FILTER=$2 ;; esac fi # Handle new modes if [ -n "$MODE" ]; then case "$MODE" in ask|task) mode_ask "$QUERY" exit $? ;; explain) mode_explain "$QUERY" exit $? ;; category) mode_category "$QUERY" exit $? ;; ai) mode_ai "$QUERY" exit $? ;; esac fi # Interactive mode with fzf if [ "$INTERACTIVE" = true ]; then # Check if fzf is available if ! command -v fzf &> /dev/null; then echo "Error: fzf is not installed" echo "Install it with: sudo apt install fzf" echo "" echo "Or use direct mode: bash-helper COMMAND [FILTER]" exit 1 fi FZF_COMMAND=$(printf "%s\n" "${COMMANDS[@]}" | fzf --height 40% --border --preview 'echo {}' --preview-window=up:1:wrap) if [ -n "$FZF_COMMAND" ]; then CMD=${FZF_COMMAND%%:*} DESC=${FZF_COMMAND#*:} echo "" echo -e "\033[0;34m═══════════════════════════════════════════════════════════\033[0m" echo -e "\033[0;32mCommand:\033[0m $CMD" echo -e "\033[0;32mDescription:\033[0m $DESC" echo -e "\033[0;34m═══════════════════════════════════════════════════════════\033[0m" echo "" read -p "Filter flags (optional, press Enter to skip): " FILTER echo "" show_flags "$CMD" "$FILTER" else echo "No command selected" exit 0 fi # Direct mode elif [ -n "$COMMAND" ]; then # Validate command exists in our list FOUND=false for cmd in "${COMMANDS[@]}"; do CMD_NAME=${cmd%%:*} if [ "$CMD_NAME" = "$COMMAND" ]; then FOUND=true DESC=${cmd#*:} break fi done if [ "$FOUND" = false ]; then echo "Warning: '$COMMAND' is not in the predefined list" echo "Available commands:" list_commands echo "" echo "Attempting to show flags anyway..." echo "" fi # Show command info DESC=$(get_command_description "$COMMAND") echo "" echo -e "\033[0;34m═══════════════════════════════════════════════════════════\033[0m" echo -e "\033[0;32mCommand:\033[0m $COMMAND" echo -e "\033[0;32mDescription:\033[0m $DESC" echo -e "\033[0;34m═══════════════════════════════════════════════════════════\033[0m" echo "" show_flags "$COMMAND" "$FILTER" else show_help exit 1 fi