Shell power tools: zoxide, direnv, starship, htop, entr
В прошлых уроках мы рассмотрели большие категории productivity-tools: jq для JSON, fzf для fuzzy search, ripgrep/fd/bat для замены классики, tmux для multiplexing. В этом, заключительном для модуля 19 уроке — сборка ещё нескольких must-have tools, которые дополняют картину: smart cd, per-project env vars, modern prompt, real-time мониторинг, file-watching.
Каждый отдельно — это +5-15% удобства. Все вместе — кардинально другой shell experience. Junior, который собрал такой setup на первой неделе, опережает коллег, которые годами работают на дефолтном bash без mods.
В этом уроке: zoxide (smart cd), direnv (per-dir envs), starship (prompt), htop/btop/duf/ncdu (system monitors), entr (file watcher). Установка, основы, DE use cases.
zoxide: smart cd
Стандартный cd требует точный путь. cd /etc или cd ~/projects/etl/dags. Если ты ходишь в эту директорию каждый день — это lots of typing.
zoxide запоминает директории, в которые ты ходил, и позволяет переходить через substring или fuzzy match:
# Установка:
sudo apt install zoxide # Debian
brew install zoxide # macOS
# Интеграция (~/.bashrc):
eval "$(zoxide init bash)"
# Перезайти в shell, начать использовать:
$ cd ~/projects/learning-platform-engine
$ cd /etc/airflow/dags
$ cd ~/Documents/work-stuff
# Сейчас zoxide запомнил эти директории. Теперь:
$ z eng # переходит в ~/projects/learning-platform-engine
$ z dags # переходит в /etc/airflow/dags
$ z work # ~/Documents/work-stuff
z PARTIAL — поиск среди запомненных директорий по substring + frecency (frequency + recency). Самые посещаемые ранжируются выше.
$ z eng dags # многословный — engineer dags = etl/dags
$ zi # interactive picker через fzf
$ z - # cd -, в предыдущую
Старая альтернатива — autojump (Python). zoxide — Rust, быстрее, активно maintained.
direnv: per-directory env variables
В DE-работе часто разные проекты требуют разных env vars: API keys, database URLs, AWS_PROFILE. Один проект работает с staging БД, другой — с production. Менять export руками каждый раз — error-prone.
direnv — автозагрузка .envrc файла в каждой директории. Зашёл в проект — env vars загружены, вышел — выгружены.
# Установка:
sudo apt install direnv
brew install direnv
# Интеграция (~/.bashrc):
eval "$(direnv hook bash)"
Использование:
$ cd ~/projects/etl-airflow
$ cat > .envrc <<EOF
export AIRFLOW_HOME=$PWD/airflow_home
export DATABASE_URL="postgresql://localhost/airflow_dev"
export AWS_PROFILE=staging
EOF
# direnv заметил .envrc:
direnv: error /home/user/projects/etl-airflow/.envrc is blocked. Run `direnv allow`.
$ direnv allow
direnv: loading .envrc
direnv: export +AIRFLOW_HOME +DATABASE_URL +AWS_PROFILE
# Теперь env vars загружены:
$ echo $AIRFLOW_HOME
/home/user/projects/etl-airflow/airflow_home
# Уходим:
$ cd ~
direnv: unloading
$ echo $AIRFLOW_HOME
# (пусто)
direnv выполняет .envrc как bash-скрипт. Это удобно (use python для virtualenv, dotenv для .env), но опасно — никогда direnv allow в чужом проекте без чтения .envrc. Команда direnv allow — explicit consent: новые .envrc не загружаются автоматически.
Standard library: layout python
direnv имеет stdlib с helper-функциями:
# .envrc
layout python # автомат: создать .venv, активировать, добавить в PATH
# Зашёл в директорию — virtualenv активен. Вышел — деактивирован.
Альтернативные layouts:
layout node # node version manager integration
layout python3.13 # specific Python version
use nix # NixOS shell integration
.envrc + .env files
Часто проекты держат env vars в .env (12-factor):
# .envrc
dotenv # загрузит .env как env vars
Поскольку .env обычно в .gitignore, а .envrc коммитится — это hybrid approach: общие настройки в .envrc, секреты в .env.
starship: modern prompt
Дефолтный bash prompt — user@host:~/path$. Минималистично, но не информативно. Если ты в git-репо — не видишь branch. В Python virtualenv — не видишь имя. Команда упала с exit code 1 — не видишь визуально.
starship — настраиваемый prompt на Rust. Conditional rendering (показывает только то, что релевантно), быстрый, кросс-shell (bash, zsh, fish, …).
# Установка:
curl -sS https://starship.rs/install.sh | sh
# или: brew install starship
# Интеграция (~/.bashrc):
eval "$(starship init bash)"
После перезахода в shell — prompt становится rich:
~/projects/etl-airflow on feature/user_events [!up] via py v3.13.0 (.venv)
>
Что видно:
- Текущая директория с иконкой
- Git branch + статус (! = unstaged, up = ahead remote)
- Python version + virtualenv name
- Стрелка
>— prompt (зелёная если последняя команда успешна, красная если упала)
Кастомизация: ~/.config/starship.toml
# ~/.config/starship.toml
# Не показывать username/hostname, если не SSH:
[username]
show_always = false
[hostname]
ssh_only = true
# Compact mode:
add_newline = false
# Git:
[git_branch]
symbol = " "
[git_status]
ahead = "up${count}"
behind = "⇣${count}"
# Python:
[python]
symbol = " "
format = 'via [${symbol}${pyenv_prefix}(${version} )(\($virtualenv\) )]($style)'
# AWS profile (видно когда работаешь с AWS):
[aws]
symbol = " "
format = 'on [${symbol}($profile )(\($region\) )]($style)'
starship поддерживает 100+ модулей: kubernetes context, terraform workspace, container, time, exit code, command duration. Каждый — conditional (показывается только когда релевантен).
kubectl context и namespace — что отображает starshiphtop/btop: process monitors
top — стандартный, но minimal. htop — interactive, colored, mouse support. btop — ещё больше fancy (CPU graph per-core, memory usage chart, network).
# Установка:
sudo apt install htop btop
brew install htop btop
# Запуск:
htop
# или:
btop
В DE-работе мониторинг полезен:
- Сколько RAM ест Airflow worker?
- Какой Python process хочет 100% CPU?
- Кто открыл файл, который нельзя удалить (
lsof-like через htop tree)?
Keys в htop:
F2— configF3— searchF4— filterF5— tree viewF6— sort by columnF9— killt— toggle tree
ncdu: disk usage navigator
du -sh */ | sort -h показывает размеры, но навигировать тяжело. ncdu — интерактивный TUI:
sudo apt install ncdu
brew install ncdu
ncdu /var/log
Открывается TUI:
--- /var/log -----------------------------
12.3 GiB [##########] /journal
4.5 GiB [### ] /apt
2.1 GiB [# ] /airflow
1.2 GiB [ ] syslog.1
423.0 MiB [ ] /docker
Стрелки навигируют, d удалить, Enter войти. Идеальный tool для “что забивает диск”.
duf: df replacement
df -h выводит таблицу filesystems, но не визуально. duf:
sudo apt install duf
brew install duf
duf
# Красивая таблица с прогресс-барами usage, типами FS, mount points
Полезно для quick overview health всех partitions.
entr: re-run on file change
entr запускает команду при изменении любого из watched файлов. Незаменим для test-driven workflow без специальных tools.
sudo apt install entr
brew install entr
# Re-run tests при изменении .py:
ls *.py | entr -r pytest
# Restart Python скрипт при изменении:
echo myscript.py | entr -r python myscript.py
# Re-validate SQL при изменении query.sql:
echo query.sql | entr -r 'sqlfluff lint query.sql'
# Re-build Markdown -> PDF:
ls *.md | entr pandoc -o out.pdf input.md
# Re-render Jupyter notebook:
ls *.ipynb | entr -r jupyter nbconvert --execute *.ipynb
-r — restart (kill previous run, start fresh). Без -r — wait for current to finish first.
Простой паттерн для local development loop без webpack/vite/что-либо.
Bash improvements
Несколько мелких настроек для ~/.bashrc:
# History:
HISTSIZE=50000
HISTFILESIZE=100000
HISTCONTROL=ignoredups:erasedups
shopt -s histappend # append, не overwrite
PROMPT_COMMAND="history -a; history -n" # sync between sessions
# Useful aliases:
alias ll='ls -lah'
alias ..='cd ..'
alias ...='cd ../..'
alias gst='git status'
alias gco='git checkout'
alias gd='git diff'
alias k='kubectl'
alias dc='docker compose'
# safer rm:
alias rm='rm -i' # confirm before delete (или -I для bulk)
# Color:
alias ls='ls --color=auto'
alias grep='grep --color=auto'
zsh — альтернатива bash с лучшей completion (Tab умнее), spell-check, theming. Если работаешь с oh-my-zsh или starship — переход easy.
Production setup checklist
Установка одной командой через brew bundle (macOS) или Ansible playbook (Linux):
# Brewfile:
brew "ripgrep"
brew "fd"
brew "bat"
brew "dust"
brew "fzf"
brew "zoxide"
brew "direnv"
brew "starship"
brew "jq"
brew "yq"
brew "htop"
brew "btop"
brew "ncdu"
brew "duf"
brew "entr"
brew "tmux"
brew "tree"
brew "wget"
brew "uv"
# Установка:
brew bundle
~/.local/bin: PATH для своих скриптов
Хорошая привычка — держать свои скрипты в ~/.local/bin/ (или ~/bin/):
# В ~/.bashrc:
export PATH="$HOME/.local/bin:$PATH"
# Создать утилиту:
mkdir -p ~/.local/bin
cat > ~/.local/bin/extract.sh <<'EOF'
#!/bin/bash
# Smart extract: extract.sh archive.tar.gz
case "$1" in
*.tar.gz|*.tgz) tar xzf "$1" ;;
*.tar.bz2) tar xjf "$1" ;;
*.tar.xz) tar xJf "$1" ;;
*.zip) unzip "$1" ;;
*.7z) 7z x "$1" ;;
*) echo "Unknown: $1"; exit 1 ;;
esac
EOF
chmod +x ~/.local/bin/extract.sh
# Теперь из любой директории:
extract.sh data.tar.gz
Это твой personal toolkit. С опытом будут десятки таких утилит.
Cross-links
- Урок 02 (fzf) — zoxide + fzf =
ziinteractive picker. - Урок 04 (tmux) — starship показывает tmux session в prompt.
- Модуль 02 (shell config) — где править ~/.bashrc, ~/.zshrc.
- Модуль 09 (processes) — htop как замена ps/top.
Попробуй сам
- Установи zoxide:
brew install zoxide # или apt
# В ~/.bashrc:
eval "$(zoxide init bash)"
# Перезайди в shell
Походи по нескольким директориям через cd. Потом попробуй z PARTIAL — переход.
- Создай .envrc в тестовом проекте:
mkdir test-proj && cd test-proj
echo 'export FOO=bar' > .envrc
direnv allow
echo $FOO # bar
cd ..
echo $FOO # (empty)
- Установи starship, сделай минимальную конфигурацию:
brew install starship
# В ~/.bashrc:
eval "$(starship init bash)"
Зайди в git-репо — увидишь branch в prompt.
-
Поэкспериментируй с htop. Сравни с дефолтным top.
-
entr — auto-rerun:
# В одном окне:
echo myscript.sh | entr -r bash myscript.sh
# В другом окне правь myscript.sh — увидишь авто-restart.
- ncdu для своей home:
ncdu ~
Найди, что съедает место.