Назад к обновлениям
New releaseSep 16, 2026

envocabulary v1.0.5

Отслеживайте каждую переменную окружения оболочки до её точного источника: файла и строки. Проверяйте конфигурации оболочек на наличие мёртвых записей, дубликатов и осиротевших файлов в zsh и bash на macOS, Linux и FreeBSD.

Поделиться

envocabulary

CI codecov Release

Для каждой переменной в вашей текущей оболочке находит файл и строку, которые её задали, или определяет, какая подсистема (direnv, launchd, терминал, SSH, система) её внедрила. Плюс несколько команд для статических файлов на тот случай, когда конфигурация вашей оболочки расползлась по N файлам и бэкапам, и вы потеряли нить.

Я создал это, потому что каждые несколько месяцев терял один и тот же час, выясняя, почему какой-нибудь JAVA_HOME или PATH указывает куда-то, где я не ожидал. which знает команды, direnv status знает direnv, launchctl getenv знает launchd. Ни одна из них не скажет вам, что ~/.zshrc:42 — это фактический источник.

Работает с zsh и bash на macOS, Linux и FreeBSD. В примерах вывода ниже используется ~/ для краткости; инструмент везде печатает абсолютные пути, кроме report.

Момент «ага»

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]

Переменные, заданные через eval "$(brew shellenv)", eval "$(pyenv init -)" и подобные, указывают на строку eval. У сгенерированного кода нет собственной строки; eval — это то, что вы можете открыть в редакторе.

Установка

curl -fsSL https://raw.githubusercontent.com/sreckoskocilic/envocabulary/main/install.sh | sh

Скрипт определяет ОС и архитектуру, скачивает архив релиза, проверяет его контрольную сумму sha256 и проверяет подпись cosign, если установлен cosign. Он устанавливает в /usr/local/bin, если туда есть доступ на запись, иначе в ~/.local/bin, и предупреждает, если этот каталог отсутствует в вашем $PATH. На macOS он также снимает флаг карантина Gatekeeper.

Опции: sh -s -- --version v1.0.4 для фиксации версии, --bin-dir DIR для выбора места назначения.

Или go install github.com/sreckoskocilic/envocabulary/cmd/envocabulary@latest. Учтите, что сборка через go install сообщает dev для --version; только релизные бинарники несут версию, коммит и дату сборки.

Готовые бинарники и пакеты для Linux (.deb / .rpm / .apk / .pkg.tar.zst) находятся на странице релизов.

Команды

Живое окружение (читает вашу запущенную оболочку):

  • scan (по умолчанию) — печатает все переменные в текущем окружении, сгруппированные по источнику
  • explain NAME — полная атрибуция для одной переменной
  • path [VARNAME...] — атрибуция по каждой записи для переменных с путями, разделёнными двоеточием; --check находит мёртвые записи

Статические файлы:

  • inventory — перечисляет файлы конфигурации оболочки в $HOME (канонические плюс варианты бэкапов вроде .zshrc.bak) и подсчитывает определения по типу
  • catalog — печатает эти файлы, объединённые в порядке, в котором их читает оболочка
  • dedup — отчёт о дубликатах для exports, assigns, aliases, functions, внутри и между файлами
  • dangling — перечисляет записи конфигурации, чья цель больше не существует; завершается с кодом 1, когда что-либо находит
  • lost — перечисляет определения, которые существуют только в осиротевших/бэкапных файлах
  • report — комбинированный аудит: безопасно удалить, проверить (дубликаты, чьи значения различаются, плюс все дублирующиеся функции), висячие ссылки, осиротевшие файлы; --html записывает файл .html с отметкой времени в текущий каталог
  • clean [--full] FILE — перечисляет строки комментариев, которые были бы удалены; с --full печатает очищенное содержимое

Прочее:

  • -V, --version — печатает версию, коммит и дату сборки

envocabulary <cmd> -h для флагов.

Коды выхода: 0 при успехе, 1 при ошибке времени выполнения или когда dangling / path --check что-то находят, 2 при ошибке использования.

Поиск сломанных ссылок

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 показывает, где была добавлена каждая запись в PATH (или MANPATH, FPATH и т. д.):

$ envocabulary path PATH
## PATH
  /opt/homebrew/bin       ~/.zprofile:6
  /opt/homebrew/sbin      ~/.zprofile:6
  /usr/local/bin          /etc/zprofile:11
  /usr/bin                inherited
  /bin                    inherited
  ~/.cargo/bin            ~/.zshrc:22

Записи, не сопоставленные ни с каким присваиванием при запуске оболочки, отображаются как inherited. Это всегда включает /usr/bin, /bin, /usr/sbin и /sbin: они — начальное значение, с которого начинает трассировщик, а не то, что добавил какой-то файл.

--check фильтрует до записей, чей каталог больше не существует, и заново определяет источник по вашим dotfiles и /etc/paths.d, так что указывает на строку для редактирования:

$ 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.
  • Статические команды смотрят только на канонические dotfiles в $HOME (.zshenv, .zprofile, .zshrc, .zlogin, .zlogout, .bashrc, .bash_profile, .profile) и их варианты в стиле .bak/.old. Они не следуют за $ZDOTDIR, ~/.config/zsh, /etc или файлами, которые вы подключаете через source.
  • dangling пропускает значения, похожие на PATH, и всё, что содержит раскрытие (export GOPATH=$HOME/go); он не может разрешить их статически.
  • Атрибуция path основана на diff'ах xtrace. Первое присваивание, включающее запись, присваивает её себе, даже если она была перенесена через раскрытие $PATH, а не добавлена явно.
  • В bash код, выполненный через eval, сообщает строку eval плюс смещение; в bash нет маркера для тел eval, как в zsh.
  • Неподдерживаемые оболочки: fish, nu, csh/tcsh, PowerShell.

Только для чтения по замыслу

envocabulary никогда не выполнит unset, rm или редактирование вашей конфигурации оболочки. Аварийный инструмент не должен быть тем, что усугубляет аварию. Если вы хотите что-то почистить, скопируйте указатели file:line и сделайте правки сами. clean выводит в stdout; перенаправление делаете вы.

Категории