# Understanding the NVM_CD_FLAGS Mechanism for Zsh Compatibility

> Explore the NVM_CD_FLAGS mechanism for zsh compatibility. Learn how this NVM setup prevents 'no matches found' errors for enhanced shell reliability.

- Repository: [nvm.sh/nvm](https://github.com/nvm-sh/nvm)
- Tags: internals
- Published: 2026-02-27

---

**NVM_CD_FLAGS is an environment variable that nvm sets to `-q` specifically in zsh shells to suppress "no matches found" errors when changing directories, ensuring reliable operation across different shell environments.**

The NVM_CD_FLAGS mechanism for zsh compatibility is a targeted fix within the nvm-sh/nvm repository that prevents glob expansion failures from interrupting Node version management. When running in zsh, nvm automatically detects the shell environment and applies quiet flags to internal directory changes to avoid spurious errors. This ensures consistent behavior whether users run bash, dash, or zsh as their default shell.

## Why Zsh Requires Special Handling

Zsh includes a **nomatch** option that changes how the builtin `cd` command handles pathname expansion. When `nomatch` is enabled (the default in many zsh configurations), `cd` aborts with **"zsh: no matches found"** if a glob pattern yields no results.

Nvm frequently invokes `cd` while resolving paths like `$(dirname "$0")` or temporary directories. These paths are never intended as globs, but zsh still evaluates them for expansion patterns. Without the quiet flag, a simple directory change inside nvm's internal logic can trigger a fatal error that breaks commands like `nvm use` or `nvm install`.

## How NVM_CD_FLAGS Works

The mechanism relies on a thin wrapper function `nvm_cd` that prepends the `-q` flag to the builtin `cd` command only when zsh is detected. This flag instructs zsh to ignore non-matching globs silently rather than erroring out.

### Shell Detection and Flag Initialization

In [`nvm.sh`](https://github.com/nvm-sh/nvm/blob/main/nvm.sh), the initialization logic checks the current shell and sets the variable accordingly around lines 437-445:

```bash
if [ -z "${NVM_CD_FLAGS-}" ]; then
  export NVM_CD_FLAGS=''
fi
if nvm_is_zsh; then
  NVM_CD_FLAGS="-q"
fi

```

The `nvm_is_zsh` function detects zsh-specific features to determine when to apply the flag. When detected, `NVM_CD_FLAGS` receives the value `-q`; otherwise, it remains an empty string.

### Application During Directory Navigation

Nvm consumes this flag when computing critical paths, such as the auto-detection of `NVM_DIR` around lines 452-454 in [`nvm.sh`](https://github.com/nvm-sh/nvm/blob/main/nvm.sh):

```bash
NVM_DIR="$(nvm_cd ${NVM_CD_FLAGS} "$(dirname "${NVM_SCRIPT_SOURCE:-$0}")" >/dev/null && \pwd)"

```

The expansion results in `\cd -q <directory>` under zsh, which suppresses glob-related errors. On other shells, the empty variable produces a standard `\cd <directory>` call without side effects.

## Scope and Cleanup in Child Processes

To prevent the zsh-specific flag from leaking into child processes or interfering with user scripts, the `nvm-exec` helper explicitly unsets the variable at line 5:

```bash
unset NVM_CD_FLAGS

```

This ensures that commands spawned through `nvm-exec` inherit a clean environment where the `-q` flag cannot affect non-nvm operations or sub-shells.

## Practical Verification and Usage

You can observe this mechanism directly in a running zsh session:

```bash
source ~/.nvm/nvm.sh
echo $NVM_CD_FLAGS

```

Output:

```

-q

```

To apply the same protection in custom scripts that coexist with nvm:

```bash
cd $NVM_CD_FLAGS "$HOME/.nvm/versions/node/v20.0.0"

```

If you need to disable the mechanism for debugging, unset the variable:

```bash
unset NVM_CD_FLAGS
cd non*existent*  # Now raises: zsh: no matches found

```

## Summary

- **NVM_CD_FLAGS** is set to `-q` exclusively in zsh to silence glob expansion errors during directory changes.
- The flag is defined in [`nvm.sh`](https://github.com/nvm-sh/nvm/blob/main/nvm.sh) (lines 437-445) and applied during path resolution (lines 452-454).
- The `nvm_cd` wrapper function executes `\cd` with the flag only when necessary, maintaining portability across bash, dash, and ksh.
- **nvm-exec** unsets the variable at line 5 to prevent inheritance by child processes.
- This mechanism ensures that users with `setopt nomatch` enabled experience no interruptions during `nvm install`, `nvm use`, or similar operations.

## Frequently Asked Questions

### What causes "no matches found" errors in nvm when using zsh?

Zsh's **nomatch** option causes the `cd` builtin to throw an error when a glob pattern (like `*` or `?`) finds no matches. Nvm internally uses `cd` with variables that might contain characters resembling globs. Without the `-q` flag stored in `NVM_CD_FLAGS`, these internal directory changes trigger false-positive "no matches found" errors that abort nvm operations.

### Is NVM_CD_FLAGS set in shells other than zsh?

No. The `nvm_is_zsh` check ensures `NVM_CD_FLAGS` remains an empty string in bash, dash, ksh, and other POSIX shells. The `-q` flag is specific to zsh's `cd` builtin and is not recognized by other shells, so nvm only populates the variable when zsh is detected.

### How can I check if NVM_CD_FLAGS is active in my session?

Run `echo $NVM_CD_FLAGS` after sourcing nvm. If you are in a zsh shell with nvm loaded, it will output `-q`. In other shells, it will output nothing. You can also verify by checking the value of `$NVM_DIR` with `echo $NVM_DIR` to confirm the path was resolved without glob errors.

### Why does nvm-exec unset NVM_CD_FLAGS?

The `nvm-exec` script unsets `NVM_CD_FLAGS` at line 5 to ensure that child processes and commands launched through nvm do not inherit the zsh-specific `-q` flag. This prevents the flag from affecting non-nvm scripts or being passed to programs that might interpret `-q` differently, maintaining clean environment isolation.