Skip to content

Instantly share code, notes, and snippets.

@fvclaus
Last active January 8, 2024 16:16
Show Gist options
  • Save fvclaus/540c08921ba884fef959053c4f974bfc to your computer and use it in GitHub Desktop.
Save fvclaus/540c08921ba884fef959053c4f974bfc to your computer and use it in GitHub Desktop.
Run vscode tasks with nvm

Nvm does not work in vscode tasks, because tasks are run without a shell. .bashrc is not loaded and the nvm command is unknown.

My solution uses a wrapper script around /bin/bash that reads in the correct node version from .npmrc in the project folder.

#!/bin/bash

set -e

if [[ "$2" == nvm* ]]; then
    export NODE_VERSION=v$(cat .nvmrc)
    if [ -z "$NODE_VERSION" ]; then
        echo "$(pwd)/.nvmrc does not exist or is empty"
        exit 1
    fi
    CLEAN_CMD=$(echo $2 | sed -e 's/nvm/npm/g')

    /bin/bash -c "~/.nvm/nvm-exec $CLEAN_CMD"
else
    /bin/bash -c $@
fi

The wrapper script is configured as default shell using the terminal.integrated.automationShell.<os> setting in settings.json.

Example:

    "terminal.integrated.automationShell.linux": "<path>/nvm-shell.sh"

Instead of defining a tasks of type npm, the shell type is used instead:

    {
        "type": "shell",
        "command": "nvm run compile",
        "label": "npm-compile",            
        "problemMatcher": "$tsc",
        "isBackground": false,  
        "presentation": {
            "reveal": "always"
        },
        "group": {
            "kind": "build",
            "isDefault": true
        }
    }

Theoretically, it should be possible to configure this script per taks without the global configuration:

        "linux": {
            "options": {
                "shell": {
                    "executable": "<path>/nvm-shell.sh",
                    "args": []
                }
            }
        }

But that always returns an error 127 command nvm not found.

@kshksdrt
Copy link

An alternative solution I've found that appears to work well is installing this extension https://marketplace.visualstudio.com/items?itemName=Orta.vscode-jest and specifying the version of node you wish to use in the vscode.json using, for example:

{
    "jest.jestCommandLine": ". ~/.nvm/nvm.sh && nvm use 12 && yarn test --",
}

The above sources the nvm setup script, sets the version and runs the test command.

${env:NVM_DIR} can be used in vscode tasks instead of ~/.nvm/

@AnweshGangula
Copy link

found this article which talks about similar approach

@jamie-pate
Copy link

jamie-pate commented Jan 3, 2024

This works in vscode 1.85.1 (i use yarn, but the npm task matcher automatically detects that i guess?)

.vscode/tasks.json

        {
            "type": "npm",
            "script": "build",
            "path": "common/",
            "group": "build",
            "problemMatcher": [],
            "label": "npm: build - common",
            "detail": "yarn run build",
            "options": {"shell": {"executable": "${workspaceFolder}/../nvms.sh"}}
        },

nvmsh.sh

#!/usr/bin/env bash

## Runs NVM or NVS depending on which is available
## Source this script or call it with arguments to execute a task with the correct nvm/nvs env

## usage:
##
## Source inside a script:
## $ dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
## $ source "$dir/path/to/nvms.sh"
##
## Run a command with nvm/nvs:
## path/to/nvms.sh command arg1 arg2 arg3

if [ -f ~/.nvm/nvm.sh ]; then
    . ~/.nvm/nvm.sh
    nvm use
else
    . ~/.nvs/nvs.sh
    nvs use
fi

if [ $# -gt 0 ]; then
    # not sure why but it won't run yarn unless we find the exact location first...
    cmd="$(which $1)"
    shift
    exec "$cmd" "$@"
fi

@FTAndy
Copy link

FTAndy commented Jan 8, 2024

https://stackoverflow.com/a/73426063/4859280, this solution is easy and works for me.

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