Zurück zu den Updates
New releaseSep 16, 2026

envocabulary v1.0.5

Verfolge jede Shell-Umgebungsvariable bis zu ihrem genauen Datei- und Zeilenursprung. Prüfe Shell-Konfigurationen auf tote Einträge, Duplikate und verwaiste Dateien in zsh und bash unter macOS, Linux und FreeBSD.

Teilen

envocabulary

CI codecov Release

Finde für jede Variable in deiner aktuellen Shell die Datei und Zeile, die sie gesetzt hat, oder welches Subsystem (direnv, launchd, Terminal, SSH, System) sie injiziert hat. Dazu ein paar Befehle für statische Dateien für den Moment, in dem deine Shell-Konfiguration über N Dateien und Backups verstreut ist und du den Überblick verloren hast.

Ich habe das gebaut, weil ich alle paar Monate dieselbe Stunde damit verbracht habe, nachzuvollziehen, warum irgendein JAVA_HOME oder PATH auf etwas zeigte, das ich nicht erwartet hatte. which kennt Befehle, direnv status kennt direnv, launchctl getenv kennt launchd. Keines davon sagt dir, dass ~/.zshrc:42 der tatsächliche Verursacher ist.

Funktioniert mit zsh und bash auf macOS, Linux und FreeBSD. Die Beispielausgabe unten verwendet ~/ der Kürze wegen; das Tool gibt überall absolute Pfade aus, außer bei report.

Der „Aha"-Moment

grep -r JAVA_HOME ~ zeigt jede Datei, die die Variable erwähnt. Es sagt dir nicht, welche Zuweisung in der Shell, in der du gerade sitzt, gewonnen hat:

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

Variablen, die durch eval "$(brew shellenv)", eval "$(pyenv init -)" und ähnliches gesetzt werden, zeigen auf die eval-Zeile. Der generierte Code hat keine eigene Zeile; das eval ist das, was du in einem Editor öffnen kannst.

Installation

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

Das Skript erkennt OS und Architektur, lädt das Release-Archiv herunter, verifiziert dessen sha256-Prüfsumme und verifiziert die cosign-Signatur, wenn cosign installiert ist. Es installiert nach /usr/local/bin, wenn dieses beschreibbar ist, andernfalls nach ~/.local/bin, und warnt, wenn dieses Verzeichnis nicht in deinem $PATH liegt. Unter macOS löscht es außerdem das Gatekeeper-Quarantäne-Flag.

Optionen: sh -s -- --version v1.0.4, um eine Version festzulegen, --bin-dir DIR, um das Zielverzeichnis zu wählen.

Oder go install github.com/sreckoskocilic/envocabulary/cmd/envocabulary@latest. Beachte, dass ein go install-Build für --version dev meldet; nur Release-Binaries tragen die Version, den Commit und das Build-Datum.

Vorgefertigte Binaries und Linux-Pakete (.deb / .rpm / .apk / .pkg.tar.zst) findest du auf der Releases-Seite.

Befehle

Live-Umgebung (liest deine laufende Shell):

  • scan (Standard) — gibt alle Variablen in der aktuellen Umgebung gruppiert nach Ursprung aus
  • explain NAME — vollständige Zuordnung für eine Variable
  • path [VARNAME...] — Zuordnung pro Eintrag für doppelpunktgetrennte Pfadvariablen; --check findet tote Einträge

Statische Dateien:

  • inventory — listet die Shell-Konfigurationsdateien in $HOME auf (die kanonischen plus Backup-Varianten wie .zshrc.bak) und zählt Definitionen nach Typ
  • catalog — gibt diese Dateien aneinandergehängt in der Reihenfolge aus, in der die Shell sie liest
  • dedup — Duplikatbericht für exports, assigns, aliases, functions, innerhalb und über Dateien hinweg
  • dangling — listet Konfigurationseinträge auf, deren Ziel nicht mehr existiert; beendet mit 1, wenn welche gefunden werden
  • lost — listet Definitionen auf, die nur in verwaisten/Backup-Dateien existieren
  • report — kombiniertes Audit: sicher zu löschen, prüfen (Duplikate mit abweichendem Wert, plus alle doppelten Funktionen), dangling, verwaiste Dateien; --html schreibt eine zeitgestempelte .html-Datei in das aktuelle Verzeichnis
  • clean [--full] FILE — listet Kommentarzeilen auf, die entfernt würden; mit --full wird der bereinigte Inhalt ausgegeben

Sonstiges:

  • -V, --version — gibt Version, Commit und Build-Datum aus

envocabulary <cmd> -h für Flags.

Exit-Codes: 0 bei Erfolg, 1 bei einem Laufzeitfehler oder wenn dangling / path --check etwas finden, 2 bei einem Nutzungsfehler.

Kaputte Referenzen finden

dangling listet Konfigurationseinträge auf, die auf nichts mehr zeigen, die Art von Überbleibseln wie JAVA_HOME=/opt/jdk-i-uninstalled und 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-Einträge nachverfolgen

path zeigt, wo jeder Eintrag in PATH (oder MANPATH, FPATH usw.) eingeführt wurde:

$ 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

Einträge, die keiner Shell-Startup-Zuweisung zugeordnet werden können, erscheinen als inherited. Das umfasst immer /usr/bin, /bin, /usr/sbin und /sbin: Sie sind der Ausgangspunkt, von dem der Tracer startet, nicht etwas, das eine Datei hinzugefügt hat.

--check filtert auf Einträge, deren Verzeichnis nicht mehr existiert, und löst die Quelle erneut gegen deine Dotfiles und /etc/paths.d auf, sodass es auf die zu bearbeitende Zeile zeigt:

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

Beendet mit 1, wenn tote Einträge gefunden werden, was es in Skripten nutzbar macht.

Einschränkungen

  • Eine Zuweisung pro Zeile: export EDITOR=vim VISUAL=vim erfasst nur EDITOR.
  • Die statischen Befehle betrachten nur die kanonischen Dotfiles in $HOME (.zshenv, .zprofile, .zshrc, .zlogin, .zlogout, .bashrc, .bash_profile, .profile) und deren Varianten im Stil .bak/.old. Sie folgen weder $ZDOTDIR, ~/.config/zsh, /etc noch Dateien, die du sourcest.
  • dangling überspringt PATH-artige Werte und alles mit einer Expansion darin (export GOPATH=$HOME/go); diese kann es statisch nicht auflösen.
  • Die path-Zuordnung basiert auf xtrace-Diffs. Die erste Zuweisung, die einen Eintrag enthält, beansprucht ihn, selbst wenn er über eine $PATH-Expansion weitergetragen statt explizit hinzugefügt wurde.
  • Unter bash meldet Code, der durch eval ausgeführt wird, die eval-Zeile plus einen Offset; bash hat keinen Marker für eval-Körper wie zsh.
  • Nicht unterstützte Shells: fish, nu, csh/tcsh, PowerShell.

Von Grund auf schreibgeschützt

envocabulary wird niemals deine Shell-Konfiguration unseten, rmen oder bearbeiten. Ein Notfallwerkzeug sollte nicht das sein, was den Notfall verschlimmert. Wenn du aufräumen möchtest, kopiere die file:line-Verweise und nimm die Änderungen selbst vor. clean gibt nach stdout aus; die Umleitung machst du.

Kategorien