Bash 5.3 new features and modern patterns (2025)
/plugin marketplace add JosiahSiegel/claude-plugin-marketplace/plugin install bash-master@claude-plugin-marketplaceThis skill inherits all available tools. When active, it can use any tool Claude has access to.
MANDATORY: Always Use Backslashes on Windows for File Paths
When using Edit or Write tools on Windows, you MUST use backslashes (\) in file paths, NOT forward slashes (/).
Examples:
D:/repos/project/file.tsxD:\repos\project\file.tsxThis applies to:
NEVER create new documentation files unless explicitly requested by the user.
Bash 5.3 (released July 2025) introduces significant new features that improve performance, readability, and functionality.
New: ${ command; } syntax - Executes without forking a subshell (runs in current shell context):
# OLD way (Bash < 5.3) - Creates subshell
output=$(expensive_command)
# NEW way (Bash 5.3+) - Runs in current shell, faster
output=${ expensive_command; }
Benefits:
Example:
#!/usr/bin/env bash
# Traditional approach
count=0
for file in *.txt; do
lines=$(wc -l < "$file") # Subshell created
((count += lines))
done
# Bash 5.3 approach (faster)
count=0
for file in *.txt; do
lines=${ wc -l < "$file"; } # No subshell
((count += lines))
done
New: ${| command; } syntax - Stores result in REPLY variable:
# Runs command, result goes to $REPLY automatically
${| complex_calculation; }
echo "Result: $REPLY"
# Multiple operations
${|
local_var="processing"
echo "$local_var: $((42 * 2))"
}
echo "Got: $REPLY"
Use Cases:
read BuiltinNew: -E option - Uses readline with programmable completion:
# Interactive input with tab completion
read -E -p "Enter filename: " filename
# User can now tab-complete file paths!
# With custom completion
read -E -p "Select environment: " env
# Enables full readline features (history, editing)
Benefits:
source BuiltinNew: -p PATH option - Custom search path for sourcing:
# OLD way
source /opt/myapp/lib/helpers.sh
# NEW way - Search custom path
source -p /opt/myapp/lib:/usr/local/lib helpers.sh
# Respects CUSTOM_PATH instead of current directory
CUSTOM_PATH=/app/modules:/shared/lib
source -p "$CUSTOM_PATH" database.sh
Benefits:
compgen BuiltinNew: Variable output option - Store completions in variable:
# OLD way - Output to stdout
completions=$(compgen -f)
# NEW way - Directly to variable
compgen -v completions_var -f
# Results now in $completions_var
Benefits:
New: Control glob sorting behavior:
# Default: alphabetical sort
echo *.txt
# Sort by modification time (newest first)
GLOBSORT="-mtime"
echo *.txt
# Sort by size
GLOBSORT="size"
echo *.txt
# Reverse alphabetical
GLOBSORT="reverse"
echo *.txt
Options:
name - Alphabetical (default)reverse - Reverse alphabeticalsize - By file sizemtime - By modification time-mtime - Reverse modification timeNew: Signal number variable in traps:
#!/usr/bin/env bash
set -euo pipefail
# BASH_TRAPSIG contains the signal number being handled
handle_signal() {
echo "Caught signal: $BASH_TRAPSIG" >&2
case "$BASH_TRAPSIG" in
15) echo "SIGTERM (15) received, shutting down gracefully" ;;
2) echo "SIGINT (2) received, cleaning up" ;;
*) echo "Signal $BASH_TRAPSIG received" ;;
esac
}
trap handle_signal SIGTERM SIGINT SIGHUP
Benefits:
New: fltexpr loadable builtin:
# Enable floating-point support
enable -f /usr/lib/bash/fltexpr fltexpr
# Perform calculations
fltexpr result = 42.5 * 1.5
echo "$result" # 63.75
# Complex expressions
fltexpr pi_area = 3.14159 * 5 * 5
echo "Area: $pi_area"
Use Cases:
# ❌ OLD (Bash < 5.3) - Multiple subshells
for i in {1..1000}; do
result=$(echo "$i * 2" | bc)
process "$result"
done
# ✅ NEW (Bash 5.3+) - No subshells
for i in {1..1000}; do
result=${ echo $((i * 2)); }
process "$result"
done
Performance Gain: ~40% faster in benchmarks
#!/usr/bin/env bash
# Process large file efficiently
process_log() {
local line_count=0
local error_count=0
while IFS= read -r line; do
((line_count++))
# Bash 5.3: No subshell for grep
if ${ grep -q "ERROR" <<< "$line"; }; then
((error_count++))
fi
done < "$1"
echo "Processed $line_count lines, found $error_count errors"
}
process_log /var/log/app.log
#!/usr/bin/env bash
# Require Bash 5.3+
if ((BASH_VERSINFO[0] < 5 || (BASH_VERSINFO[0] == 5 && BASH_VERSINFO[1] < 3))); then
echo "Error: Bash 5.3+ required (found $BASH_VERSION)" >&2
exit 1
fi
# Test for 5.3 features
has_bash_53_features() {
# Try using ${ } syntax
if eval 'test=${ echo "yes"; }' 2>/dev/null; then
return 0
else
return 1
fi
}
if has_bash_53_features; then
echo "Bash 5.3 features available"
else
echo "Using legacy mode"
fi
#!/usr/bin/env bash
set -euo pipefail
# Support both old and new bash
if ((BASH_VERSINFO[0] > 5 || (BASH_VERSINFO[0] == 5 && BASH_VERSINFO[1] >= 3))); then
# Bash 5.3+ path
result=${ compute_value; }
else
# Legacy path
result=$(compute_value)
fi
Use ${ } for performance-critical loops
for item in "${large_array[@]}"; do
processed=${ transform "$item"; }
done
Use ${| } for clean temporary values
${| calculate_hash "$file"; }
if [[ "$REPLY" == "$expected_hash" ]]; then
echo "Valid"
fi
Enable readline for interactive scripts
read -E -p "Config file: " config
Use source -p for modular libraries
source -p "$LIB_PATH" database.sh logging.sh
Document version requirements
# Requires: Bash 5.3+ for performance features
Note: Bash 5.3 (released July 2025) is the latest stable version. There is no Bash 5.4 as of October 2025.
brew install bash)bash:5.3 official imageBash 5.3 updated to C23 language standard. Note: K&R style C compilers are no longer supported.
#!/usr/bin/env bash
set -euo pipefail
# Detect bash version
readonly BASH_53_PLUS=$((BASH_VERSINFO[0] > 5 || (BASH_VERSINFO[0] == 5 && BASH_VERSINFO[1] >= 3)))
process_items() {
local item
for item in "$@"; do
if ((BASH_53_PLUS)); then
result=${ transform "$item"; } # Fast path
else
result=$(transform "$item") # Compatible path
fi
echo "$result"
done
}
#!/usr/bin/env bash
set -euo pipefail
# Parse log file (Bash 5.3 optimized)
parse_log() {
local file="$1"
local stats_errors=0
local stats_warnings=0
local stats_lines=0
while IFS= read -r line; do
((stats_lines++))
# Fast pattern matching (no subshell)
${| grep -q "ERROR" <<< "$line"; } && ((stats_errors++))
${| grep -q "WARN" <<< "$line"; } && ((stats_warnings++))
done < "$file"
echo "Lines: $stats_lines, Errors: $stats_errors, Warnings: $stats_warnings"
}
parse_log /var/log/application.log
#!/usr/bin/env bash
set -euo pipefail
# Interactive setup with readline
setup_config() {
echo "Configuration Setup"
echo "==================="
# Tab completion for paths
read -E -p "Data directory: " data_dir
read -E -p "Config file: " config_file
# Validate and store
${|
[[ -d "$data_dir" ]] && echo "valid" || echo "invalid"
}
if [[ "$REPLY" == "valid" ]]; then
echo "DATA_DIR=$data_dir" > config.env
echo "CONFIG_FILE=$config_file" >> config.env
echo "✓ Configuration saved"
else
echo "✗ Invalid directory" >&2
return 1
fi
}
setup_config
Bash 5.3 provides significant performance and usability improvements. Adopt these features gradually while maintaining backwards compatibility for older systems.
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.