Run a CLI by name, whether or not the project has it installed:

nubx eslint . --fix        # installed — runs the local copy
nubx vitest run --coverage
nubx cowsay "hi"           # not installed — offers to fetch it

Resolution is local first. Nub walks node_modules/.bin from the current directory up to the workspace root and runs the match directly, with no network and no Node process in the wrapper. Only a local miss reaches the registry.

dispatch a locally-installed CLI · 50 runs

nub exec11.6 ms · tie with bun x
bun x10.6 ms
pnpm exec175 ms · 15× slower
npm exec201 ms · 17× slower

View benchmark →

In a Yarn Plug'n'Play project, bins resolve through pnpapi, as with yarn exec. See module resolution.

Arguments

Everything after the tool name goes to the tool. No -- separator is needed.

nubx eslint . --fix --max-warnings 0

Registry fetches

Unlike npx, nubx asks before it downloads. The first fetch of a tool prompts, runs the tool once you agree, and remembers the answer:

$ nubx cowsay "Hello"
The cowsay bin is not installed locally.
Install and run from the remote registry?
  ● Yes
  ○ No
  ○ Never (don't ask me again)

A pinned version (nubx cowsay@1.5.0) is remembered indefinitely. A floating one (nubx cowsay, which tracks latest) asks again after a day, so a tool that has published new code asks again before running it.

Outside a terminal there is no one to ask, so the fetch fails. That covers CI and any run where stdin is not a terminal:

$ nubx cowsay "hi"          # in CI
nubx: refusing to download cowsay in CI.
  A CI job should declare the tool as a dependency, or pass -y to fetch it.

A fetched package goes through Nub's install resolver, so the cooling window applies and lifecycle scripts are skipped.

-y

The -y flag (--yes) consents up front. It skips the first-run prompt and lets a fetch through in CI.

nubx -y cowsay "hi"

exec.implicitDlx

Answering Never records exec.implicitDlx in the global settings file, ~/.config/nub/nub.jsonc. From then on a local miss stops instead of offering a download. Explicit fetches, through nub dlx or nubx -y, still run.

Restore the prompt:

nub config set exec.implicitDlx prompt

The dlx block in the global nub.jsonc sets the same policy:

~/.config/nub/nub.jsonc
{
  // ...
  "dlx": {
    // no implicit nubx registry fetch; an explicit nub dlx still runs
    "consent": "never"
  }
}

--node

The --node flag runs the tool with runtime augmentation off; see the runtime overview for the full contract. Resolution and the registry fetch still run.

nubx --node prisma generate

nub exec

The local half of nubx on its own: the same node_modules/.bin walk, and never the registry. When nothing matches, it prints an install hint and exits 127.

nub exec eslint . --fix
nub exec --node tsc --noEmit   # augmentation off

It takes the same workspace flags as nub run, such as --filter, -r, and --parallel.

nub dlx

Fetch a package from the registry and run its bin. Typing the command is the consent, so nub dlx never prompts and runs in CI.

nub dlx create-vite my-app
nub x create-vite my-app                       # short alias, as bunx
nub dlx -p @angular/cli ng new my-app          # bin name differs
nub dlx -p cowsay -c 'cowsay hi | tr a-z A-Z'  # one-liner, bin on PATH
nub dlx --node prisma generate                 # augmentation off

An unversioned name that is already installed in the project runs the local copy. A versioned spec such as cowsay@1.5.0, or -p, always fetches. The flags mirror pnpm dlx; see the full docs on pnpm.io.

A fetch shares the persistent cache with nubx and gets the same safeguards as an install:

  • Lifecycle scripts are skipped. Approve one with --allow-build=<pkg>, the same allowlist nub install uses.
  • The cooling window applies. A resolved version must be older than minimumReleaseAge (default 24 hours). When the latest release is inside the window, Nub runs the newest release that clears it and says so. See the cooling window.