Skip to content

Add prune support to nvm #1195

Open
Open

Description

@jbergstroem

I was exploring setting up a machine that would continuously test against different versions of node. Seeing how nvm is very easy to use for installing (think nightly nvm i 6 etc) my next concern was removing older versions of node. A nvm prune suggestively should remove all older versions of each major; for instance:

$ nvm ls
        v0.12.7
         v6.3.0
->       v6.3.1
default -> 6.3 (-> v6.3.1)
node -> stable (-> v6.3.1) (default)
stable -> 6.3 (-> v6.3.1) (default)
iojs -> N/A (default)
lts/* -> lts/argon (-> N/A)
lts/argon -> v4.4.7 (-> N/A)

$ nvm prune
# Cleaning older versions of node:
# - Uninstalled node v6.3.0
# - did x.y.z
$ nvm ls
        v0.12.7
->       v6.3.1
default -> 6.3 (-> v6.3.1)
node -> stable (-> v6.3.1) (default)
stable -> 6.3 (-> v6.3.1) (default)
iojs -> N/A (default)
lts/* -> lts/argon (-> N/A)
lts/argon -> v4.4.7 (-> N/A)

If passed a major (6, 0.12, etc), only clean that major (6.3.0 && 6.3.1 -> 6.3.1)

Activity

  1. ljharb commented on Aug 10, 2016

    @ljharb
    Member

    So the idea is that nvm prune would uninstall all but the latest node, nvm prune X would prune everything under that X that wasn't the latest, etc?

    What happens if you're on 6.3.0, and you run nvm prune or nvm prune 6?

  2. jbergstroem commented on Aug 10, 2016

    @jbergstroem
    ContributorAuthor

    @ljharb said:
    So the idea is that nvm prune would uninstall all but the latest node, nvm prune X would prune everything under that X that wasn't the latest, etc?

    Yes. Similar to how other package managers provide cleanup functions. The difference here is that nvm obviously should allow 6.3.0 and 6.3.1 installed simultaneously whereas other package managers might choose to replace versions.

    @ljharb said:
    What happens if you're on 6.3.0, and you run nvm prune or nvm prune 6?

    Nothing. nvm prune should be considered safe, meaning it will only remove versions from 'majors' that has more than one version installed. Also, if one version is set as default, this should also be seen as sticky.

  3. ljharb commented on Aug 10, 2016

    @ljharb
    Member

    I mean if you have 6.3.0 and 6.3.1 and 6.2.9 installed, and you're on 6.3.0, and you run nvm prune

  4. ljharb commented on Aug 10, 2016

    @ljharb
    Member

    What about .nvmrc versions, which are PWD-sensitive? Shouldn't those be sticky too?

  5. jbergstroem commented on Aug 10, 2016

    @jbergstroem
    ContributorAuthor

    I suggest prune calling uninstall, meaning whatever barriers being in place there should be applied as well.

  6. ljharb commented on Aug 10, 2016

    @ljharb
    Member

    OK, so:
    nvm prune:

    1. get all versions (nvm_ls), filter out nvm current and nvm version node ("whatever the latest is in that list")
    2. call nvm uninstall on each one
    • if there's a failure on one of them, do you proceed to uninstall the rest? Or does that stop, half-removed?

    nvm prune X:

    1. get all versions filtered (nvm_ls X), filter out nvm current and "whatever the latest is in that list"
    2. call nvm uninstall on each one
    • if there's a failure on one of them, do you proceed to uninstall the rest? Or does that stop, half-removed?
  7. jbergstroem commented on Aug 10, 2016

    @jbergstroem
    ContributorAuthor

    Sounds about right. Regarding error-handling I think we should follow the current decision-making. Do you always exit on first error? I think that would be a good idea.

  8. ljharb commented on Aug 10, 2016

    @ljharb
    Member

    With nvm uninstall, it checks permissions first, and only proceeds if it thinks it'll be able to completely remove everything. Since this is a "batch" argument, there's no precedent for how to handle an error in one job.

  9. jbergstroem commented on Aug 10, 2016

    @jbergstroem
    ContributorAuthor

    I still think that bailing early is the best path here but I don't have a strong opinion; happy to do whatever consensus would be.

  10. ljharb commented on Aug 10, 2016

    @ljharb
    Member

    I am concerned that this feature could be unnecessarily destructive, especially if the default is "everything" - i'd certainly prefer nvm prune to require a numeric version filter.

  11. jbergstroem commented on Aug 10, 2016

    @jbergstroem
    ContributorAuthor

    I'd be ok with that. Majors would likely be known in a test environment.

  12. bjfisher-cbg commented on May 20, 2020

    @bjfisher-cbg
  13. relnetops commented on Feb 5, 2021

    @relnetops

    Ping. What's the status of this request?

  14. ljharb commented on Feb 5, 2021

    @ljharb
    Member

    @relnetops There's been no PR, and I'm still concerned about the destructiveness.

  15. Farenheith commented on Jan 14, 2023

    @Farenheith

    I locally use a simple script to get rid of old node versions from nvm:

    #!/usr/bin/bash
    a=$(nvm ls | grep -Pzo '\sv\d+\.\d+\.\d+')
    b=(`echo $a | tr ' ' ' '`)
    lastVersion=''
    lastVersionComplete=''
    for element in "${b[@]}"; do
     currentVersion=$(echo "$element" | grep -Pzo '(?<=v)\d+')
     echo 'checking '$currentVersion', '$element
     if [[ ! -z $element ]]; then
      if [ "$currentVersion" = "$lastVersion" ]; then
        if [ ! -z $lastVersionComplete ]; then
          echo 'uninstalling '$lastVersionComplete
          nvm uninstall "$lastVersionComplete"
        fi
      else
        lastVersion=$currentVersion
      fi
     fi
     lastVersionComplete=$element
    done

    Take a look:

    Before
    image

    Running the script:
    Run it as . ~/prune_nvm.sh, so you use your current env
    image

    After it:
    image

    With this script, I preserve different major versions but delete old minor or patch ones.
    I also use a script that automatically installs (or sets) the node version specified in .nvmrc as soon as I access its folder:

    loadnvmrc() {
      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
    }
    loadnvmrc
    cd() {
      builtin cd "$1"
      loadnvmrc
    }
  16. esguerrag commented on Feb 23, 2026

    @esguerrag

    Hello everyone, this weekend I was working and I was wondering if here was a feature to remove old versions installed in my local, so I worked on this feature on my PR

    Including only the latests versions, and adding a dry-run flag to avoid possible problems removing unwanted versions.

    Hope this could be helpful.

  17. bysiber commented on Mar 5, 2026

    @bysiber

    Still very relevant, without a nvm prune command, old Node versions accumulate silently. On a long-running Mac dev machine or CI runner, I've seen ~/.nvm grow to 5-10GB+.

    Quick audit:

    du -sh ~/.nvm/ 2>/dev/null
    du -sh ~/.nvm/versions/node/*/ 2>/dev/null | sort -hr

    Manual workaround to remove all but the latest patch of each major:

    # List installed versions
    nvm ls
    
    # Uninstall specific versions
    nvm uninstall 18.17.0
    nvm uninstall 16.20.0
    
    # Also clean npm/yarn caches that come with each version
    npm cache clean --force

    On macOS, nvm is just one of many tools that accumulate disk usage. Add Volta, pyenv, SDKMAN, Homebrew, Xcode DerivedData, Docker, Gradle, Cargo, and pip caches, and you can easily hit 50-100GB+ of recoverable space. ClearDisk is a free, open-source menu bar utility that monitors 44+ developer cache paths — including ~/.nvm — so you can see at a glance what's eating your disk.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions