Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

run `nvm use` automatically every time there's a .nvmrc file on the directory

People also ask

What is .nvmrc file?

nvmrc file containing a node version number in your project. You can use the nvm —-help to check other options. After that you can simply run commands like nvm use, nvm install and nvm run etc. This will the default node. js version defined in .

How do I make node default with NVM?

Just type nvm alias default v10. 16.3 in your terminal and then type nvm use default . This command will make v10. 16.3 available in any shell you open — you just have to restart your terminal to make sure it works.

What is NVM Noinstall?

The Node Version Manager (NVM) is an open source version manager for Node. js (Node). NVM is easy to install and understand, and works on any POSIX-compliant shell (for example, sh or bash). NVM allows you to easily install and manage different versions of Node and switch between them on a per-shell basis.

How do I change NVM version?

Switching among Node. 7; we can simply run either nvm use 12.22. 7 or nvm use 16.13. 0 to easily switch into either version we need. Note that since we only have one version that begins with 12, 14, or 16, we can switch versions with a simple nvm use 16 , nvm use 14 , or nvm use 12 command.


If you use zsh (z shell):

Calling 'nvm use' automatically in a directory with a .nvmrc file

Put this into your $HOME/.zshrc to call nvm use automatically whenever you enter a directory that contains an .nvmrc file with a string telling nvm which node to use:

# place this after nvm initialization!
autoload -U add-zsh-hook
load-nvmrc() {
  local node_version="$(nvm version)"
  local nvmrc_path="$(nvm_find_nvmrc)"

  if [ -n "$nvmrc_path" ]; then
    local nvmrc_node_version=$(nvm version "$(cat "${nvmrc_path}")")

    if [ "$nvmrc_node_version" = "N/A" ]; then
      nvm install
    elif [ "$nvmrc_node_version" != "$node_version" ]; then
      nvm use
    fi
  elif [ "$node_version" != "$(nvm version default)" ]; then
    echo "Reverting to nvm default version"
    nvm use default
  fi
}
add-zsh-hook chpwd load-nvmrc
load-nvmrc

More info: https://github.com/creationix/nvm#zsh


If you use bash you can add this to your ~/.bashrc file:

enter_directory() {
  if [[ $PWD == $PREV_PWD ]]; then
    return
  fi

  PREV_PWD=$PWD
  [[ -f ".nvmrc" ]] && nvm use
}

export PROMPT_COMMAND=enter_directory

Excellent answer from @devius.

I just extended it so it can revert to the default version when leaving a directory with .nvmrc to another without it.

~/.bashrc:

#
# Run 'nvm use' automatically every time there's 
# a .nvmrc file in the directory. Also, revert to default 
# version when entering a directory without .nvmrc
#
enter_directory() {
if [[ $PWD == $PREV_PWD ]]; then
    return
fi

PREV_PWD=$PWD
if [[ -f ".nvmrc" ]]; then
    nvm use
    NVM_DIRTY=true
elif [[ $NVM_DIRTY = true ]]; then
    nvm use default
    NVM_DIRTY=false
fi
}

export PROMPT_COMMAND=enter_directory

Following @doug-barbieri's suggestion, the script below will not change node back to the default version if there's no .nvmrc file in the current directory but there is one in the parent sub-directory.

~/.bashrc:

enter_directory() {
  if [[ $PWD == $PREV_PWD ]]; then
    return
  fi

  if [[ "$PWD" =~ "$PREV_PWD" && ! -f ".nvmrc" ]]; then
    return
  fi

  PREV_PWD=$PWD
  if [[ -f ".nvmrc" ]]; then
    nvm use
    NVM_DIRTY=true
  elif [[ $NVM_DIRTY = true ]]; then
    nvm use default
    NVM_DIRTY=false
  fi
}

The trick is here:

if [[ "$PWD" =~ "$PREV_PWD" && ! -f ".nvmrc" ]]; then
  return
fi

It checks if the PWD contains PREV_PWD. For example, if /home/user1/a/b contains /home/user1/a.


This can be extended to work with Starship (even on Git Bash for Windows not WSL) as well using the starship_precmd_user_func

set_win_title() {
  BASEPWD=$(basename "$PWD")
  echo -ne "\033]0; 📁 $BASEPWD \a" < /dev/null
  if [[ $PWD == $PREV_PWD ]]; then
    return
  fi

  if [[ "$PWD" =~ "$PREV_PWD" && ! -f ".nvmrc" ]]; then
    return
  fi

  PREV_PWD=$PWD
  if [[ -f ".nvmrc" ]]; then
    nvm use
    NVM_DIRTY=true
  elif [[ $NVM_DIRTY = true ]]; then
    nvm use default
    NVM_DIRTY=false
  fi
}
starship_precmd_user_func="set_win_title"
eval "$(starship init bash)"

I just found out about Automatic Version Switching for Node.js https://github.com/wbyoung/avn, you can use that.

You can also follow this thread https://github.com/creationix/nvm/issues/110


This answer is taken from the official nvm documentation.

Put the following at the end of your $HOME/.bashrc:

find-up () {
    path=$(pwd)
    while [[ "$path" != "" && ! -e "$path/$1" ]]; do
        path=${path%/*}
    done
    echo "$path"
}

cdnvm(){
    cd "$@";
    nvm_path=$(find-up .nvmrc | tr -d '[:space:]')

    # If there are no .nvmrc file, use the default nvm version
    if [[ ! $nvm_path = *[^[:space:]]* ]]; then

        declare default_version;
        default_version=$(nvm version default);

        # If there is no default version, set it to `node`
        # This will use the latest version on your machine
        if [[ $default_version == "N/A" ]]; then
            nvm alias default node;
            default_version=$(nvm version default);
        fi

        # If the current version is not the default version, set it to use the default version
        if [[ $(nvm current) != "$default_version" ]]; then
            nvm use default;
        fi

        elif [[ -s $nvm_path/.nvmrc && -r $nvm_path/.nvmrc ]]; then
        declare nvm_version
        nvm_version=$(<"$nvm_path"/.nvmrc)

        # Add the `v` suffix if it does not exists in the .nvmrc file
        if [[ $nvm_version != v* ]]; then
            nvm_version="v""$nvm_version"
        fi

        # If it is not already installed, install it
        if [[ $(nvm ls "$nvm_version" | tr -d '[:space:]') == "N/A" ]]; then
            nvm install "$nvm_version";
        fi

        if [[ $(nvm current) != "$nvm_version" ]]; then
            nvm use "$nvm_version";
        fi
    fi
}
alias cd='cdnvm'

This is an improvement over:

  • @Gabo Esquivel's answer - because you won't have to switch to another tool (avn)
  • @devius's and @Adriano P's answers - which do not deal with situations where you are within a project

This alias would search 'up' from your current directory in order to detect a .nvmrc file. If it finds it, it will switch to that version; if not, it will use the default version.


I tried many solutions for this and nothing worked the way I wanted, so I wrote my own:

ZSH function to auto-switch to correct Node version

As far as I know, this is the only one that meets all the following criteria:

  • guarantees you are always on the right version by searching up the directory tree to find the closest .nvmrc (just like nvm use);
  • can handle any valid .nvmrc format;
  • clearly warns you if no installed version satisfies the .nvmrc,
  • assumes you want default if there is no .nvmrc anywhere up the tree;
  • is completely silent and fast if you are already on the correct Node version.

Yet another solution using direnv. Direnv comes with OS X and many distros so no installation is needed.

Add these two lines to your .zshenv or .bash_profile depending on which shell you use:


export NVM_DIR="$HOME/.nvm" # You probably have this line already
export NODE_VERSIONS="${NVM_DIR}/versions/node"
export NODE_VERSION_PREFIX="v"

Add an .envrc file to the project root with the contents

set -e
use node

Finally cd to your directory. (Don't forget to source .zshenv)

direnv will ask you to allow load config. Type direnv allow and voila!

Note that direnv doesn't support fancy constructs like lts/* in .nvrmc. On the positive side, direnv supports a bunch of runtimes like node, php, go, pyhton, ruby etc. allowing us to use a single tool to solve path issues.