
Отслеживайте каждую переменную окружения оболочки до её точного источника: файла и строки. Проверяйте конфигурации оболочек на наличие мёртвых записей, дубликатов и осиротевших файлов в zsh и bash на macOS, Linux и FreeBSD.
Для каждой переменной в вашей текущей оболочке находит файл и строку, которые её установили, — или определяет, какая подсистема (direnv, launchd, терминал, SSH, система) её внедрила. Плюс несколько команд для статических файлов на тот случай, когда ваш конфиг оболочки расползся по N файлам и резервным копиям, и вы потеряли нить.
Я создал этот инструмент, потому что постоянно терял один и тот же час каждые несколько месяцев, выясняя, почему какой-нибудь JAVA_HOME или PATH указывает не туда, куда я ожидал. which знает команды, direnv status знает direnv, launchctl getenv знает launchd — но ни один из них не скажет вам, что настоящим автором значения является ~/.zshrc:42.
Работает с zsh и bash на macOS, Linux и FreeBSD.
grep -r JAVA_HOME ~ покажет все файлы, в которых упоминается переменная, но из вывода неясно, какое именно присваивание активно в текущей оболочке:
$ envocabulary explain --chain JAVA_HOME
JAVA_HOME
origin shell-file
primary ~/helpers.sh:3
chain ~/.zshrc → ~/helpers.sh
writers
~/.zshenv:8
~/helpers.sh:3 (winner)
value [hidden, use --values]
Одной строкой (определяет ОС/архитектуру, кладёт бинарник в ваш $PATH, снимает Gatekeeper на macOS):
curl -fsSL https://raw.githubusercontent.com/sreckoskocilic/envocabulary/main/install.sh | sh
Или go install github.com/sreckoskocilic/envocabulary/cmd/envocabulary@latest. Готовые бинарники и пакеты для Linux (.deb / .rpm / .apk / .pkg.tar.zst) доступны на странице релизов.
Живое окружение (анализирует вашу работающую оболочку):
scan (по умолчанию) — выводит все переменные текущего окружения, сгруппированные по источникуexplain NAME — выводит полную атрибуцию для указанной переменнойpath [VARNAME...] — по элементная атрибуция для переменных-путей, разделённых двоеточием; --check находит мёртвые записиСтатические файлы:
inventory — перечисляет все конфигурационные файлы оболочки и подсчитывает определения по типамcatalog — выводит всю конфигурацию оболочки, объединяя все её конфигурационные файлыdedup — отчёт о дубликатах между файлами для exports, assigns, aliases, functionsdangling — перечисляет записи конфигурационных файлов, которые больше не ссылаются на валидную цельlost — перечисляет определения, уникальные для осиротевших/резервных конфигурационных файловreport — объединённый аудит: безопасные к удалению, на проверку (дубликаты с изменённым значением), висячие, осиротевшие файлы; --html записывает файл .html с отметкой времени в текущий каталогclean [--full] FILE — выводит строки, которые следует удалить; с --full печатает полное очищенное содержимоеПрочее:
-V, --version — вывести версию, коммит и дату сборкиenvocabulary <cmd> -h — для получения списка флагов.
В примерах ниже используется ~/ для краткости; инструмент печатает абсолютные пути везде, кроме report.
dangling перечисляет записи конфигурационных файлов, которые больше не ссылаются на валидную цель, — такие остатки, как JAVA_HOME=/opt/jdk-i-uninstalled и source ~/dotfiles/work-old.zsh:
$ envocabulary dangling
## ~/.zshrc
~/.zshrc:14 source → ~/dotfiles/work-old.zsh (source target missing)
~/.zshrc:42 export JAVA_HOME → /opt/jdk-11 (path does not exist)
path показывает, где была добавлена каждая запись в PATH (или MANPATH, FPATH и т. д.):
$ envocabulary path PATH
## PATH
/opt/homebrew/bin ~/.zprofile:21
/usr/local/bin ~/.zprofile:1
/usr/bin /etc/zprofile:1
/bin /etc/zprofile:1
/usr/sbin /etc/zprofile:1
/sbin /etc/zprofile:1
~/.cargo/bin ~/.zshrc:22
Записи, не сопоставленные ни с одним присваиванием при старте оболочки, показываются как inherited.
--check отфильтровывает записи, чей каталог больше не существует, и прослеживает их до конфигурационного файла, который нужно отредактировать:
$ envocabulary path --check PATH
## PATH
/opt/homebrew/Cellar/go/1.25.1/libexec/bin ~/.zshrc:17 (does not exist)
/opt/pkg/env/active/bin /etc/paths.d/10-pmk-global:1 (does not exist)
/Applications/VMware /etc/paths.d/com.vmware.fusion.public:1 (does not exist)
Завершается с кодом 1, если найдены мёртвые записи (удобно в скриптах).
export EDITOR=vim VISUAL=vim фиксирует только EDITOR).dangling не разрешает выражения вида PATH или подстановки (export GOPATH=$HOME/go).path основана на diff трассировки xtrace — первое присваивание, включающее запись, объявляет её своей, даже если она была перенесена через раскрытие $PATH, а не добавлена явно.envocabulary никогда не будет выполнять unset, rm или редактировать ваш конфиг оболочки. Аварийный инструмент не должен усугублять аварию. Если хотите навести порядок, скопируйте указатели file:line и сделайте правки сами. clean выводит результат в stdout; перенаправление делаете вы.