# @antfu/ni

> Use the right package manager

Latest version **30.6.0** (published 2026-09-16) · MIT license · 0 weekly downloads

## Install

```sh
npm install @antfu/ni
pnpm add @antfu/ni
yarn add @antfu/ni
bun add @antfu/ni
```

Provides the commands `na`, `nd`, `ni`, `nr`, `nci`, `nlx`, `nun`, `nup`.

## Health

**Score 75/100 (B)** — status: active.

Positive: has types; esm support; no vulnerabilities; has provenance; recently updated; high maintenance score; high quality score.

Warnings: low downloads.

## Facts

| | |
|---|---|
| Version | 30.6.0 |
| Published | 2026-09-16 |
| First published | 2020-11-05 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM |
| Node | >=20.19.0 |
| Dependencies | 4 |
| Unpacked size | 403.8 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Provenance | attested (GitHub Actions) |
| GitHub stars | 8300 |
| Author | Anthony Fu <anthonyfu117@hotmail.com> |
| Maintainers | antfu |

## Links

- npm: https://www.npmjs.com/package/@antfu/ni
- Repository: https://github.com/antfu-collective/ni
- Homepage: https://github.com/antfu-collective/ni#readme
- Issues: https://github.com/antfu-collective/ni/issues
- npm.io page: https://npm.io/package/@antfu/ni

## Dependencies (4)

- [fzf](https://npm.io/package/fzf.md) ^0.5.2
- [tinyexec](https://npm.io/package/tinyexec.md) ^1.3.0
- [tinyglobby](https://npm.io/package/tinyglobby.md) ^0.2.17
- [package-manager-detector](https://npm.io/package/package-manager-detector.md) ^1.8.0

## Recent versions

- 30.6.0 (latest) — 2026-09-16
- 30.5.0 — 2026-08-06
- 30.4.0 — 2026-08-06
- 30.3.0 — 2026-07-22
- 30.2.0 — 2026-06-25
- 30.1.0 — 2026-04-22
- 30.0.0 — 2026-03-23
- 29.0.0 — 2026-03-13
- 28.3.0 — 2026-03-06
- 28.2.0 — 2026-01-14
- 28.1.0 — 2026-01-06
- 28.0.0 — 2025-12-02
- 27.0.1 — 2025-10-26
- 27.0.0 — 2025-10-19
- 26.2.0 — 2025-10-16
- … 89 more at https://npm.io/package/@antfu/ni/versions

## README

# ni

~~*`npm i` in a yarn project, again? F\*\*k!*~~

**ni** - use the right package manager

<br>

<pre>
<code>
npm i -g <b>@antfu/ni</b>
</code>
</pre>

<a href='https://docs.npmjs.com/cli/v6/commands/npm'>npm</a> · <a href='https://yarnpkg.com'>yarn</a> · <a href='https://pnpm.io/'>pnpm</a> · <a href='https://bun.sh/'>bun</a> · <a href='https://deno.land/'>deno</a> · <a href='https://nubjs.com/'>nub</a> · <a href='https://aube.jdx.dev/'>aube</a>

<br>

### `ni` - install

```bash
ni

# npm install
# yarn install
# pnpm install
# bun install
# deno install
# nub install
# aube install
```

```bash
ni vite

# npm i vite
# yarn add vite
# pnpm add vite
# bun add vite
# deno add vite
# nub add vite
# aube add vite
```

```bash
ni @types/node -D

# npm i @types/node -D
# yarn add @types/node -D
# pnpm add -D @types/node
# bun add -d @types/node
# deno add -D @types/node
# nub add -D @types/node
# aube add -D @types/node
```

```bash
ni -P

# npm i --omit=dev
# yarn install --production
# pnpm i --production
# bun install --production
# (deno not supported)
# nub install --production
# aube install --production
```

```bash
ni --frozen

# npm ci
# yarn install --frozen-lockfile (Yarn 1)
# yarn install --immutable (Yarn Berry)
# pnpm install --frozen-lockfile
# bun install --frozen-lockfile
# deno install --frozen
# nub install --frozen-lockfile
# aube install --frozen-lockfile
```

```bash
ni -g eslint

# npm i -g eslint
# yarn global add eslint (Yarn 1)
# pnpm add -g eslint
# bun add -g eslint
# deno install eslint
# nub add -g eslint
# aube add -g eslint

# this uses default agent, regardless your current working directory
```

```bash
ni -i

# interactively select the dependency to install
# search for packages by name
```

<details>
<summary>catalogs support</summary>

> Since v29.0.0

When working in a pnpm workspace with [catalogs](https://pnpm.io/catalogs) configured in `pnpm-workspace.yaml`, a Yarn Berry workspace with catalogs in `.yarnrc.yml`, or a [Bun workspace with catalogs](https://bun.com/docs/pm/catalogs) in `package.json`, `ni` automatically enters **catalog mode**. Instead of adding packages with pinned versions, it writes `catalog:` references into `package.json` and updates the workspace catalog.

```bash
# Given pnpm-workspace.yaml with:
#   catalogs:
#     prod:
#       react: ^18.3.0

ni react
# → detects react in "prod" catalog
# → writes "react": "catalog:prod" to package.json
# → runs pnpm install

ni lodash
# → lodash not in any catalog
# → prompts to select a catalog (or skip)
# → fetches latest version, updates pnpm-workspace.yaml
# → writes "lodash": "catalog:prod" to package.json
# → runs pnpm install
```

For Bun, catalogs live in the root `package.json` instead, either nested under `workspaces` or at the top level:

```bash
# Given root package.json with:
#   "workspaces": {
#     "packages": ["packages/*"],
#     "catalogs": { "prod": { "react": "^18.3.0" } }
#   }

ni react
# → detects react in "prod" catalog
# → writes "react": "catalog:prod" to package.json
# → runs bun install
```

When only a default catalog (`catalog:` top-level) is used, new packages are added directly without prompting. When only named catalogs exist, the default catalog is never offered.

Flags like `-D` are respected — the catalog ref is written to the correct `package.json` section:

```bash
ni typescript -D
# → writes "typescript": "catalog:dev" to devDependencies
```

Use `-w` / `--workspace` to target the workspace root `package.json`:

```bash
ni react -w
# → writes catalog ref to workspace root package.json
```

To only reuse catalog entries that already exist — never adding a new package to a catalog and never prompting for one — set `catalog=existing` in `~/.nirc` or `NI_CATALOG=existing` environment variable:

```bash
# with catalog=existing

ni react
# → react is already in the "prod" catalog
# → writes "react": "catalog:prod" to package.json

ni lodash
# → lodash is in no catalog
# → installed normally with a pinned version, catalogs are left untouched
```

To disable catalog mode, set `catalog=false` in `~/.nirc` or `NI_CATALOG=false` environment variable.

</details>

<br>

### `nr` - run

```bash
nr dev --port=3000

# npm run dev -- --port=3000
# yarn run dev --port=3000
# pnpm run dev --port=3000
# bun run dev --port=3000
# deno task dev --port=3000
# nub run dev --port=3000
# aube run dev --port=3000
```

```bash
nr

# interactively select the script to run
# supports https://www.npmjs.com/package/npm-scripts-info convention
```

```bash
nr -

# rerun the last command
```

```bash
nr -p
nr -p dev

# interactively select the package and script to run
```

<details>
<summary>shell completion scripts</summary>

```bash
# Add completion script for bash
nr --completion-bash >> ~/.bashrc

# Add completion script for zsh
# For zim:fw
mkdir -p ~/.zim/custom/ni-completions
nr --completion-zsh > ~/.zim/custom/ni-completions/_ni
echo "zmodule $HOME/.zim/custom/ni-completions --fpath ." >> ~/.zimrc
zimfw install

# Add completion script for fish
mkdir -p ~/.config/fish/completions
nr --completion-fish > ~/.config/fish/completions/nr.fish
```

</details>

<br>

### `nlx` - download & execute

```bash
nlx vitest

# npx vitest
# yarn dlx vitest
# pnpm dlx vitest
# bunx vitest
# deno run npm:vitest
# nubx vitest
# aube dlx vitest
```

Pass `--local` to prefer an already-installed local binary over downloading it (equivalent to `pnpm exec` / `yarn exec`). `npm`, `bun` and `aube` already resolve local binaries first, so this flag mainly matters for `pnpm`, `yarn`, and `nub`:

```bash
nlx --local vitest

# npx vitest
# yarn exec vitest
# pnpm exec vitest
# bunx vitest
# nub exec vitest
# aube exec vitest
```

<br>

### `nup` - upgrade

```bash
nup

# npm upgrade
# yarn upgrade (Yarn 1)
# yarn up (Yarn Berry)
# pnpm update
# bun update
# deno upgrade
# nub update
# aube update
```

```bash
nup -i

# (not available for npm)
# yarn upgrade-interactive (Yarn 1)
# yarn up -i (Yarn Berry)
# pnpm update -i
# bun update -i
# deno outdated -u -i
# nub update -i
# aube update -i
```

<br>

### `nun` - uninstall

```bash
nun webpack

# npm uninstall webpack
# yarn remove webpack
# pnpm remove webpack
# bun remove webpack
# deno remove webpack
# nub remove webpack
# aube remove webpack
```

```bash
nun

# interactively multi-select
# the dependencies to remove
```

```bash
nun -g silent

# npm uninstall -g silent
# yarn global remove silent
# pnpm remove -g silent
# bun remove -g silent
# deno uninstall -g silent
# nub remove -g silent
# aube remove -g silent
```

<br>

### `nci` - clean install

```bash
nci

# npm ci
# yarn install --frozen-lockfile
# pnpm install --frozen-lockfile
# bun install --frozen-lockfile
# deno cache --reload
# nub install --frozen-lockfile
# aube install --frozen-lockfile
```

<br>

### `nd` - dedupe dependencies

```bash
nd

# npm dedupe
# yarn dedupe
# pnpm dedupe
# nub dedupe
# aube dedupe
```

<br>

### `na` - agent alias

```bash
na

# npm
# yarn
# pnpm
# bun
# deno
# nub
# aube
```

```bash
na run foo

# npm run foo
# yarn run foo
# pnpm run foo
# bun run foo
# deno task foo
# nub run foo
# aube run foo
```

<br>

### Global Flags

```bash
# ?               | Print the command execution depends on the agent
ni vite ?

# -C              | Change directory before running the command
ni -C packages/foo vite
nr -C playground dev

# -v, --version   | Show version number
ni -v

# -h, --help      | Show help
ni -h
```

<br>

### Config

```ini
; ~/.nirc

; fallback when no lock found
defaultAgent=npm # default "prompt"

; for global installs
globalAgent=npm

; use node --run instead of package manager run command (requires Node.js 22+)
runAgent=node

; prefix commands with sfw
useSfw=true

; use catalog mode when catalogs are detected (default true)
; "existing" only reuses packages already in a catalog, never adds new ones
catalog=true
```

```bash
# ~/.bashrc

# custom configuration file path
export NI_CONFIG_FILE="$HOME/.config/ni/nirc"

# environment variables have higher priority than config file if presented
export NI_DEFAULT_AGENT="npm" # default "prompt"
export NI_GLOBAL_AGENT="npm"
export NI_USE_SFW="true"
export NI_CATALOG="false" # disable catalog mode, "existing" to only reuse existing catalog entries
```

```ps
# for Windows

# custom configuration file path in PowerShell accessible within the `$profile` path
$Env:NI_CONFIG_FILE = 'C:\to\your\config\location'
```

<br>

### Automatic installation

You can set `NI_AUTO_INSTALL=true` to enable automatic installation.

If the corresponding package manager (**npm**, **yarn**, **pnpm**, **bun**, **deno**, **nub**, or **aube**) is not installed, it will install it globally before running the command.

### Integrations

#### Homebrew

You can install ni with [Homebrew](https://brew.sh/):

```bash
brew install ni
```

#### asdf

You can also install ni via the [3rd-party asdf-plugin](https://github.com/CanRau/asdf-ni.git) maintained by [CanRau](https://github.com/CanRau)

```bash
# first add the plugin
asdf plugin add ni https://github.com/CanRau/asdf-ni.git

# then install the latest version
asdf install ni latest

# and make it globally available
asdf global ni latest
```

### How?

**ni** assumes that you work with lock-files (and you should).

Before `ni` runs the command, it detects your `yarn.lock` / `pnpm-lock.yaml` / `pnpm-workspace.yaml` / `package-lock.json` / `bun.lock` / `bun.lockb` / `deno.json` / `deno.jsonc` / `nub.lock` / `aube-lock.yaml` / `aube-workspace.yaml` to know the current package manager (or `packageManager` field in your packages.json if specified) using the [package-manager-detector](https://github.com/antfu-collective/package-manager-detector) package and then runs the corresponding [package-manager-detector command](https://github.com/antfu-collective/package-manager-detector/blob/main/src/commands.ts).

### Trouble shooting

#### Conflicts with PowerShell

PowerShell comes with a built-in alias `ni` for the `New-Item` cmdlet. To remove the alias in your current PowerShell session in favor of this package, use the following command:

```PowerShell
'Remove-Item Alias:ni -Force -ErrorAction Ignore'
```

If you want to persist the changes, you can add them to your PowerShell profile. The profile path is accessible within the `$profile` variable. The ps1 profile file can normally be found at

- PowerShell 5 (Windows PowerShell): `C:\Users\USERNAME\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1`
- PowerShell 7: `C:\Users\USERNAME\Documents\PowerShell\Microsoft.PowerShell_profile.ps1`
- VSCode: `C:\Users\USERNAME\Documents\PowerShell\Microsoft.VSCode_profile.ps1`

You can use the following script to remove the alias at shell start by adding the above command to your profile:

```PowerShell
if (-not (Test-Path $profile)) {
  New-Item -ItemType File -Path (Split-Path $profile) -Force -Name (Split-Path $profile -Leaf)
}

$profileEntry = 'Remove-Item Alias:ni -Force -ErrorAction Ignore'
$profileContent = Get-Content $profile
if ($profileContent -notcontains $profileEntry) {
  ("`n" + $profileEntry) | Out-File $profile -Append -Force -Encoding UTF8
}
```

#### `nx`, `nix` and `nu` are no longer available

We renamed `nx`/`nix` and `nu` to `nlx` and `nup` to avoid conflicts with the other existing tools - [nx](https://nx.dev/), [nix](https://nixos.org/) and [nushell](https://www.nushell.sh/). You can always alias them back on your shell configuration file (`.zshrc`, `.bashrc`, etc).

```bash
alias nx="nlx"
# or
alias nix="nlx"
# or
alias nu="nup"
```

---
_Source: https://npm.io/package/@antfu/ni · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
