{"id":13765403,"url":"https://github.com/tkareine/chnode","last_synced_at":"2025-07-09T13:08:13.615Z","repository":{"id":66767251,"uuid":"150030497","full_name":"tkareine/chnode","owner":"tkareine","description":"Changes shell's current Node.js version by updating $PATH","archived":false,"fork":false,"pushed_at":"2025-06-25T19:20:04.000Z","size":143,"stargazers_count":21,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-06-25T19:26:58.929Z","etag":null,"topics":["bash","chnode","homebrew-tap","minimalist","node-version-manager","nodejs","shell","version-manager","zsh"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tkareine.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":"support/fixture.sh","governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2018-09-23T22:20:56.000Z","updated_at":"2025-06-25T18:17:01.000Z","dependencies_parsed_at":"2025-04-30T10:31:42.983Z","dependency_job_id":"27dc3da8-185e-4ff7-90e0-3093fe0ec0a2","html_url":"https://github.com/tkareine/chnode","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/tkareine/chnode","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tkareine%2Fchnode","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tkareine%2Fchnode/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tkareine%2Fchnode/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tkareine%2Fchnode/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tkareine","download_url":"https://codeload.github.com/tkareine/chnode/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tkareine%2Fchnode/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264465641,"owners_count":23612576,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bash","chnode","homebrew-tap","minimalist","node-version-manager","nodejs","shell","version-manager","zsh"],"created_at":"2024-08-03T16:00:38.390Z","updated_at":"2025-07-09T13:08:13.601Z","avatar_url":"https://github.com/tkareine.png","language":"Shell","readme":"# chnode\n\n[![CI](https://github.com/tkareine/chnode/actions/workflows/ci.yml/badge.svg)][chnode-CI]\n\nChanges shell's current Node.js version by updating `$PATH`.\n\n`chnode` is a lightweight Node.js version switcher that selects a\nNode.js version for a shell session. The mechanism to do this is by\nupdating the `PATH` environment variable. Confining version switching to\na shell session allows you to run different Node.js versions in many\nshell sessions simultaneously.\n\nThe lightweight design and small feature set makes `chnode` very fast to\nload, having minimal negative effect on your shell's init script.\n\n`chnode` expects that Node.js versions are already installed on your\nsystem. It cannot download them for you. Instead, download Node.js\nbinaries manually or use another tool, such as [node-build], for the\njob.\n\nTo read more about the design rationale and a comparison to [nvm] and\n[nodenv], look [here][tkareine-lightweight-nodejs-version-switching].\n\n`chnode` is inspired by [chruby], which is awesome.\n\n## Features\n\n* Selects Node.js version for a shell session by updating the `PATH`\n  environment variable. Version switching is independent per shell\n  session.\n* Optional automatic Node.js version switching based on the contents of\n  the `.node-version` file in your project directory, or from another\n  file, specified in the `CHNODE_AUTO_VERSION_FILENAME` shell variable.\n* Small feature set by design, making the tool very fast to load.\n* Each Node.js version has its own set of global npm packages.\n* Allows accessing man pages for the selected Node.js version and its\n  global npm packages.\n* After switching Node.js version, calls `hash -r` to clear the hash\n  table for program locations.\n* Best candidate (\"fuzzy\") matching of Node.js versions at switching.\n* The path to the selected Node.js version is available in the\n  `CHNODE_ROOT` environment variable. This makes it easy to display the\n  selected version in your shell prompt.\n* Locates installed Node.js versions in the `~/.nodes` directory, or\n  from a custom directory read from `CHNODE_NODES_DIR` shell variable.\n* Add additional Node.js versions by appending Node.js installation\n  paths to the `CHNODE_NODES` array shell variable.\n* Works with Bash's `set -euo pipefail` shell options (\"strict mode\").\n* Good test coverage.\n\n## Requirements\n\n[GNU Bash] version \u003e= 3.2 or [Zsh] version \u003e= 5.3\n\n## Install\n\n### Manual\n\nThe manual method just downloads the latest revision of [chnode.sh]\nscript:\n\n``` shell\ncurl -L 'https://raw.githubusercontent.com/tkareine/chnode/master/chnode.sh' \u003e chnode.sh\n```\n\nIt's up to you to download the script again to update.\n\n### Homebrew\n\n[Homebrew] [tap][Homebrew-tap-chnode] is available for macOS users:\n\n``` shell\nbrew tap tkareine/chnode\nbrew install tkareine/chnode/chnode\n```\n\nThis is the easy way to install just the script and related\ndocumentation, and to keep the script up-to-date.\n\n### Git clone\n\nAlternatively, clone the git repository:\n\n``` shell\ngit clone --depth 1 git@github.com:tkareine/chnode.git\n```\n\nThe downside of cloning is that you'll download all the non-essential\nproject files.\n\n### Post-installation\n\nExecute the `source` command to load chnode functions:\n\n``` bash\nsource chnode.sh\n```\n\nYou may append the command above into your shell's init script\n(`~/.bashrc` for Bash, `~/.zshrc` for Zsh) to load chnode for your\ninteractive shell usage.\n\nAutomatic Node.js version switching requires additional setup, read\nbelow for more.\n\n### Configure the prefix path for `npm`\n\nConsider configuring the [prefix path][npm-config-folders-prefix] for\n`npm` in the per-user [npmrc][npm-npmrc] file. It defines the\ninstallation location for global npm packages, ensuring sharing the\npackage installations for the Node.js versions you've installed.\n\nAn example `~/.npmrc`:\n\n```\nprefix=/usr/local\n```\n\n### Rename `npm` shipped with Node.js after updating `npm` globally\n\nWhen you install `npm` as a global npm package, the `npm` command\nshipped with Node.js takes precedence over the globally installed npm\npackage if the `PATH` environment variable includes the path to the\nformer before the path to the latter.\n\nAfter selecting a Node.js version with `chnode NODE_VERSION` (see the\nUsage section below), `chnode` adds the installation directory of the\nselected Node.js version to the beginning of `PATH`. Later invocations\nof `chnode NODE_VERSION` will change the installation directory of the\nselected Node.js version in `PATH` in place. Nevertheless, the user\nwould still need to append the npm prefix path (see the previous\nsection) to `PATH` after using `chnode NODE_VERSION` the first time.\n\nTo guarantee that the `npm` and `npx` commands of the npm package\nshipped with Node.js won't interfere with the commands from the globally\ninstalled npm package, you can rename the symlinks of the commands\nshipped with Node.js. For example:\n\n``` shell\n# Update npm by installing it as a global npm package\nnpm install -g npm@latest\n\n# Rename command symlinks of the npm package shipped with the selected\n# Node.js version\ncd \"$CHNODE_ROOT/bin\"\nmv npm{,@shipped}\nmv npx{,@shipped}\n```\n\n### Sourcing `.bashrc` on macOS\n\n(Applies to the Bash shell only.)\n\nmacOS does not execute `~/.bashrc` automatically when opening a\nterminal. You might want to add the following line to `~/.bash_profile`\nto fix it:\n\n``` bash\n[[ -r ~/.bashrc ]] \u0026\u0026 source ~/.bashrc\n```\n\n## Available Node.js versions\n\nWhen shell loads chnode with the `source` command, the script\nauto-detects Node.js versions installed in the `~/.nodes` directory.\n\nYou may override the `~/.nodes` directory by setting the\n`CHNODE_NODES_DIR` shell variable to point to another directory. Do this\nbefore executing the `source` command. For example:\n\n``` bash\nCHNODE_NODES_DIR=/opt/nodes\nsource chnode.sh\n```\n\nThe value of the `CHNODE_NODES_DIR` shell variable should point to a\ndirectory where you have Node.js installations. For example, if\n`CHNODE_NODES_DIR=~/.nodes` (the default):\n\n``` bash\nls -l ~/.nodes\n```\n\nOutput (truncated):\n\n```\n… node-16 -\u003e /usr/local/opt/node@16\n… node-18.10.0\n```\n\nThe first directory entry, `node-16`, is a symbolic link that ultimately\npoints to the actual Node.js installation path. The second directory\nentry, `node-18.10.0`, is a regular directory containing another Node.js\ninstallation.\n\nSourcing `chnode.sh` populates the `CHNODE_NODES` shell array variable\nwith paths to all the entries in the `CHNODE_NODES_DIR` directory. These\npaths are the Node.js versions you can select with the `chnode\nNODE_VERSION` command.\n\nAfter installing new Node.js versions or removing them, affecting the\ncontents of the `CHNODE_NODES_DIR` directory, run `chnode --reload` to\npopulate `CHNODE_NODES` again.\n\nFor Node.js versions installed elsewhere, add their paths to\n`CHNODE_NODES` after running the `source chnode.sh` or `chnode --reload`\ncommands. For example:\n\n``` bash\nsource chnode.sh\nCHNODE_NODES+=(/opt/node-10.11.0 /usr/local/opt/node@16)\n```\n\nWhen selecting a Node.js version with the `chnode NODE_VERSION` command,\nchnode attempts to match the `NODE_VERSION` user input to a path in the\n`CHNODE_NODES` shell array variable. Matching is done against the\nbasename of the path (the last path component). Upon finding a match,\nchnode checks that the path is a valid Node.js installation: the path\nmust contain an executable at the `bin/node` relative path. Continuing\nthe example above, when selecting Node.js v18.10.0 with the `chnode 18`\ncommand, chnode checks that `~/.nodes/node-18.10.0/bin/node` is an\nexecutable file. If the check fails, chnode prints an error message and\nreturns 1 as the exit code.\n\n### Installing Node.js versions\n\nUse any tool you like to install Node.js binaries.\n\nOne good option is [node-build]. Installing to `~/.nodes`:\n\n``` shell\nnode-build 10.11.0 ~/.nodes/node-10.11.0\n```\n\nAlternatively, download binaries from the Node.js [download\npage][nodejs-download] and extract them to `~/.nodes`:\n\n``` shell\nmkdir -p ~/.nodes/node-10.12.0 \\\n    \u0026\u0026 tar xzvf ~/Downloads/node-v10.12.0-darwin-x64.tar.gz --strip-components 1 -C ~/.nodes/node-10.12.0\n```\n\nYou can also use [Homebrew] to install a Node.js version:\n\n``` shell\nbrew install node@16\nln -s /usr/local/opt/node@16 ~/.nodes/node-16\n```\n\nThe previous approach relies on Homebrew providing you the symbolic link\nat `/usr/local/opt/node@16`, which points to the actual installation\npath. Homebrew will update that link whenever you upgrade the `node@16`\nformula with Homebrew.\n\n### Default Node.js version (without auto switching)\n\nChoose the default Node.js version in your shell's init script, here a\n10.x series:\n\n``` bash\nsource chnode.sh\nchnode node-10\n```\n\n## Usage\n\n**List** available Node.js versions:\n\n```\n$ chnode\n   node-10.11.0\n   node-8.11.4\n```\n\n**Select** a Node.js version, here using fuzzy matching to switch to\n10.x series:\n\n```\n$ chnode node-10\n\n$ chnode\n * node-10.11.0\n   node-8.11.4\n\n$ echo \"$PATH\"\n/Users/tkareine/.nodes/node-10.11.0/bin:/usr/local/bin:/usr/bin:…\n\n$ echo \"$CHNODE_ROOT\"\n/Users/tkareine/.nodes/node-10.11.0\n```\n\n`chnode` stores the path of the selected version in the `CHNODE_ROOT`\nenvironment variable.\n\nIf no version matches, `chnode` prints error and preserves the previous\nselection. Continuing the example above:\n\n```\n$ chnode nosuch\nchnode: unknown Node.js: nosuch\n\n$ echo \"$CHNODE_ROOT\"\n/Users/tkareine/.nodes/node-10.11.0\n```\n\nWhile in the shell, install another Node.js version and **reload**\nchnode (`chnode --reload`):\n\n```\n$ node-build 8.9.4 ~/.nodes/node-8.9.4\n\n$ chnode\n * node-10.11.0\n   node-8.11.4\n\n$ chnode --reload  # or -R\n\n$ chnode\n * node-10.11.0\n   node-8.11.4\n   node-8.9.4\n```\n\n**Reset** the version (`chnode --reset`), clearing the path that was set\nin the `PATH` environment variable:\n\n```\n$ chnode --reset  # or -r\n\n$ chnode\n   node-10.11.0\n   node-8.11.4\n   node-8.9.4\n\n$ echo \"$PATH\"\n/usr/local/bin:/usr/bin:…\n```\n\nUse `--reset` to use your system's Node.js installation (usually\n`/usr/local/bin/node` or `/usr/bin/node`).\n\nShow **usage**:\n\n```\n$ chnode --help  # or -h\n```\n\nShow **version**:\n\n```\n$ chnode --version  # or -V\n```\n\n## Automatic version switching\n\nAutomatic Node.js version switching is included in the [auto.sh] script\nas an optional add-on on top of `chnode.sh`. The feature detects a\n`.node-version` file in the current working directory (or in a parent\ndirectory, up to the system root directory), and switches the current\nNode.js version to the version specified in the file. You'll need to\nhave the specified version installed for switching to happen, otherwise\nyou'll get an error.\n\nTo use the feature, edit your shell's init script:\n\n1. Source `chnode.sh` and `auto.sh` (in this order).\n\n2. Optionally set the `CHNODE_AUTO_VERSION_FILENAME` shell variable to\n   name the file used in detecting automatic version switching. The\n   default value of the variable is `.node-version`. If this is ok, you\n   don't need to set the variable explicitly. For example, to use the\n   `.nvmrc` files of [nvm][nvmrc], set\n   `CHNODE_AUTO_VERSION_FILENAME=.nvmrc`.\n\n3. Configure the `chnode_auto` function to be called in\n   [PROMPT_COMMAND][Bash Controlling the Prompt] (for Bash) or in the\n   [precmd_functions][Zsh Hook Functions] hook (for Zsh).\n\nFor example:\n\n``` bash\nsource chnode.sh\nsource auto.sh\n\n# Uncomment to set the filename for the version file for something else\n# than `.node-version`.\n#CHNODE_AUTO_VERSION_FILENAME=.nvmrc\n\nPROMPT_COMMAND=chnode_auto       # if using Bash\nprecmd_functions+=(chnode_auto)  # if using Zsh\n```\n\nNote that you might already have commands to be evaluated in\n`PROMPT_COMMAND` in Bash. In that case, you can choose to:\n\n1. Wrap all the commands in a single function, calling `chnode_auto`\n   from inside the function, and set the value of `PROMPT_COMMAND` to be\n   the name of the function:\n\n   ``` bash\n   my_prompt_function() {\n       chnode_auto\n\n       # do something else, like set PS1\n   }\n\n   PROMPT_COMMAND=my_prompt_function\n   ```\n\n2. Include `chnode_auto` to be called in `PROMPT_COMMAND`, separating\n   other commands with a semicolon:\n\n   ``` bash\n   PROMPT_COMMAND=\"chnode_auto; $PROMPT_COMMAND\"\n   ```\n\n3. Use [Bash-Preexec] or a similar tool to simulate `precmd_functions`\n   of Zsh in Bash. For example, with Bash-Preexec:\n\n   ``` bash\n   source bash-preexec.sh\n   precmd_functions+=(chnode_auto)\n   ```\n\nWe don't recommend to call `chnode_auto` via shell's DEBUG trap, because\nit makes the shell to call the function too often. For example, Bash\nexecutes the DEBUG trap for each command in a command group. In\naddition, the trap might already be utilized by other shell extensions.\nTo demonstrate the problem with command groups:\n\n``` bash\n# WARNING: Don't install chnode_auto like this, because the function gets called too often\ntrap '[[ $BASH_COMMAND != \"${PROMPT_COMMAND:-}\" ]] \u0026\u0026 echo CALLED \u0026\u0026 chnode_auto' DEBUG\n\n# Execute a command group\n{ echo lol; echo bal; }\nCALLED\nlol\nCALLED\nbal\n```\n\nTo set a default node version for a project, create a `.node-version`\nfile in the root directory of the project:\n\n``` bash\necho node-8.1.0 \u003e node-project/.node-version\n```\n\nThe first line of the `.node-version` file should contain a version\nstring that the `chnode_auto` function uses to select a Node.js\nversion. The function invokes `chnode $version`, where `$version` is the\nfirst line from the file. This means that fuzzy matching is\nsupported. If no version matches, an error is reported.\n\nYou can set the default node version by adding a `.node-version` file to\nthe root of your home directory. The version you specify in the file\nwill be used unless any of your Node.js projects, located somewhere\nunder your home directory, has their own `.node-version` file.\n\n## Supported `.node-version` file format\n\nSpecifications for the `chnode_auto` function parsing the version string\nfrom the `.node-version` file are:\n\n1. The file must be a regular file or a symbolic link, and the current\n   user must have read access to it.\n\n2. The version string must be in the first line. The line may have\n   leading and trailing whitespace, which get trimmed out. Trailing\n   newline character is not required. Both Unix (`\\n`) and Windows\n   (`\\r\\n`) style line endings are supported.\n\n3. If the version string starts with the `v` character followed by a\n   digit, then the `v` character gets trimmed out.\n\n4. The lines following the first are ignored.\n\n5. If the first line cannot be parsed (no version string is found), then\n   the file is ignored. No error is reported.\n\n## Display current Node.js in shell prompt\n\nYou can pick up the selected Node.js version from the `CHNODE_ROOT`\nenvironment variable. An example script to customize shell prompt is in\n[set-prompt.sh]. Usage:\n\n```\n$ source chnode.sh\n$ source contrib/set-prompt.sh\ntkareine@sky ~/Projects/chnode (node:10.11.0)\n$\n```\n\n## License\n\nMIT. See [LICENSE.txt].\n\n[shUnit2], located as a git submodule in the `test/shunit2` directory:\nCopyright 2008-2021 Kate Ward. Released under the Apache 2.0 license.\n\n[Bash Controlling the Prompt]: https://www.gnu.org/software/bash/manual/html_node/Controlling-the-Prompt.html\n[Bash-Preexec]: https://github.com/rcaloras/bash-preexec\n[GNU Bash]: https://www.gnu.org/software/bash/\n[Homebrew-tap-chnode]: https://github.com/tkareine/homebrew-chnode\n[Homebrew]: https://brew.sh/\n[LICENSE.txt]: https://raw.githubusercontent.com/tkareine/chnode/master/LICENSE.txt\n[Zsh Hook Functions]: http://zsh.sourceforge.net/Doc/Release/Functions.html#Hook-Functions\n[Zsh]: https://www.zsh.org/\n[auto.sh]: https://raw.githubusercontent.com/tkareine/chnode/master/auto.sh\n[chnode-CI]: https://github.com/tkareine/chnode/actions/workflows/ci.yml\n[chnode.sh]: https://raw.githubusercontent.com/tkareine/chnode/master/chnode.sh\n[chruby]: https://github.com/postmodern/chruby\n[node-build]: https://github.com/nodenv/node-build\n[nodejs-download]: https://nodejs.org/en/download/current/\n[nodenv]: https://github.com/nodenv/nodenv\n[npm-config-folders-prefix]: https://docs.npmjs.com/cli/v8/configuring-npm/folders#prefix-configuration\n[npm-npmrc]: https://docs.npmjs.com/cli/v8/configuring-npm/npmrc\n[nvm]: https://github.com/nvm-sh/nvm\n[nvmrc]: https://github.com/nvm-sh/nvm#nvmrc\n[set-prompt.sh]: https://raw.githubusercontent.com/tkareine/chnode/master/contrib/set-prompt.sh\n[shUnit2]: https://github.com/kward/shunit2\n[tkareine-lightweight-nodejs-version-switching]: https://tkareine.org/articles/lightweight-nodejs-version-switching.html\n","funding_links":[],"categories":["Version Managers"],"sub_categories":["Node.js"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftkareine%2Fchnode","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftkareine%2Fchnode","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftkareine%2Fchnode/lists"}