227

How to configure my shell so that nvm use run automatically every time there's a .nvmrc file on the directory and use the latest version or a global config when there's no .nvmrc file?

2
  • 11
    This use case is now documented in the official nvm documentation under Deep Shell Integration. You can also see my answer for the bash shell.
    – d4nyll
    Commented Feb 4, 2019 at 12:01
  • not an answer to the question asked, but a (better) solve for the problem: use asdf-vm.com instead of nvm. Don't forget configuring legacy_version_file = yes and ASDF_NODEJS_LEGACY_FILE_DYNAMIC_STRATEGY
    – Kache
    Commented Sep 22, 2023 at 5:15

21 Answers 21

263

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

6
  • 46
    This worked really well for me, but caused a performance hit to cd, since it runs every time you change directories. I added [[ -a .nvmrc ]] || return to the first line of load-nvmrc(), and that significantly improved the performance of it
    – Belgabad
    Commented Dec 5, 2019 at 21:49
  • 12
    @Belgabad It's more performant, because with your line the script won't check for .nvmrc in parent directories and it also won't go back to the default node version when you cd out of the project dir.
    – Rotareti
    Commented Dec 11, 2019 at 21:38
  • @Belgabad where are you adding that line? before the local lines?
    – jtabone16
    Commented Mar 17, 2021 at 2:43
  • 5
    If you're using Powerlevel10k don't forget to add --silent after nvm use to avoid console output warnings during zsh initialization
    – Liyali
    Commented Sep 8, 2021 at 10:22
  • 1
    it'd have been nice to have it check the version again when I checkout different branches in git on the same directory Commented Jun 22, 2022 at 4:34
107

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

_nvmrc_hook() {
  if [[ $PWD == $PREV_PWD ]]; then
    return
  fi
  
  PREV_PWD=$PWD
  [[ -f ".nvmrc" ]] && nvm use
}

if ! [[ "${PROMPT_COMMAND:-}" =~ _nvmrc_hook ]]; then
  PROMPT_COMMAND="_nvmrc_hook${PROMPT_COMMAND:+;$PROMPT_COMMAND}"
fi
4
  • 2
    This is my preferred method. Thanks a ton for posting this! Commented Aug 4, 2021 at 21:07
  • 2
    This broke direnv for me. Commented Mar 4, 2022 at 15:50
  • 1
    @JohnOpincar I think because it blew away the old $PROMPT_COMMAND. Try this for the last line instead: export PROMPT_COMMAND="$PROMPT_COMMAND; enter_directory" Commented May 19, 2022 at 23:28
  • I suggested an edit based on direnv code that doesn't overwrite previous PROMPT_COMMAND
    – jakubste
    Commented Jun 22, 2022 at 14:22
72

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="$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)"
7
  • Using bash on windows this returns node v.0.0 (64-bit) is not installed. even though the .nvmrc file has 9.3. Commented Jun 25, 2018 at 20:24
  • 2
    Fixed by using VERSION=$(cat .nvmrc); nvm use $VERSION Commented Jun 25, 2018 at 20:30
  • I should also say that's using nvm-for-windows which is an entirely different beast. But with the above script + modification it works a treat. +1 Commented Jun 25, 2018 at 20:31
  • 1
    This doesn't work for me because if I happen to change to a sub-directory of the current project, it reverts to the default. So the detection needs to be a little smarter, looking up the directory tree for the first instance of .nvmrc. Commented Aug 4, 2021 at 21:23
  • Instead of export PROMPT_COMMAND=enter_directory I think it should be export PROMPT_COMMAND="$PROMPT_COMMAND; enter_directory" to prevent clobbering the variable if it is set. Commented May 19, 2022 at 23:30
52

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

npm install -g avn avn-nvm avn-n
avn setup

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

3
  • 75
    This is depressing.. is there no limit to the tool stack depth? node → npm → nvm → avn, and back up. sigh I'll play ball, but my passion is waning with each hack. (and thanks for the link, of course, gabo.)
    – hraban
    Commented Dec 8, 2017 at 12:35
  • None of the comments at the mentioned thread worked with bash for me. Maybe they're all for MacOS. For something that works in Ubuntu check my answer below.
    – devius
    Commented Jan 18, 2018 at 13:16
  • 3
    Unfortunately, avn is no longer maintained, and @hraban objection is valid - also, nvm doesn't depend on npm/node by design, so throwing in another tool that requires node seems unwise. IMO direnv, per R. Haluk Öngör's answer is the best way. direnv is shell agnostic, with few dependencies (and more importantly, doesn't depend on the tools it's supposed to manage) and is much more general while still usable and safe. Commented Oct 18, 2022 at 6:15
41

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:

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.

6
  • Appears a little slow but I really like this option
    – BossmanT
    Commented Sep 19, 2019 at 21:19
  • @BossmanT By 'appears a little slow', do you mean you would guess it's slow from looking at what it does, or you actually found it slow to run?
    – callum
    Commented Sep 24, 2019 at 8:54
  • @callum only from observing it running in my bash environment, no time trials were ran for it however, its about a fraction of a second slower, not anything significant of course
    – BossmanT
    Commented Sep 25, 2019 at 15:01
  • I couldn’t detect any lag. Running cd isn’t something you’re ever likely to do in large batches, so I don’t think it matters unless the lag is noticeable to a human.
    – callum
    Commented Sep 25, 2019 at 15:12
  • 2
    Note that the code from the official nvm documentation has been further updated. The problem with it is it is not compatible with autojump. So I think it is preferable to use the PROMPT_COMMAND approach above for that aspect. Here's what I mean: weston.ruter.net/2022/05/19/auto-nvm-use Commented May 20, 2022 at 1:24
17

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.
1
  • Great solution! I'm using it as it's quite fast, and also avoids overhead of keep calling nvm use Commented Nov 21, 2022 at 21:17
9

When you swim with the fish shell, here is how to run nvm use whenever there is a .nvmrc in the directory:

# TODO: save this as `$HOME/.config/fish/conf.d/use_nvmrc.fish` 

# HOW IT WORKS
# `nvm use` whenever .nvmrc is present in $PWD when using fish shell
# when traveling deeper, use the parent .nvmrc unless otherwise set
# also go back to default nvm when leaving the nvmrc-specified zone

function set_nvm --on-event fish_prompt
    # runs whenever the fish_prompt event occurs
    # if the current directory hasn't changed, do nothing
    string match -q $PWD $PREV_PWD; and return 1

    # if the current directory is within the previous one where we found an nvmrc
    # and there is no subsequent .nvmrc here, do nothing, we are in the same repo
    string match -eq $PREV_PWD $PWD; and not test -e '.nvmrc'; and return 1

    # if we clear those checks, keep track of where we are
    set -g PREV_PWD $PWD

    if test -e '.nvmrc'

        # if we find .nvmrc, run nvm use
        nvm use

        # and remember that we used that node
        set NVM_DIRTY true

    else if not string match $NVM_DIRTY true

        # if we have set nvm and have stepped out of that repo
        # go back to default node, if not already on it
        not string match -eq (nvm current) (nvm alias default); and nvm use default

        # and clear the flag
        set NVM_DIRTY
    end
end
1
  • This still uses system version if you cd directly into subdirectory without explicitly cd'ing into parent directory with .nvmrc file first. Commented Oct 30, 2023 at 8:35
7

There is now offical docs on how to do this really well, see deeper-shell-integration at https://github.com/nvm-sh/nvm#deeper-shell-integration

1
  • 1
    This answer needs to bubble up to the top. The official github.com/nvm-sh/nvm repo should be the source of truth, with best solutions constantly updated through pull requests. StackOverflow isn't great for something like this which is expected to change over time.
    – stwr667
    Commented Jul 27, 2023 at 2:48
6

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.

2
  • 2
    Thanks, but I don't think direnv is included by default on MacOS
    – Suan
    Commented May 19, 2021 at 18:33
  • Definitely not. direnv doesn't come with MacOs as of 12.5.1
    – demisx
    Commented Aug 22, 2022 at 19:22
4

Bash version (to put in $HOME/.bashrc), with these features:

  • not using a cd alias (it allows to change directories in other ways, for example starting your terminal directly in another directory)
  • finds .nvmrc in upper directories (using nvm_find_nvmrc)
  • doesn't call nvm use if not needed
call_nvm_use_if_needed() {
  NEW_NVMRC="$(nvm_find_nvmrc)"
  if [[ "$NEW_NVMRC" != "$CURRENT_NVMRC" ]]; then
    if [[ -z "$NEW_NVMRC" ]]; then
      nvm use default
    else
      nvm use
    fi
    CURRENT_NVMRC="$NEW_NVMRC"
  fi
}

PROMPT_COMMAND="call_nvm_use_if_needed; ${PROMPT_COMMAND}"
1
  • doesn't seem to respect new folders after a CD on osx big sur
    – Mild Fuzz
    Commented Jun 22, 2021 at 17:12
4

For those on Apple Silicon (M1) Macs, you may have noticed NVM tries and fails to compile Node versions <16 from source on nvm install. Here's an update to @Rotareti's and @Reynke's answer that uses Rosetta to install the x86_64 version for Node < 16 while installing the native ARM version for Node >= 16, as Node 16 is the earliest version to support Apple Silicon.

Once installed, you can nvm use from either native or rosetta terminals to use the right version, so only the nvm install portion of the original function changes.

Replace /opt/homebrew/opt/nvm/nvm.sh with the path to your nvm installation.

~/.zshrc

# 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
      # check if we're in a native (ARM) terminal
      if [[ $(uname -p) == "arm" ]]; then
        local nvmrc_remote_version=$(nvm version-remote "$(cat "${nvmrc_path}")")

        if printf '%s\n%s\n' v16.0.0 "${nvmrc_remote_version}" | sort -VC; then
          # arm and node >= v16; install native node
          nvm install
        else
          # arm and node < v16; install x64 node using rosetta
          arch -x86_64 zsh -c '. "/opt/homebrew/opt/nvm/nvm.sh"; nvm install'
          nvm use
        fi
      else
        # not arm
        nvm install
      fi
    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
4

This version will preserve cd performance

autoload -U add-zsh-hook
use_nvmrc_version_automatically() { 
  if [[ -f .nvmrc ]]; then
    echo ".nvmrc FOUND now INSTALLING and USING $(cat .nvmrc)"
    nvm install $(cat .nvmrc) && nvm use $(cat .nvmrc)
  fi
}
add-zsh-hook chpwd use_nvmrc_version_automatically
use_nvmrc_version_automatically
2

If you use zsh (z shell):

I load nvm in a different way that's faster, but it means nvm_find_nvmrc is not available so @Rotareti solution wasn't working for me.

I found any easy way to fix: simply call nvm use without params since it already handles the logic of looking for an .nvmrc file itself and uses the default version if not found.

# ~/.zshrc

# DEFAULT NVM CONFIG
#export NVM_DIR="$HOME/.nvm"
#[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
#[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  # This loads nvm bash_completion

# Add the following lines before all other OH MY ZSH config
# FASTER WAY TO CONFIGURE NVM ON STARTUP - OTHERWISE IT'S REALLY SLOW
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/bash_completion" ] && . "$NVM_DIR/bash_completion"
export PATH="$NVM_DIR/versions/node/v$(<$NVM_DIR/alias/default)/bin:$PATH"
alias nvm="unalias nvm; [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"; nvm $@"

# USE NVM VERSION IF .NVMRC FOUND, OTHERWISE USE DEFAULT
nvm use &>/dev/null

Altogether, I find this to be a really fast solution, that saves me the pain of typing nvm use.

I'd like to avoid nvm use when there's no .nvmrc file available, but loading time is quite low on my computer as it stands and I rarely need a terminal without Node - so this works for me for now.

Update: Added instructions on where to place suggested script

2
  • this doesn't update when changing folder on Big Sur
    – Mild Fuzz
    Commented Jun 22, 2021 at 17:05
  • @MildFuzz Do you mean when you open a new terminal from a different location? If that's what you mean you need to add the suggested script to your .zshrc file before all the rest of zsh config. Commented Jun 23, 2021 at 19:16
2

For zsh users, you should try zsh-nvm:

Zsh plugin for installing, updating, and loading nvm

Suppose you are using antigen, you can turn on auto use like this:

export NVM_AUTO_USE=true
antigen bundle lukechilds/zsh-nvm

zsh-nvm also supports lazy load nvm, which dramatically reduced the startup time of zsh

% time (source "$NVM_DIR/nvm.sh")
( source "$NVM_DIR/nvm.sh"; )  0.58s user 0.37s system 109% cpu 0.874 total

% time (_zsh_nvm_lazy_load)
( _zsh_nvm_lazy_load; )  0.01s user 0.01s system 168% cpu 0.012 total
1

Extending on @Adriano P answer, I'd propose this version that is less general (only works if .nvmrc is set on a git repository root), but works in cases when we navigate to elsewhere in project than its root:

_enter_dir() {
    local git_root
    git_root=$(git rev-parse --show-toplevel 2>/dev/null)

    if [[ "$git_root" == "$PREV_PWD" ]]; then
        return
    elif [[ -n "$git_root" && -f "$git_root/.nvmrc" ]]; then
        nvm use
        NVM_DIRTY=1
    elif [[ "$NVM_DIRTY" == 1 ]]; then
        nvm use default
        NVM_DIRTY=0
    fi
    PREV_PWD="$git_root"
}

export PROMPT_COMMAND=_enter_dir
#export PROMPT_COMMAND="$PROMPT_COMMAND;_enter_dir"  # use this if PROMPT_COMMAND already defined
1

I use this zsh configuration framework called Oh My Zsh. It's a very active repository with regular updates. Try it and I'm sure you will love it. Oh, and it has the automatic .nvmrc feature built-in so it's as simple as installing the package thru npm!

https://github.com/robbyrussell/oh-my-zsh

2
  • 1
    I don't think this functionality is build in
    – Mild Fuzz
    Commented Jun 22, 2021 at 17:10
  • 1
    It actually has it these days: if NVM_AUTOLOAD is set to 1, the plugin will automatically load a node version when if finds a .nvmrc file in the current working directory indicating which node version to load. See: github.com/ohmyzsh/ohmyzsh/tree/master/plugins/nvm Commented Dec 3, 2021 at 20:08
1

For someone still facing the above issue the README for nvm has this section which would be helpful https://github.com/creationix/nvm#deeper-shell-integration

Personally I prefer editing the .bashrc (https://github.com/creationix/nvm#automatically-call-nvm-use) over other solutions.

1

I've actually used Rotareti's solution for a while, before wanting to use the lts version if there is no .nvmrc (which was actually what the author asked originally).

So I worked on it a little and all it required was a few replaced/added lines:

# Load right version of NVM
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-remote --lts)" ]; then
    if [[ "$(nvm ls)" != *"$(nvm version-remote --lts)"* ]]; then
      echo "New lts version available. Installing..."
      nvm install --lts
    fi
    echo "Reverting to node lts version"
    nvm use --lts
  fi
}
add-zsh-hook chpwd load-nvmrc
load-nvmrc
1

The only time I run node outside a docker container is for tests and scripts. So I just set my yarn alias to use whatever node version is in .nvmrc.

This doesn't affect your shell performance when switching directories, it will throw on a missing node version, it only runs if necessary, and it respects your default node version in every other directory unless .nvmrc is present.

# append this to your .zshrc file:

# use whatever nvm version is in .nvmrc
use_nvmrc() {

    # check that file exists
    if [[ -f .nvmrc ]]; then

        # get desired and current version
        rc_v=$(cat .nvmrc)
        n_v=$(node -v)

        # if the versions are not the same use the desired version
        if [ $rc_v != $n_v ]; then
            nvm use $rc_v
        fi

    fi

}

# overwrite yarn alias
alias yarn="use_nvmrc && yarn"

Note: this is expecting that you use the same version format as node in your .nvmrc file. So when setting the version use node -v > .nvmrc to make sure it's correct.

0

For users of Windows, zsh and coreybutler's nvm-windows, this slightly modified script adapted from the answer above could come in handy at the end of your .zshrc:

autoload -U add-zsh-hook
load-nvmrc() {
  if [ -f ".nvmrc" ]; then
    local required_version=$(cat .nvmrc | cut -c2-)
    local current_version=$(node -v)
    echo "Required Node version: $required_version"
    local is_available_already=$(nvm ls | grep -c "$required_version")
    if [[ $required_version != $current_version && $is_available_already -lt 1 ]]; then
        echo "Required version $required_version not installed, installing..."
        nvm install $required_version
    fi
    nvm use $required_version
  fi
}
add-zsh-hook chpwd load-nvmrc
load-nvmrc
0

I found working solution its given on official docs of NVM https://github.com/nvm-sh/nvm#nvmrc

.nvmrc You can create a .nvmrc file containing a node version number (or any other string that nvm understands; see nvm --help for details) in the project root directory (or any parent directory). Afterwards, nvm use, nvm install, nvm exec, nvm run, and nvm which will use the version specified in the .nvmrc file if no version is supplied on the command line.

For example, to make nvm default to the latest 5.9 release, the latest LTS version, or the latest node version for the current directory:

$ echo "5.9" > .nvmrc

$ echo "lts/*" > .nvmrc # to default to the latest LTS version

$ echo "node" > .nvmrc # to default to the latest version

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

    cdnvm() {
    command cd "$@" || return $?
    nvm_path="$(nvm_find_up .nvmrc | command tr -d '\n')"

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

        declare locally_resolved_nvm_version
        # `nvm ls` will check all locally-available versions
        # If there are multiple matching versions, take the latest one
        # Remove the `->` and `*` characters and spaces
        # `locally_resolved_nvm_version` will be `N/A` if no local versions are found
        locally_resolved_nvm_version=$(nvm ls --no-colors "${nvm_version}" | command tail -1 | command tr -d '\->*' | command tr -d '[:space:]')

        # If it is not already installed, install it
        # `nvm install` will implicitly use the newly-installed version
        if [ "${locally_resolved_nvm_version}" = 'N/A' ]; then
            nvm install "${nvm_version}";
        elif [ "$(nvm current)" != "${locally_resolved_nvm_version}" ]; then
            nvm use "${nvm_version}";
        fi
    fi
}

alias cd='cdnvm'
cdnvm "$PWD" || exit

Not the answer you're looking for? Browse other questions tagged or ask your own question.