Install
npx skillscat add vamseeachanta/workspace-hub/bash-cli-framework Install via the SkillsCat registry.
This skill supplies reusable bash patterns for colors, logging, headers, and error handling, allowing developers to produce consistent, readable terminal output and reliable error management in command‑line scripts. Use it when creating new CLI tools or standardizing existing scripts; avoid it for trivial one‑liners or when a different language framework is more appropriate.
Bash CLI Framework
A comprehensive framework for building consistent, professional bash CLI tools with standardized colors, logging, headers, and error handling patterns extracted from workspace-hub scripts.
When to Use This Skill
✅ Use when:
- Building new bash CLI tools or scripts
- Adding consistent output formatting to existing scripts
- Need standardized error handling and logging
- Creating user-friendly interactive scripts
- Building tools that will be used across multiple repositories
❌ Avoid when:
- Simple one-liner scripts
- Scripts that don't produce user-facing output
- When Python/Node CLI frameworks are more appropriate
Core Capabilities
1. Color Definitions
Standard ANSI color codes for consistent terminal output:
#!/bin/bash
# ABOUTME: Standard color definitions for CLI output
# ABOUTME: Use these consistently across all workspace-hub scripts
# 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'
WHITE='\033[1;37m'
NC='\033[0m' # No Color
# Bold variants
BOLD='\033[1m'
BOLD_RED='\033[1;31m'
BOLD_GREEN='\033[1;32m'
BOLD_YELLOW='\033[1;33m'
BOLD_BLUE='\033[1;34m'
# Usage examples
echo -e "${GREEN}✓ Success${NC}"
echo -e "${RED}✗ Error${NC}"
echo -e "${YELLOW}⚠ Warning${NC}"
echo -e "${CYAN}ℹ Info${NC}"2. Script Header Template
Every script should start with proper identification:
#!/bin/bash
# ABOUTME: Brief one-line description of what this script does
# ABOUTME: Additional context about usage or dependencies
set -e # Exit on error
# Script metadata
SCRIPT_NAME="$(basename "$0")"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
VERSION="1.0.0"3. Logging Functions
Standardized logging with timestamps and levels:
#!/bin/bash
# ABOUTME: Logging framework for bash scripts
# ABOUTME: Supports DEBUG, INFO, WARNING, ERROR, CRITICAL levels
# Log file configuration
LOG_FILE="${LOG_FILE:-/tmp/${SCRIPT_NAME}.log}"
LOG_LEVEL="${LOG_LEVEL:-INFO}"
# Log level values
declare -A LOG_LEVELS=(
["DEBUG"]=0
["INFO"]=1
["WARNING"]=2
["ERROR"]=3
["CRITICAL"]=4
)
log() {
local level="$1"
shift
local message="$*"
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
# Check if level meets threshold
if [[ ${LOG_LEVELS[$level]} -ge ${LOG_LEVELS[$LOG_LEVEL]} ]]; then
case "$level" in
DEBUG) echo -e "${CYAN}[${timestamp}] DEBUG${NC} - $message" ;;
INFO) echo -e "${GREEN}[${timestamp}] INFO${NC} - $message" ;;
WARNING) echo -e "${YELLOW}[${timestamp}] WARNING${NC} - $message" ;;
ERROR) echo -e "${RED}[${timestamp}] ERROR${NC} - $message" >&2 ;;
CRITICAL) echo -e "${BOLD_RED}[${timestamp}] CRITICAL${NC} - $message" >&2 ;;
esac
# Also write to log file
echo "[${timestamp}] ${level} - $message" >> "$LOG_FILE"
fi
}
# Convenience functions
log_debug() { log "DEBUG" "$@"; }
log_info() { log "INFO" "$@"; }
log_warning() { log "WARNING" "$@"; }
log_error() { log "ERROR" "$@"; }
log_critical() { log "CRITICAL" "$@"; }4. Display Headers
Professional header/banner display:
#!/bin/bash
# ABOUTME: Header and banner display functions
# ABOUTME: Creates consistent visual separation in CLI output
print_header() {
local title="$1"
local width="${2:-60}"
local char="${3:-═}"
local line=$(printf "%${width}s" | tr ' ' "$char")
echo ""
echo -e "${CYAN}${line}${NC}"
echo -e "${CYAN} ${title}${NC}"
echo -e "${CYAN}${line}${NC}"
echo ""
}
print_section() {
local title="$1"
echo ""
echo -e "${BOLD}${title}${NC}"
echo -e "${CYAN}$(printf '%.0s─' {1..40})${NC}"
}
print_status() {
local status="$1"
local message="$2"
case "$status" in
success) echo -e " ${GREEN}✓${NC} $message" ;;
error) echo -e " ${RED}✗${NC} $message" ;;
warning) echo -e " ${YELLOW}⚠${NC} $message" ;;
info) echo -e " ${CYAN}ℹ${NC} $message" ;;
pending) echo -e " ${BLUE}○${NC} $message" ;;
skip) echo -e " ${MAGENTA}⊘${NC} $message" ;;
esac
}5. Error Handling
Robust error handling with cleanup:
#!/bin/bash
# ABOUTME: Error handling and cleanup functions
# ABOUTME: Ensures graceful exit and resource cleanup
# Trap for cleanup on exit
cleanup() {
local exit_code=$?
# Remove temporary files
[[ -n "$TEMP_DIR" && -d "$TEMP_DIR" ]] && rm -rf "$TEMP_DIR"
# Log exit status
if [[ $exit_code -eq 0 ]]; then
log_info "Script completed successfully"
else
log_error "Script exited with code $exit_code"
fi
exit $exit_code
}
# Set trap
trap cleanup EXIT INT TERM
# Error handler
die() {
local message="$1"
local exit_code="${2:-1}"
log_critical "$message"
exit "$exit_code"
}
# Assert function
assert() {
local condition="$1"
local message="${2:-Assertion failed}"
if ! eval "$condition"; then
die "$message"
fi
}6. Argument Parsing
Standard argument parsing pattern:
#!/bin/bash
# ABOUTME: Argument parsing framework
# ABOUTME: Supports short/long options with values
# Default values
VERBOSE=false
DRY_RUN=false
CONFIG_FILE=""
show_usage() {
cat << EOF
Usage: $SCRIPT_NAME [OPTIONS] <arguments>
Options:
-h, --help Show this help message
-v, --verbose Enable verbose output
-n, --dry-run Show what would be done without doing it
-c, --config FILE Use specified configuration file
--version Show version information
Examples:
$SCRIPT_NAME --verbose process
$SCRIPT_NAME -c config.yaml --dry-run
EOF
}
parse_args() {
while [[ $# -gt 0 ]]; do
case "$1" in
-h|--help)
show_usage
exit 0
;;
-v|--verbose)
VERBOSE=true
LOG_LEVEL="DEBUG"
shift
;;
-n|--dry-run)
DRY_RUN=true
shift
;;
-c|--config)
CONFIG_FILE="$2"
shift 2
;;
--version)
echo "$SCRIPT_NAME version $VERSION"
exit 0
;;
--)
shift
break
;;
-*)
die "Unknown option: $1"
;;
*)
break
;;
esac
done
# Remaining arguments
ARGS=("$@")
}Complete Example
A complete script using all framework components:
#!/bin/bash
# ABOUTME: Example script demonstrating bash-cli-framework usage
# ABOUTME: Template for new CLI tools in workspace-hub
set -e
# ─────────────────────────────────────────────────────────────────
# Configuration
# ─────────────────────────────────────────────────────────────────
SCRIPT_NAME="$(basename "$0")"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
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'
NC='\033[0m'
# Defaults
VERBOSE=false
DRY_RUN=false
LOG_LEVEL="INFO"
# ─────────────────────────────────────────────────────────────────
# Functions
# ─────────────────────────────────────────────────────────────────
log_info() { echo -e "${GREEN}[INFO]${NC} $*"; }
log_warning() { echo -e "${YELLOW}[WARN]${NC} $*"; }
log_error() { echo -e "${RED}[ERROR]${NC} $*" >&2; }
die() { log_error "$1"; exit "${2:-1}"; }
print_header() {
echo ""
echo -e "${CYAN}═══════════════════════════════════════${NC}"
echo -e "${CYAN} $1${NC}"
echo -e "${CYAN}═══════════════════════════════════════${NC}"
echo ""
}
show_usage() {
cat << EOF
Usage: $SCRIPT_NAME [OPTIONS] <command>
Commands:
run Execute the main operation
status Show current status
clean Clean up temporary files
Options:
-h, --help Show this help
-v, --verbose Verbose output
-n, --dry-run Dry run mode
--version Show version
EOF
}
cleanup() {
local exit_code=$?
[[ $VERBOSE == true ]] && log_info "Cleanup complete"
exit $exit_code
}
trap cleanup EXIT INT TERM
# ─────────────────────────────────────────────────────────────────
# Main
# ─────────────────────────────────────────────────────────────────
main() {
# Parse arguments
while [[ $# -gt 0 ]]; do
case "$1" in
-h|--help) show_usage; exit 0 ;;
-v|--verbose) VERBOSE=true; shift ;;
-n|--dry-run) DRY_RUN=true; shift ;;
--version) echo "$VERSION"; exit 0 ;;
-*) die "Unknown option: $1" ;;
*) break ;;
esac
done
local command="${1:-}"
[[ -z "$command" ]] && { show_usage; die "No command specified"; }
print_header "$SCRIPT_NAME v$VERSION"
case "$command" in
run)
log_info "Running main operation..."
[[ $DRY_RUN == true ]] && log_warning "Dry run mode - no changes made"
# Implementation here
;;
status)
log_info "Checking status..."
;;
clean)
log_info "Cleaning up..."
;;
*)
die "Unknown command: $command"
;;
esac
log_info "Done!"
}
main "$@"Best Practices
1. Always Use set -e
Exit immediately if a command exits with non-zero status:
set -e
# Or for more control:
set -euo pipefail2. Quote Variables
Always quote variables to prevent word splitting:
# Good
echo "$variable"
"$command" "$arg1" "$arg2"
# Bad
echo $variable
$command $arg1 $arg23. Use Meaningful Exit Codes
# Exit codes
EXIT_SUCCESS=0
EXIT_ERROR=1
EXIT_USAGE=2
EXIT_CONFIG=34. Provide Feedback
Always tell the user what's happening:
log_info "Starting process..."
# do work
log_info "Process complete (processed $count items)"5. Support Dry Run
Let users preview changes:
if [[ $DRY_RUN == true ]]; then
log_info "[DRY RUN] Would execute: $command"
else
eval "$command"
fiIntegration with workspace-hub
This framework is used across all workspace-hub scripts:
scripts/monitoring/suggest_model.shscripts/monitoring/check_claude_usage.shscripts/workspacescripts/repository_sync
Resources
- Bash Best Practices
- Google Shell Style Guide
- ShellCheck - Static analysis tool
Version History
- 1.0.0 (2026-01-14): Initial release - extracted from workspace-hub scripts