Claude-skill-registry cli-productivity
Essential CLI tools and shell productivity patterns for efficient terminal workflows
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/cli-productivity" ~/.claude/skills/majiayu000-claude-skill-registry-cli-productivity && rm -rf "$T"
skills/data/cli-productivity/SKILL.mdCLI Productivity Skill
Master essential CLI tools and shell patterns for efficient terminal workflows. This skill covers modern replacements for traditional Unix tools, fuzzy finding, pipeline patterns, and shell customization.
When to Use This Skill
USE when:
- Building efficient terminal workflows
- Processing text and JSON data
- Searching codebases quickly
- Navigating file systems efficiently
- Automating repetitive tasks
- Creating shell functions and aliases
- Building interactive scripts
DON'T USE when:
- GUI-based workflows are more appropriate
- Processing binary data (use specialized tools)
- Complex data analysis (use Python/Pandas)
- Tasks requiring visual feedback
Prerequisites
Installation
macOS (Homebrew):
# Essential modern tools brew install jq # JSON processor brew install fzf # Fuzzy finder brew install ripgrep # Fast grep (rg) brew install fd # Fast find brew install bat # Better cat brew install exa # Better ls (or eza) brew install zoxide # Smart cd brew install starship # Shell prompt brew install tmux # Terminal multiplexer # Install fzf keybindings $(brew --prefix)/opt/fzf/install
Linux (Ubuntu/Debian):
# Update package list sudo apt-get update # Install from apt (may be older versions) sudo apt-get install -y jq fzf ripgrep fd-find bat # Note: fd is 'fdfind' on Debian/Ubuntu sudo ln -s $(which fdfind) /usr/local/bin/fd # bat may be 'batcat' on older systems sudo ln -s $(which batcat) /usr/local/bin/bat # Install exa/eza sudo apt-get install -y exa # or: cargo install eza # Install zoxide curl -sS https://raw.githubusercontent.com/ajeetdsouza/zoxide/main/install.sh | bash # Install starship curl -sS https://starship.rs/install.sh | sh
Arch Linux:
sudo pacman -S jq fzf ripgrep fd bat exa zoxide starship tmux
Verification:
# Verify installations for cmd in jq fzf rg fd bat exa zoxide starship; do command -v $cmd && echo "$cmd: OK" || echo "$cmd: NOT FOUND" done
Core Capabilities
1. jq - JSON Processing
Basic Operations:
# Pretty print JSON echo '{"name":"John","age":30}' | jq '.' # Extract field curl -s https://api.github.com/repos/nodejs/node | jq '.stargazers_count' # Filter arrays echo '[1,2,3,4,5]' | jq '.[] | select(. > 2)' # Transform data echo '{"first":"John","last":"Doe"}' | jq '{fullName: (.first + " " + .last)}'
Common jq Patterns:
# Extract multiple fields jq '{name: .name, stars: .stargazers_count}' # Array operations jq '.items | length' # Count items jq '.items | first' # First item jq '.items | last' # Last item jq '.items[0:5]' # Slice first 5 # Filtering jq '.[] | select(.status == "active")' jq '.[] | select(.count > 100)' jq '.[] | select(.name | contains("test"))' # Sorting jq 'sort_by(.date)' jq 'sort_by(.date) | reverse' # Grouping jq 'group_by(.category)' jq 'group_by(.category) | map({key: .[0].category, count: length})' # Mapping jq '.[] | {id, name}' jq 'map({id: .id, upper_name: (.name | ascii_upcase)})'
Shell Functions for jq:
# Pretty print JSON file jqp() { jq '.' "$1" | bat --language json } # Extract field from JSON file jqf() { local file="$1" local field="$2" jq -r ".$field" "$file" } # Count items in JSON array jqcount() { jq 'if type == "array" then length else 1 end' "$1" } # Filter JSON by field value jqfilter() { local file="$1" local field="$2" local value="$3" jq --arg val "$value" ".[] | select(.$field == \$val)" "$file" }
2. fzf - Fuzzy Finder
Basic Usage:
# Find and edit file vim $(fzf) # Find with preview fzf --preview 'bat --color=always {}' # Multi-select fzf --multi # Filter with query echo -e "apple\nbanana\norange" | fzf --query "an"
fzf Configuration:
# Add to ~/.bashrc or ~/.zshrc # Default options export FZF_DEFAULT_OPTS=' --height 40% --layout=reverse --border --preview-window=right:50%:wrap --bind=ctrl-d:preview-page-down --bind=ctrl-u:preview-page-up ' # Use fd for faster file finding export FZF_DEFAULT_COMMAND='fd --type f --hidden --follow --exclude .git' export FZF_CTRL_T_COMMAND="$FZF_DEFAULT_COMMAND" export FZF_ALT_C_COMMAND='fd --type d --hidden --follow --exclude .git' # Preview settings export FZF_CTRL_T_OPTS='--preview "bat --color=always --style=numbers --line-range=:500 {}"' export FZF_ALT_C_OPTS='--preview "exa --tree --level=2 --color=always {}"'
Powerful fzf Functions:
# Fuzzy edit file fe() { local file file=$(fzf --preview 'bat --color=always --style=numbers --line-range=:500 {}') [[ -n "$file" ]] && ${EDITOR:-vim} "$file" } # Fuzzy cd into directory fcd() { local dir dir=$(fd --type d --hidden --follow --exclude .git | fzf --preview 'exa --tree --level=2 --color=always {}') [[ -n "$dir" ]] && cd "$dir" } # Fuzzy kill process fkill() { local pid pid=$(ps aux | sed 1d | fzf --multi | awk '{print $2}') [[ -n "$pid" ]] && echo "$pid" | xargs kill -9 } # Fuzzy git checkout branch fco() { local branch branch=$(git branch -a --color=always | grep -v '/HEAD' | fzf --ansi | sed 's/^[* ]*//' | sed 's#remotes/origin/##') [[ -n "$branch" ]] && git checkout "$branch" } # Fuzzy git log flog() { git log --oneline --color=always | fzf --ansi --preview 'git show --color=always {1}' | awk '{print $1}' } # Fuzzy history search fh() { local cmd cmd=$(history | fzf --tac | sed 's/^[ ]*[0-9]*[ ]*//') [[ -n "$cmd" ]] && eval "$cmd" } # Fuzzy environment variable fenv() { local var var=$(env | fzf | cut -d= -f1) [[ -n "$var" ]] && echo "${!var}" } # Fuzzy docker container fdocker() { local container container=$(docker ps --format '{{.Names}}\t{{.Image}}\t{{.Status}}' | fzf | awk '{print $1}') [[ -n "$container" ]] && docker exec -it "$container" sh }
3. ripgrep (rg) - Fast Search
Basic Usage:
# Search for pattern rg "function" # Case insensitive rg -i "error" # Show line numbers rg -n "TODO" # Search specific file types rg --type py "import" rg -t js "require" # Exclude patterns rg "pattern" --glob '!*.min.js' rg "pattern" --glob '!node_modules'
Advanced ripgrep:
# Context lines rg -C 3 "error" # 3 lines before and after rg -B 2 "error" # 2 lines before rg -A 2 "error" # 2 lines after # Fixed strings (no regex) rg -F "func()" # Word boundaries rg -w "log" # Match "log" not "logging" # Multiple patterns rg -e "pattern1" -e "pattern2" # Files matching pattern rg -l "TODO" # List files only rg -c "TODO" # Count matches per file # Inverse match rg -v "DEBUG" # Lines NOT containing DEBUG # Replace rg "old" --replace "new" # JSON output rg --json "pattern" | jq '.' # Statistics rg --stats "pattern"
ripgrep Functions:
# Search and preview with fzf rgs() { rg --color=always --line-number "$1" | fzf --ansi --preview 'bat --color=always $(echo {} | cut -d: -f1) --highlight-line $(echo {} | cut -d: -f2)' } # Search and open in editor rge() { local selection selection=$(rg --color=always --line-number "$1" | fzf --ansi) if [[ -n "$selection" ]]; then local file=$(echo "$selection" | cut -d: -f1) local line=$(echo "$selection" | cut -d: -f2) ${EDITOR:-vim} "+$line" "$file" fi } # Search TODOs todos() { rg --color=always "TODO|FIXME|HACK|XXX" "${1:-.}" | fzf --ansi } # Search function definitions funcs() { rg --color=always "^(def |function |async function |const .* = |class )" "${1:-.}" | fzf --ansi }
4. fd - Fast Find
Basic Usage:
# Find files by name fd "readme" # Find with extension fd -e md fd -e py -e js # Find directories fd -t d "src" # Find files fd -t f "config" # Exclude patterns fd -E node_modules -E .git # Hidden files fd -H "config" # Execute command on results fd -e log -x rm {} fd -e py -x wc -l {}
fd Functions:
# Find and preview fdp() { fd "$@" | fzf --preview 'bat --color=always {} 2>/dev/null || exa --tree --level=2 --color=always {}' } # Find and edit fde() { local file file=$(fd -t f "$@" | fzf --preview 'bat --color=always {}') [[ -n "$file" ]] && ${EDITOR:-vim} "$file" } # Find large files fdlarge() { local size="${1:-100M}" fd -t f -S +"$size" | xargs ls -lh | sort -k5 -h } # Find recent files fdrecent() { local days="${1:-7}" fd -t f --changed-within "${days}d" } # Find duplicates by name fddup() { fd -t f | sort | uniq -d }
5. bat - Better cat
Basic Usage:
# Syntax highlighted output bat file.py # Show line numbers bat -n file.py # Show all non-printable chars bat -A file.py # Multiple files bat file1.py file2.py # Plain output (no decorations) bat -p file.py # Specific language bat -l json data.txt # Diff two files bat --diff file1 file2
bat Configuration:
# Add to ~/.bashrc or ~/.zshrc # Set bat as default pager export MANPAGER="sh -c 'col -bx | bat -l man -p'" export PAGER="bat" # Bat theme export BAT_THEME="TwoDark" # Bat style export BAT_STYLE="numbers,changes,header"
bat Aliases:
# Replace cat with bat alias cat='bat --paging=never' # Preview alias for fzf alias preview='fzf --preview "bat --color=always {}"' # Pretty print JSON alias json='bat -l json' # Pretty print YAML alias yaml='bat -l yaml' # Diff with bat alias diff='bat --diff'
6. exa/eza - Better ls
Basic Usage:
# Basic list exa # Long format exa -l # All files including hidden exa -la # Tree view exa --tree exa --tree --level=2 # Sort by modified exa -l --sort=modified # With git status exa -l --git # Group directories first exa -l --group-directories-first # Icons exa -l --icons
exa Aliases:
# Add to ~/.bashrc or ~/.zshrc # Replace ls with exa alias ls='exa --group-directories-first' alias ll='exa -l --group-directories-first --git' alias la='exa -la --group-directories-first --git' alias lt='exa --tree --level=2' alias lta='exa --tree --level=2 -a' # With icons (if supported) alias li='exa -l --icons --group-directories-first --git'
7. zoxide - Smart cd
Basic Usage:
# Initialize (add to shell rc) eval "$(zoxide init bash)" # or zsh # Use z instead of cd z projects # Jump to most frequent/recent match z pro # Partial match # Interactive selection zi # Opens fzf for selection # Add directory manually zoxide add /path/to/dir # Query database zoxide query projects zoxide query -l # List all entries
zoxide Configuration:
# Add to ~/.bashrc or ~/.zshrc # Initialize zoxide eval "$(zoxide init bash --cmd cd)" # Replace cd # Or use custom command eval "$(zoxide init bash --cmd j)" # Use 'j' for jump
8. Shell Aliases and Functions
Essential Aliases:
# Navigation alias ..='cd ..' alias ...='cd ../..' alias ....='cd ../../..' alias ~='cd ~' alias -- -='cd -' # Safety alias rm='rm -i' alias mv='mv -i' alias cp='cp -i' # Shortcuts alias c='clear' alias h='history' alias q='exit' alias v='vim' alias e='${EDITOR:-vim}' # Git shortcuts alias g='git' alias gs='git status' alias ga='git add' alias gc='git commit' alias gp='git push' alias gl='git log --oneline -20' alias gd='git diff' alias gb='git branch' alias gco='git checkout' # Docker shortcuts alias d='docker' alias dc='docker compose' alias dps='docker ps' alias dimg='docker images' alias dlog='docker logs -f' # Common directories alias proj='cd ~/projects' alias docs='cd ~/Documents' alias dl='cd ~/Downloads'
Utility Functions:
# Create directory and cd into it mkcd() { mkdir -p "$1" && cd "$1" } # Extract any archive extract() { if [[ -f "$1" ]]; then case "$1" in *.tar.bz2) tar xjf "$1" ;; *.tar.gz) tar xzf "$1" ;; *.tar.xz) tar xJf "$1" ;; *.bz2) bunzip2 "$1" ;; *.rar) unrar x "$1" ;; *.gz) gunzip "$1" ;; *.tar) tar xf "$1" ;; *.tbz2) tar xjf "$1" ;; *.tgz) tar xzf "$1" ;; *.zip) unzip "$1" ;; *.Z) uncompress "$1" ;; *.7z) 7z x "$1" ;; *) echo "'$1' cannot be extracted" ;; esac else echo "'$1' is not a valid file" fi } # Get public IP myip() { curl -s https://ifconfig.me } # Weather weather() { curl -s "wttr.in/${1:-}" } # Quick note note() { local notes_dir="${NOTES_DIR:-$HOME/notes}" local date=$(date +%Y-%m-%d) mkdir -p "$notes_dir" ${EDITOR:-vim} "$notes_dir/$date.md" } # Serve current directory serve() { local port="${1:-8000}" python -m http.server "$port" } # Show disk usage for directory duh() { du -h "${1:-.}" | sort -h | tail -20 } # Find process by name psg() { ps aux | grep -v grep | grep -i "$1" }
Integration Examples
1. Complete Shell Configuration
~/.bashrc or ~/.zshrc:
# ═══════════════════════════════════════════════════════════════ # CLI Productivity Configuration # ═══════════════════════════════════════════════════════════════ # ───────────────────────────────────────────────────────────────── # Environment # ───────────────────────────────────────────────────────────────── export EDITOR="vim" export VISUAL="$EDITOR" export PAGER="bat" export MANPAGER="sh -c 'col -bx | bat -l man -p'" # XDG Base Directory export XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}" export XDG_DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}" export XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/.cache}" # ───────────────────────────────────────────────────────────────── # History # ───────────────────────────────────────────────────────────────── HISTSIZE=50000 HISTFILESIZE=50000 HISTCONTROL=ignoreboth:erasedups shopt -s histappend # ───────────────────────────────────────────────────────────────── # fzf Configuration # ───────────────────────────────────────────────────────────────── export FZF_DEFAULT_COMMAND='fd --type f --hidden --follow --exclude .git' export FZF_DEFAULT_OPTS=' --height 40% --layout=reverse --border --preview-window=right:50%:wrap ' export FZF_CTRL_T_COMMAND="$FZF_DEFAULT_COMMAND" export FZF_CTRL_T_OPTS='--preview "bat --color=always --style=numbers --line-range=:500 {}"' export FZF_ALT_C_COMMAND='fd --type d --hidden --follow --exclude .git' export FZF_ALT_C_OPTS='--preview "exa --tree --level=2 --color=always {}"' # ───────────────────────────────────────────────────────────────── # Tool Initialization # ───────────────────────────────────────────────────────────────── # fzf keybindings [ -f ~/.fzf.bash ] && source ~/.fzf.bash # zoxide eval "$(zoxide init bash)" # starship prompt eval "$(starship init bash)" # ───────────────────────────────────────────────────────────────── # Aliases # ───────────────────────────────────────────────────────────────── # Modern replacements alias ls='exa --group-directories-first' alias ll='exa -l --group-directories-first --git' alias la='exa -la --group-directories-first --git' alias lt='exa --tree --level=2' alias cat='bat --paging=never' alias grep='rg' alias find='fd' # Navigation alias ..='cd ..' alias ...='cd ../..' alias ....='cd ../../..' # Git alias g='git' alias gs='git status' alias ga='git add' alias gc='git commit' alias gp='git push' alias gl='git log --oneline -20' alias gd='git diff' # Docker alias d='docker' alias dc='docker compose' alias dps='docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"' # ───────────────────────────────────────────────────────────────── # Functions # ───────────────────────────────────────────────────────────────── # Fuzzy edit fe() { local file file=$(fzf --preview 'bat --color=always --style=numbers --line-range=:500 {}') [[ -n "$file" ]] && ${EDITOR:-vim} "$file" } # Fuzzy cd fcd() { local dir dir=$(fd --type d | fzf --preview 'exa --tree --level=2 --color=always {}') [[ -n "$dir" ]] && cd "$dir" } # Search and edit rge() { local selection selection=$(rg --color=always --line-number "$1" | fzf --ansi) if [[ -n "$selection" ]]; then local file=$(echo "$selection" | cut -d: -f1) local line=$(echo "$selection" | cut -d: -f2) ${EDITOR:-vim} "+$line" "$file" fi } # Create and cd mkcd() { mkdir -p "$1" && cd "$1" }
2. Data Processing Pipeline
# Process JSON API response curl -s 'https://api.github.com/users/torvalds/repos?per_page=100' \ | jq '.[] | {name: .name, stars: .stargazers_count}' \ | jq -s 'sort_by(.stars) | reverse | .[0:10]' # Find large log files and show preview fd -e log -S +10M \ | fzf --preview 'tail -100 {}' \ | xargs -I{} bat --line-range=:50 {} # Search code, preview matches, edit selected rg --color=always -l "TODO" \ | fzf --preview 'rg --color=always -C 3 "TODO" {}' \ | xargs -o ${EDITOR:-vim} # Git log with diff preview git log --oneline --color=always \ | fzf --ansi --preview 'git show --color=always {1}' \ | awk '{print $1}' \ | xargs git show
3. Interactive Script Template
#!/bin/bash # ABOUTME: Interactive CLI script using fzf and modern tools # ABOUTME: Template for building interactive shell tools set -e # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' CYAN='\033[0;36m' NC='\033[0m' log_info() { echo -e "${GREEN}[INFO]${NC} $*"; } log_warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } log_error() { echo -e "${RED}[ERROR]${NC} $*" >&2; } # Check dependencies check_deps() { local missing=() for cmd in fzf rg fd bat jq; do command -v "$cmd" >/dev/null || missing+=("$cmd") done if [[ ${#missing[@]} -gt 0 ]]; then log_error "Missing dependencies: ${missing[*]}" exit 1 fi } # Main menu using fzf main_menu() { local options=( "Search files" "Search content" "Edit config" "Run tests" "Exit" ) local selection selection=$(printf '%s\n' "${options[@]}" | fzf --header="Select action:") case "$selection" in "Search files") search_files ;; "Search content") search_content ;; "Edit config") edit_config ;; "Run tests") run_tests ;; "Exit") exit 0 ;; esac } search_files() { local file file=$(fd --type f | fzf --preview 'bat --color=always {}') [[ -n "$file" ]] && ${EDITOR:-vim} "$file" } search_content() { local query read -p "Search pattern: " query rge "$query" } edit_config() { local configs=("~/.bashrc" "~/.vimrc" "~/.gitconfig") local config config=$(printf '%s\n' "${configs[@]}" | fzf --header="Select config:") [[ -n "$config" ]] && ${EDITOR:-vim} "${config/#\~/$HOME}" } run_tests() { log_info "Running tests..." # Add test command here } # Main check_deps while true; do main_menu done
Best Practices
1. Tool Selection Guidelines
| Task | Tool | Why |
|---|---|---|
| Find files by name | fd | Fast, intuitive syntax |
| Find files by content | rg | Faster than grep, better defaults |
| View files | bat | Syntax highlighting, line numbers |
| List files | exa | Icons, git status, tree view |
| Navigate directories | zoxide | Learns your patterns |
| Interactive selection | fzf | Fuzzy matching, preview |
| Process JSON | jq | Powerful, composable |
2. Performance Tips
# Use fd instead of find fd "pattern" # Instead of: find . -name "*pattern*" # Use rg instead of grep rg "pattern" # Instead of: grep -r "pattern" . # Limit search depth fd --max-depth 3 rg --max-depth 3 # Exclude directories fd -E node_modules -E .git rg --glob '!node_modules'
3. Shell Startup Optimization
# Lazy load slow tools nvm() { unset -f nvm [ -s "$NVM_DIR/nvm.sh" ] && source "$NVM_DIR/nvm.sh" nvm "$@" } # Cache expensive operations _update_ps1_cache() { PS1_CACHE="$(expensive_command)" }
Troubleshooting
Common Issues
fzf not finding files:
# Check FZF_DEFAULT_COMMAND echo $FZF_DEFAULT_COMMAND # Test fd directly fd --type f # Check for hidden files fd -H
Colors not working:
# Check terminal capabilities echo $TERM # Force color output export CLICOLOR_FORCE=1
Slow shell startup:
# Profile startup time time bash -i -c exit # Identify slow sources for f in ~/.bashrc ~/.bash_profile; do echo "--- $f ---" time source "$f" done
zoxide not working:
# Check initialization type z # Rebuild database zoxide import --from=z
Version History
- 1.0.0 (2026-01-17): Initial release
- Core CLI tools coverage (jq, fzf, ripgrep, fd, bat, exa)
- Shell aliases and functions
- Pipeline patterns
- Integration examples
- Shell configuration templates
Use this skill to build efficient, productive terminal workflows with modern CLI tools!