Voltar às atualizações
New releaseSep 16, 2026

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.

Compartilhar

envocabulary

CI codecov Release

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 origem
  • explain NAME — atribuição completa para uma variável
  • path [VARNAME...] — atribuição por entrada para variáveis de caminho separadas por dois-pontos; --check encontra 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 tipo
  • catalog — 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 arquivos
  • dangling — lista entradas de configuração cujo alvo não existe mais; sai com 1 quando encontra alguma
  • lost — lista definições que existem apenas em arquivos órfãos/backup
  • report — auditoria combinada: seguro para deletar, revisar (duplicatas cujo valor difere, mais todas as funções duplicadas), dangling, arquivos órfãos; --html escreve um arquivo .html com timestamp no diretório atual
  • clean [--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=vim registra apenas EDITOR.
  • 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ê faz source.
  • dangling ignora 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 $PATH em vez de explicitamente adicionada.
  • Sob bash, código executado através de eval reporta a linha do eval mais 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.

Categorias