Custom widgets allow you to extend Dracula tmux with your own functionality by writing bash scripts.
Custom widgets are bash scripts placed in the Dracula tmux scripts directory. They’re executed periodically to gather and display information in the status bar.
Script naming pattern
To use a custom widget, reference it in your configuration with the custom: prefix:
set -g @dracula-plugins "custom:my-script.sh"
This tells Dracula to look for my-script.sh in the scripts directory.
Script location
Place your custom script in the Dracula tmux scripts directory:
~/.tmux/plugins/tmux/scripts/my-script.sh
Or if using a custom plugin path:
/path/to/dracula/tmux/scripts/my-script.sh
Make sure your script has execute permissions: chmod +x my-script.sh
Basic script template
Here’s a minimal template for a custom widget:
#!/usr/bin/env bash
# setting the locale, some users have issues with different locales
export LC_ALL=en_US.UTF-8
# Source utilities
current_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source $current_dir/utils.sh
main()
{
# Your logic here
echo "Your output"
}
# Run main function
main
Accessing tmux options
Use the get_tmux_option utility function to read configuration values:
main()
{
# Get custom option with default value
label=$(get_tmux_option "@dracula-custom-label" "Default")
# Get refresh rate
RATE=$(get_tmux_option "@dracula-refresh-rate" 5)
echo "$label Your data here"
sleep $RATE
}
Then in your .tmux.conf:
set -g @dracula-custom-label "My Widget:"
set -g @dracula-refresh-rate 5
Example 1: Display current directory
#!/usr/bin/env bash
export LC_ALL=en_US.UTF-8
current_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source $current_dir/utils.sh
get_current_dir()
{
# Get the current pane's directory
for i in $(tmux list-panes -F "#{pane_active} #{pane_current_path}");
do
if [ "$i" == "1" ]; then
nextone="true"
elif [ "$nextone" == "true" ]; then
basename "$i"
return
fi
done
}
main()
{
label=$(get_tmux_option "@dracula-cwd-label" "📁")
dir=$(get_current_dir)
echo "$label $dir"
}
main
Configuration:
set -g @dracula-plugins "custom:current-dir.sh"
set -g @dracula-cwd-label "📁"
Example 2: Display disk usage
#!/usr/bin/env bash
export LC_ALL=en_US.UTF-8
current_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source $current_dir/utils.sh
get_disk_usage()
{
case $(uname -s) in
Linux)
df -h / | awk 'NR==2 {print $5}'
;;
Darwin)
df -h / | awk 'NR==2 {print $5}'
;;
*)
echo "N/A"
;;
esac
}
main()
{
RATE=$(get_tmux_option "@dracula-refresh-rate" 5)
label=$(get_tmux_option "@dracula-disk-label" "💾")
usage=$(get_disk_usage)
echo "$label $usage"
sleep $RATE
}
main
Configuration:
set -g @dracula-plugins "custom:disk-usage.sh"
set -g @dracula-disk-label "💾"
set -g @dracula-refresh-rate 10
Example 3: Display Docker status
#!/usr/bin/env bash
export LC_ALL=en_US.UTF-8
current_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source $current_dir/utils.sh
get_docker_status()
{
if ! command -v docker &> /dev/null; then
echo "N/A"
return
fi
if ! docker info &> /dev/null; then
echo "OFF"
return
fi
running=$(docker ps -q | wc -l | tr -d ' ')
echo "${running} running"
}
main()
{
RATE=$(get_tmux_option "@dracula-refresh-rate" 5)
label=$(get_tmux_option "@dracula-docker-label" "🐳")
status=$(get_docker_status)
echo "$label $status"
sleep $RATE
}
main
Configuration:
set -g @dracula-plugins "custom:docker-status.sh"
set -g @dracula-docker-label "🐳"
Example 4: Display todo count
#!/usr/bin/env bash
export LC_ALL=en_US.UTF-8
current_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source $current_dir/utils.sh
get_todo_count()
{
todo_file=$(get_tmux_option "@dracula-todo-file" "$HOME/todo.txt")
if [ ! -f "$todo_file" ]; then
echo "0"
return
fi
# Count non-empty lines
grep -c '.' "$todo_file" 2>/dev/null || echo "0"
}
main()
{
label=$(get_tmux_option "@dracula-todo-label" "✓")
count=$(get_todo_count)
if [ "$count" -eq 0 ]; then
echo ""
else
echo "$label $count"
fi
}
main
Configuration:
set -g @dracula-plugins "custom:todo-count.sh"
set -g @dracula-todo-file "$HOME/Documents/todo.txt"
set -g @dracula-todo-label "✓"
Best practices
Avoid expensive operations in custom widgets. They run every few seconds according to the refresh rate. Use caching for slow operations.
# Example: Cache slow operations
get_cached_data()
{
cache_file="/tmp/my-widget-cache"
cache_duration=60 # seconds
if [ -f "$cache_file" ]; then
cache_age=$(($(date +%s) - $(stat -f %m "$cache_file" 2>/dev/null || stat -c %Y "$cache_file")))
if [ $cache_age -lt $cache_duration ]; then
cat "$cache_file"
return
fi
fi
# Expensive operation
result=$(expensive_command)
echo "$result" > "$cache_file"
echo "$result"
}
Error handling
Handle errors gracefully to prevent widget failures:
main()
{
# Check if required command exists
if ! command -v some_command &> /dev/null; then
echo "N/A"
return
fi
# Handle command failures
result=$(some_command 2>/dev/null) || {
echo "ERROR"
return
}
echo "$result"
}
Support multiple operating systems:
get_data()
{
case $(uname -s) in
Linux)
# Linux-specific command
;;
Darwin)
# macOS-specific command
;;
FreeBSD|OpenBSD)
# BSD-specific command
;;
*)
echo "Unsupported"
;;
esac
}
Using utilities
The utils.sh file provides helpful functions:
# Get tmux option with default
get_tmux_option "@option-name" "default-value"
# Normalize percentage length
normalize_percent_len "75%"
Test your script directly before adding it to tmux:
# Make script executable
chmod +x ~/.tmux/plugins/tmux/scripts/my-script.sh
# Run script manually
~/.tmux/plugins/tmux/scripts/my-script.sh
# Test with different options
TMUX= ~/.tmux/plugins/tmux/scripts/my-script.sh
Debugging
Add debug output to a log file:
main()
{
# Debug logging
echo "[$(date)] Starting widget" >> /tmp/my-widget-debug.log
result=$(get_data)
echo "[$(date)] Result: $result" >> /tmp/my-widget-debug.log
echo "$result"
}
Then tail the log:
tail -f /tmp/my-widget-debug.log
Complete example
Here’s a complete custom widget with all best practices:
#!/usr/bin/env bash
# Custom widget: Display system load with color coding
export LC_ALL=en_US.UTF-8
current_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source $current_dir/utils.sh
get_load_average()
{
case $(uname -s) in
Linux|Darwin)
uptime | awk -F'load averages?: ' '{print $2}' | awk '{print $1}' | sed 's/,//'
;;
*)
echo "N/A"
;;
esac
}
main()
{
# Get configuration options
RATE=$(get_tmux_option "@dracula-refresh-rate" 5)
label=$(get_tmux_option "@dracula-load-label" "LOAD")
threshold=$(get_tmux_option "@dracula-load-threshold" "2.0")
# Get load average
load=$(get_load_average)
# Output
if [ "$load" != "N/A" ]; then
echo "$label $load"
else
echo ""
fi
sleep $RATE
}
# Run main function
main
Configuration:
set -g @dracula-plugins "custom:load-average.sh"
set -g @dracula-load-label "⚡"
set -g @dracula-load-threshold "3.0"
set -g @dracula-load-average-colors "yellow dark_gray"