In the daily basis, we run a lot of the scripts of npm packages like nx, biome, eslint etc…

Jetbrains IDEs supports auto-injection of node_modules/.bin into their inner terminal automatically and this is a charm feature.

We can imitate this with some shell scripts into our .zshrc

SpecsPermalink

  • search package root upside until .git or package.json is founded.
  • deallocate bin path from PATH if it doesn’t valid anymore(change directory to outside of project)

CodePermalink

Copy the following into your .zshrc

Happy Coding!

# Auto add node_modules/.bin into PATH

# 1) Declare a global variable to store the previously added pm bin path
typeset -g ZPM_BIN=""

# 2) Helper to locate package.json up to the Git top-level directory
_locate_pkg() {
  local dir=$1 top
  # get Git repository root, or fail
  top=$(git rev-parse --show-toplevel 2>/dev/null) || return 1
  # traverse from current dir up to the Git root
  while [[ $dir != $top && $dir != "/" ]]; do
    [[ -f $dir/package.json ]] && { echo "$dir"; return 0; }
    dir=${dir%/*}
  done
  # check at the Git root
  [[ -f $top/package.json ]] && echo "$top" && return 0
  return 1
}

# 3) Function to update PATH with the project’s local bin
update_pm_bin() {
  # 3-1) Remove the previously added bin directory from PATH
  if [[ -n $ZPM_BIN ]]; then
    path=( ${path:#$ZPM_BIN} )
    ZPM_BIN=""
  fi

  # 3-2) Find the directory containing package.json
  local root bin_dir
  root=$(_locate_pkg "$PWD") || return

  # 3-3) Determine which package manager is in use and set bin_dir
  if [[ -f $root/pnpm-lock.yaml ]]; then
    bin_dir=$(pnpm --prefix "$root" bin)
  elif [[ -f $root/yarn.lock ]]; then
    bin_dir=$(yarn --cwd "$root" bin)
  elif [[ -f $root/bun.lockb ]]; then
    bin_dir="$root/node_modules/.bin"
  else
    bin_dir=$(npm --prefix "$root" bin)
  fi

  # 3-4) If bin_dir exists, prepend it to PATH and record it
  [[ -d $bin_dir ]] || return
  path=( $bin_dir $path )
  ZPM_BIN=$bin_dir
}

# 4) Register hook to run on directory change, and run once at shell startup
autoload -U add-zsh-hook
add-zsh-hook chpwd update_pm_bin
update_pm_bin

Tags:

Categories:

Updated:

Comments