
envocabulary v1.0.5
Rastreie cada variável de ambiente do shell até a origem exata em arquivo e linha. Audite as configurações do shell em busca de entradas mortas, duplicatas e arquivos órfãos em zsh e bash no macOS, Linux e FreeBSD.
envocabulary
Para cada variável no seu shell atual, encontre o arquivo e a linha que a definiu, ou qual subsistema (direnv, launchd, terminal, SSH, sistema) a injetou. Além disso, alguns comandos para arquivos estáticos para o momento em que sua configuração de shell se espalhou por N arquivos e backups e você perdeu o fio da meada.
Eu construí isso porque eu continuava perdendo a mesma hora a cada poucos meses rastreando por que algum JAVA_HOME ou PATH estava apontando para algum lugar que eu não esperava. O which conhece comandos, o direnv status conhece o direnv, o launchctl getenv conhece o launchd. Nenhum deles te diz que ~/.zshrc:42 é o verdadeiro autor.
Funciona com zsh e bash no macOS, Linux e FreeBSD. A saída de exemplo abaixo usa ~/ por brevidade; a ferramenta imprime caminhos absolutos em todos os lugares, exceto em report.
O momento "ah"
grep -r JAVA_HOME ~ mostra todos os arquivos que mencionam a variável. Ele não te diz qual atribuição venceu no shell em que você está sentado:
$ 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]
Variáveis definidas através de eval "$(brew shellenv)", eval "$(pyenv init -)" e similares apontam para a linha do eval. O código gerado não tem uma linha própria; o eval é o que você pode abrir em um editor.
Instalação
curl -fsSL https://raw.githubusercontent.com/sreckoskocilic/envocabulary/main/install.sh | sh
O script detecta o SO e a arquitetura, baixa o arquivo de release, verifica seu checksum sha256 e verifica a assinatura cosign quando o cosign está instalado. Ele instala em /usr/local/bin se isso for gravável, caso contrário em ~/.local/bin, e avisa se esse diretório não estiver no seu $PATH. No macOS ele também limpa a flag de quarentena do Gatekeeper.
Opções: sh -s -- --version v1.0.4 para fixar uma versão, --bin-dir DIR para escolher o destino.
Ou go install github.com/sreckoskocilic/envocabulary/cmd/envocabulary@latest. Note que uma build de go install reporta dev para --version; apenas binários de release carregam a versão, o commit e a data de build.
Binários pré-compilados e pacotes Linux (.deb / .rpm / .apk / .pkg.tar.zst) estão na página de releases.
Comandos
Env ao vivo (lê o seu shell em execução):
scan(padrão) — imprime todas as variáveis no env atual agrupadas por origemexplain NAME— atribuição completa para uma variávelpath [VARNAME...]— atribuição por entrada para variáveis de caminho separadas por dois-pontos;--checkencontra entradas mortas
Arquivos estáticos:
inventory— lista os arquivos de configuração de shell em$HOME(os canônicos mais variantes de backup como.zshrc.bak) e conta definições por tipocatalog— imprime esses arquivos concatenados na ordem em que o shell os lêdedup— relatório de duplicatas para exports, assigns, aliases, funções, dentro e entre arquivosdangling— lista entradas de configuração cujo alvo não existe mais; sai com 1 quando encontra algumalost— lista definições que existem apenas em arquivos órfãos/backupreport— auditoria combinada: seguro para deletar, revisar (duplicatas cujo valor difere, mais todas as funções duplicadas), dangling, arquivos órfãos;--htmlescreve um arquivo.htmlcom timestamp no diretório atualclean [--full] FILE— lista linhas de comentário que seriam removidas; com--full, imprime o conteúdo limpo
Outros:
-V,--version— imprime versão, commit e data de build
envocabulary <cmd> -h para flags.
Códigos de saída: 0 em caso de sucesso, 1 em caso de erro de execução ou quando dangling / path --check encontram algo, 2 em caso de erro de uso.
Encontrando referências quebradas
dangling lista entradas de configuração que não apontam mais para nada, do tipo JAVA_HOME=/opt/jdk-i-uninstalled e 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)
Rastreando entradas do PATH
path mostra onde cada entrada em PATH (ou MANPATH, FPATH, etc.) foi introduzida:
$ 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
Entradas não correspondidas a nenhuma atribuição de inicialização de shell aparecem como inherited. Isso sempre inclui /usr/bin, /bin, /usr/sbin e /sbin: eles são a semente da qual o rastreador parte, não algo que um arquivo adicionou.
--check filtra para entradas cujo diretório não existe mais e re-resolve a origem contra seus dotfiles e /etc/paths.d, para que aponte para a linha a editar:
$ 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)
Sai com 1 quando entradas mortas são encontradas, o que o torna utilizável em scripts.
Limitações
- Uma atribuição por linha:
export EDITOR=vim VISUAL=vimregistra apenasEDITOR. - Os comandos estáticos olham apenas para os dotfiles canônicos em
$HOME(.zshenv,.zprofile,.zshrc,.zlogin,.zlogout,.bashrc,.bash_profile,.profile) e suas variantes no estilo.bak/.old. Eles não seguem$ZDOTDIR,~/.config/zsh,/etc, ou arquivos que você fazsource. danglingignora valores do tipo PATH e qualquer coisa com uma expansão neles (export GOPATH=$HOME/go); ele não consegue resolvê-los estaticamente.- A atribuição de
pathé baseada em diffs de xtrace. A primeira atribuição que inclui uma entrada a reivindica, mesmo que ela tenha sido carregada adiante via expansão de$PATHem vez de explicitamente adicionada. - Sob bash, código executado através de
evalreporta a linha doevalmais um offset; o bash não tem um marcador para corpos de eval como o zsh tem. - Shells não suportados: fish, nu, csh/tcsh, PowerShell.
Somente leitura por design
envocabulary nunca vai unset, rm ou editar sua configuração de shell. Uma ferramenta de emergência não deveria ser a coisa que piora a emergência. Se você quiser limpar as coisas, copie os ponteiros file:line e faça as edições você mesmo. clean imprime para stdout; você faz o redirecionamento.