업데이트로 돌아가기
New releaseSep 16, 2026

envocabulary v1.0.5

모든 셸 환경 변수에 대해 정확한 파일 및 줄 출처를 추적합니다. macOS, Linux, FreeBSD의 zsh 및 bash에서 셸 설정 파일을 감사하여 죽은 항목, 중복, 고아 파일을 찾아냅니다.

공유

envocabulary

CI codecov Release

현재 셸에 있는 모든 변수에 대해, 그 변수를 설정한 파일과 줄 번호를 찾아주거나, 어떤 하위 시스템(direnv, launchd, 터미널, SSH, 시스템)이 주입했는지 알려줍니다. 또한 셸 설정이 N개의 파일과 백업으로 흩어져 더 이상 파악이 안 될 때를 위한 몇 가지 정적 파일 명령도 제공합니다.

이 도구를 만든 이유는 몇 달에 한 번씩 JAVA_HOME이나 PATH가 예상치 못한 곳을 가리키는 이유를 추적하다가 매번 같은 시간을 낭비했기 때문입니다. which는 명령어를 알고, direnv status는 direnv를 알고, launchctl getenv는 launchd를 압니다. 하지만 그중 어느 것도 ~/.zshrc:42가 실제 작성자라는 사실을 알려주지 않습니다.

macOS, Linux, FreeBSD에서 zsh와 bash를 지원합니다. 아래 샘플 출력은 간결함을 위해 ~/를 사용하지만, 도구는 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

이 스크립트는 OS와 아키텍처를 감지하고, 릴리스 아카이브를 다운로드하며, 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 빌드는 --version에 대해 dev를 보고한다는 점에 유의하세요. 릴리스 바이너리만 버전, 커밋, 빌드 날짜를 포함합니다.

미리 빌드된 바이너리와 Linux 패키지(.deb / .rpm / .apk / .pkg.tar.zst)는 릴리스 페이지에 있습니다.

명령어

라이브 환경(실행 중인 셸을 읽음):

  • scan (기본값) — 현재 환경의 모든 변수를 origin별로 그룹화하여 출력
  • explain NAME — 하나의 변수에 대한 전체 출처 정보
  • path [VARNAME...] — 콜론으로 구분된 경로 변수의 항목별 출처 정보; --check는 죽은 항목을 찾음

정적 파일:

  • inventory$HOME에 있는 셸 설정 파일(정식 파일과 .zshrc.bak 같은 백업 변형)을 나열하고 유형별로 정의 개수를 집계
  • catalog — 셸이 읽는 순서대로 해당 파일들을 이어붙여 출력
  • dedup — 파일 내 및 파일 간의 export, assign, alias, function에 대한 중복 보고서
  • dangling — 대상이 더 이상 존재하지 않는 설정 항목을 나열; 발견 시 종료 코드 1
  • lost — 고아/백업 파일에만 존재하는 정의를 나열
  • report — 통합 감사: 삭제해도 안전한 것, 검토 필요(값이 다른 중복, 모든 중복 함수), dangling, 고아 파일; --html은 현재 디렉터리에 타임스탬프가 붙은 .html 파일을 작성
  • clean [--full] FILE — 제거될 주석 줄을 나열; --full을 사용하면 정리된 내용을 출력

기타:

  • -V, --version — 버전, 커밋, 빌드 날짜 출력

플래그는 envocabulary <cmd> -h를 참조하세요.

종료 코드: 성공 시 0, 런타임 오류 또는 dangling / path --check가 무언가를 발견했을 때 1, 사용법 오류 시 2.

깨진 참조 찾기

dangling은 더 이상 아무것도 가리키지 않는 설정 항목, 즉 JAVA_HOME=/opt/jdk-i-uninstalledsource ~/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 항목 추적

pathPATH(또는 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=vimEDITOR만 기록합니다.
  • 정적 명령은 $HOME의 정식 dotfile(.zshenv, .zprofile, .zshrc, .zlogin, .zlogout, .bashrc, .bash_profile, .profile)과 그 .bak/.old 스타일 변형만 봅니다. $ZDOTDIR, ~/.config/zsh, /etc, 또는 source한 파일은 따라가지 않습니다.
  • dangling은 PATH 같은 값과 확장이 포함된 것(export GOPATH=$HOME/go)은 건너뜁니다. 이런 것들은 정적으로 확인할 수 없습니다.
  • path 출처 정보는 xtrace diff를 기반으로 합니다. 항목을 포함하는 첫 번째 할당이 그 항목을 차지하며, 명시적으로 추가된 것이 아니라 $PATH 확장을 통해 이어져 온 경우에도 마찬가지입니다.
  • bash에서는 eval을 통해 실행된 코드가 eval 줄과 오프셋을 보고합니다. bash에는 zsh처럼 eval 본문에 대한 마커가 없습니다.
  • 지원하지 않는 셸: fish, nu, csh/tcsh, PowerShell.

설계상 읽기 전용

envocabulary는 절대 unset, rm, 또는 셸 설정을 편집하지 않습니다. 비상 도구가 비상 상황을 더 악화시키는 원인이 되어서는 안 됩니다. 정리를 원한다면 file:line 포인터를 복사해서 직접 편집하세요. clean은 stdout으로 출력하며, 리다이렉션은 직접 하시면 됩니다.

카테고리