Development Workflows
1. Project Switcher
# Jump between projects with fzf
fproject() {
local project_dirs=(
~/projects
~/work
/opt/docker-data/apps
/srv
)
local project
project=$(find "${project_dirs[@]}" \
-maxdepth 2 \
-name ".git" -type d 2>/dev/null \
| sed 's|/.git||' \
| fzf \
--preview 'echo "📁 $(basename {})" && git -C {} log --oneline -10 --color=always && echo "---" && git -C {} status --short' \
--preview-window 'right:50%' \
--prompt '📂 Project> ' \
--bind 'ctrl-/:toggle-preview' \
--header 'Select project directory')
[[ -z "$project" ]] && return
cd "$project"
# Optional: open in tmux new window
if [[ -n "$TMUX" ]]; then
tmux rename-window "$(basename "$project")"
fi
}
2. npm / yarn Script Runner
# Run npm/yarn scripts interactively
fnpm() {
local pkg_json
pkg_json=$(find . -name "package.json" -not -path "*/node_modules/*" | fzf \
--prompt 'package.json> ' \
--preview 'jq .scripts {}')
[[ -z "$pkg_json" ]] && return
local dir
dir=$(dirname "$pkg_json")
local script
script=$(jq -r '.scripts | keys[]' "$pkg_json" | fzf \
--preview "jq -r '.scripts.{}' $pkg_json" \
--preview-window 'down:3' \
--prompt "npm run ($dir)> ")
[[ -n "$script" ]] && cd "$dir" && npm run "$script"
}
3. Python Environment Switcher
# Activate a Python virtual environment
fpyenv() {
local venv
venv=$(find ~ /srv /opt -name "activate" -path "*/bin/activate" \
-not -path "*/proc/*" 2>/dev/null \
| sed 's|/bin/activate||' \
| fzf \
--preview 'cat {}/bin/python --version 2>/dev/null; ls {}/lib/python*/site-packages/ 2>/dev/null | head -20' \
--preview-window 'right:40%' \
--prompt '🐍 venv> ')
[[ -n "$venv" ]] && source "$venv/bin/activate" && echo "Activated: $venv"
}
4. Environment Variable Switcher (.env files)
# Load a .env file interactively
fenv_load() {
local envfile
envfile=$(find . ~ /opt -name ".env" -o -name "*.env" \
-not -path "*/node_modules/*" 2>/dev/null | fzf \
--preview 'cat {}' \
--preview-window 'right:50%' \
--prompt '🌍 .env> ')
[[ -z "$envfile" ]] && return
set -a
source "$envfile"
set +a
echo "Loaded: $envfile"
}
5. HTTP Status Code Lookup
# Quickly look up HTTP status codes
fhttp() {
local code
code=$(cat << 'EOF'
100 Continue
101 Switching Protocols
200 OK
201 Created
204 No Content
301 Moved Permanently
302 Found
304 Not Modified
400 Bad Request
401 Unauthorized
403 Forbidden
404 Not Found
405 Method Not Allowed
408 Request Timeout
409 Conflict
410 Gone
422 Unprocessable Entity
429 Too Many Requests
500 Internal Server Error
501 Not Implemented
502 Bad Gateway
503 Service Unavailable
504 Gateway Timeout
EOF
)
echo "$code" | fzf \
--prompt 'HTTP Status> ' \
--preview 'echo {}' \
--preview-window 'down:3' \
--query="${1:-}"
}
6. Makefile Target Runner
# Select and run a Makefile target
fmake() {
local target
local makefile="${1:-Makefile}"
[[ ! -f "$makefile" ]] && echo "No $makefile found" && return
target=$(grep -E "^[a-zA-Z_-]+:" "$makefile" \
| grep -v "^#" | cut -d: -f1 | sort -u | fzf \
--preview "make -n {} 2>/dev/null | head -20" \
--preview-window 'right:50%' \
--prompt 'make> ' \
--header "Makefile targets in $PWD")
[[ -n "$target" ]] && make "$target"
}
7. Interactive API Testing
# Browse and run .http files with rest.nvim or httpie
fhttp_file() {
local file
file=$(find . -name "*.http" -o -name "*.rest" | fzf \
--preview 'bat --color=always {}' \
--preview-window 'right:60%' \
--prompt '🌐 HTTP File> ')
[[ -z "$file" ]] && return
# Open in nvim (with rest.nvim)
nvim "$file"
}
8. Complete Dotfile Manager
# Interactive dotfile linker
fdotfiles() {
local dotfiles_dir="${DOTFILES:-~/.dotfiles}"
[[ ! -d "$dotfiles_dir" ]] && echo "No dotfiles dir: $dotfiles_dir" && return
local file action key
local out
out=$(find "$dotfiles_dir" -type f | fzf \
--preview 'bat --color=always {} || cat {}' \
--preview-window 'right:60%:hidden' \
--bind 'ctrl-/:toggle-preview' \
--expect=ctrl-l,ctrl-e \
--prompt '⚙ Dotfiles> ' \
--header $'Enter: open Ctrl+L: link Ctrl+E: edit')
key=$(head -1 <<< "$out")
file=$(tail -1 <<< "$out")
[[ -z "$file" ]] && return
local relative
relative="${file#$dotfiles_dir/}"
local target="$HOME/$relative"
case "$key" in
ctrl-l)
mkdir -p "$(dirname "$target")"
ln -sfv "$file" "$target"
;;
ctrl-e)
${EDITOR:-vim} "$file"
;;
*)
${EDITOR:-vim} "$file"
;;
esac
}