Retour aux mises à jour
New releaseSep 16, 2026

envocabulary v1.0.5

Tracez chaque variable d'environnement shell jusqu'à son fichier et sa ligne d'origine exacts. Auditez les configurations shell pour repérer les entrées mortes, les doublons et les fichiers orphelins sur zsh et bash sous macOS, Linux et FreeBSD.

Partager

envocabulary

CI codecov Release

Pour chaque variable de votre shell actuel, trouvez le fichier et la ligne qui l'ont définie, ou quel sous-système (direnv, launchd, terminal, SSH, système) l'a injectée. Plus quelques commandes pour fichiers statiques, pour le moment où votre configuration shell s'est éparpillée sur N fichiers et sauvegardes et où vous avez perdu le fil.

J'ai créé cet outil parce que je perdais la même heure tous les quelques mois à retracer pourquoi un JAVA_HOME ou un PATH pointait vers un endroit inattendu. which connaît les commandes, direnv status connaît direnv, launchctl getenv connaît launchd. Aucun d'eux ne vous dit que ~/.zshrc:42 est le véritable auteur de l'assignation.

Fonctionne avec zsh et bash sur macOS, Linux et FreeBSD. Les exemples de sortie ci-dessous utilisent ~/ par souci de concision ; l'outil affiche des chemins absolus partout sauf pour report.

Le moment « ah »

grep -r JAVA_HOME ~ affiche tous les fichiers qui mentionnent la variable. Cela ne vous dit pas quelle assignation a gagné dans le shell où vous êtes assis :

$ 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]

Les variables définies via eval "$(brew shellenv)", eval "$(pyenv init -)" et compagnie pointent vers la ligne eval. Le code généré n'a pas de ligne propre ; l'eval est ce que vous pouvez ouvrir dans un éditeur.

Installation

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

Le script détecte l'OS et l'architecture, télécharge l'archive de la release, vérifie sa somme de contrôle sha256, et vérifie la signature cosign lorsque cosign est installé. Il installe dans /usr/local/bin si ce répertoire est accessible en écriture, sinon dans ~/.local/bin, et avertit si ce répertoire n'est pas dans votre $PATH. Sur macOS, il efface aussi le drapeau de quarantaine de Gatekeeper.

Options : sh -s -- --version v1.0.4 pour épingler une version, --bin-dir DIR pour choisir la destination.

Ou go install github.com/sreckoskocilic/envocabulary/cmd/envocabulary@latest. Notez qu'une compilation via go install indique dev pour --version ; seuls les binaires de release portent la version, le commit et la date de compilation.

Les binaires précompilés et les paquets Linux (.deb / .rpm / .apk / .pkg.tar.zst) sont sur la page des releases.

Commandes

Env actif (lit votre shell en cours d'exécution) :

  • scan (par défaut) — affiche toutes les variables de l'env actuel groupées par origine
  • explain NAME — attribution complète pour une variable
  • path [VARNAME...] — attribution par entrée pour les variables de chemin séparées par des deux-points ; --check trouve les entrées mortes

Fichiers statiques :

  • inventory — liste les fichiers de configuration shell dans $HOME (les canoniques plus les variantes de sauvegarde comme .zshrc.bak) et compte les définitions par type
  • catalog — affiche ces fichiers concaténés dans l'ordre où le shell les lit
  • dedup — rapport des doublons pour les exports, assignations, alias, fonctions, au sein d'un fichier et entre fichiers
  • dangling — liste les entrées de configuration dont la cible n'existe plus ; se termine avec le code 1 lorsqu'il en trouve
  • lost — liste les définitions qui n'existent que dans des fichiers orphelins/de sauvegarde
  • report — audit combiné : sûr à supprimer, à vérifier (doublons dont la valeur diffère, plus toutes les fonctions dupliquées), références mortes, fichiers orphelins ; --html écrit un fichier .html horodaté dans le répertoire courant
  • clean [--full] FILE — liste les lignes de commentaire qui seraient supprimées ; avec --full, affiche le contenu nettoyé

Autres :

  • -V, --version — affiche la version, le commit et la date de compilation

envocabulary <cmd> -h pour les options.

Codes de sortie : 0 en cas de succès, 1 en cas d'erreur d'exécution ou lorsque dangling / path --check trouvent quelque chose, 2 en cas d'erreur d'utilisation.

Trouver les références cassées

dangling liste les entrées de configuration qui ne pointent plus vers rien, du genre JAVA_HOME=/opt/jdk-i-uninstalled et 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)

Tracer les entrées de PATH

path montre où chaque entrée de PATH (ou MANPATH, FPATH, etc.) a été introduite :

$ 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

Les entrées qui ne correspondent à aucune assignation de démarrage du shell apparaissent comme inherited. Cela inclut toujours /usr/bin, /bin, /usr/sbin et /sbin : ils constituent la graine à partir de laquelle le traceur démarre, et non quelque chose qu'un fichier a ajouté.

--check filtre pour ne garder que les entrées dont le répertoire n'existe plus et re-résout la source par rapport à vos dotfiles et à /etc/paths.d, afin de pointer vers la ligne à modifier :

$ 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)

Se termine avec le code 1 lorsque des entrées mortes sont trouvées, ce qui le rend utilisable dans des scripts.

Limites

  • Une assignation par ligne : export EDITOR=vim VISUAL=vim n'enregistre que EDITOR.
  • Les commandes statiques ne regardent que les dotfiles canoniques dans $HOME (.zshenv, .zprofile, .zshrc, .zlogin, .zlogout, .bashrc, .bash_profile, .profile) et leurs variantes de type .bak/.old. Elles ne suivent pas $ZDOTDIR, ~/.config/zsh, /etc, ni les fichiers que vous source.
  • dangling ignore les valeurs de type PATH et tout ce qui contient une expansion (export GOPATH=$HOME/go) ; il ne peut pas les résoudre statiquement.
  • L'attribution de path est basée sur des diffs xtrace. La première assignation qui inclut une entrée la revendique, même si elle a été transmise via une expansion de $PATH plutôt qu'ajoutée explicitement.
  • Sous bash, le code exécuté via eval indique la ligne eval plus un décalage ; bash n'a pas de marqueur pour les corps d'eval comme zsh.
  • Shells non pris en charge : fish, nu, csh/tcsh, PowerShell.

En lecture seule par conception

envocabulary ne fera jamais unset, rm ou ne modifiera votre configuration shell. Un outil d'urgence ne devrait pas être ce qui aggrave l'urgence. Si vous voulez nettoyer les choses, copiez les pointeurs file:line et faites les modifications vous-même. clean écrit sur stdout ; c'est vous qui faites la redirection.

Catégories