mrkeyoor.com_
Tue 22 Sept 00:44 UTC
npmTestingupdated 21 Sept 2026

nyc review

nyc is Istanbul's command-line coverage runner for Node.js. It starts a test command, instruments eligible source files as CommonJS loads them, gathers line, branch, function, and statement counters, remaps results through source maps, and writes terminal, HTML, LCOV, or JSON reports. Its process wrapper can collect coverage from commands spawned by the test suite, which remains a useful distinction for CLI integration tests. Version 18.0.0 updates dependencies, replaces an older glob line, and raises the runtime requirement to Node 20 or Node 22 and later. The core instrumentation model is mature and CommonJS-oriented; native ESM projects usually fit V8-based coverage better.

Verdict

Keep nyc where CommonJS tests, subprocess collection, and Istanbul-specific controls are already working. New ESM projects should start with c8 or their runner's own V8 coverage and avoid a 134-package compatibility layer.

We installed it

Lab card: what happened when we installed nycScreenshot of nyc documentation
Install✓ · 8.2s134 packages on disk · 31 MB
ImportESM import works · require() works · CommonJS package
Browsern/acould not be bundled for the browser (Node-only code, most likely)
Typesno TypeScript types found
Known vulns00 critical · 0 high · 0 moderate · 0 low (npm audit)

Answers from our run

Does nyc install cleanly?

Yes. In a fresh container with an empty cache, npm install nyc finished in 8 seconds, leaving 134 packages and 31 MB on disk. npm audit reported no known vulnerabilities.

Can nyc run in a browser?

Not directly: esbuild could not bundle it for the browser in our run, which normally means it depends on Node built-ins. Use it on the server, or find a browser-targeted alternative.

Does nyc work with both ESM and CommonJS?

Yes. Both import 'nyc' and require('nyc') worked in Node 22 in our run. The package is published as CommonJS.

Does nyc include TypeScript types?

No type declarations were found in our install, so TypeScript users need their own declarations.

nyc or c8: which should you use?

c8: Use it for V8-native coverage across CommonJS and ESM while keeping Istanbul-compatible report formats. Keep nyc where CommonJS tests, subprocess collection, and Istanbul-specific controls are already working.

When should you not use nyc?

Source executes as native ES modules. nyc's main path instruments files through CommonJS loading, while c8 reads V8 coverage from both module systems.

API stability5/5The command shape, `.nycrc` keys, include and exclude rules, reporters, thresholds, cache directories, subprocess collection, and Istanbul ignore hints have changed little across recent major releases. Version 18's breaking change is its Node engine floor rather than a rewritten coverage workflow. Old configurations therefore migrate easily when their runtime is supported, although native ESM remains outside the mechanism's comfortable path.
Docs3/5The README documents every accepted config-file name, default directories, project-root discovery, selection ordering, negated excludes, shared presets, thresholds, cache controls, and multiple-run collection. It also sends readers to `nyc --help` for the complete option set. Native ESM limitations are not explained with the prominence they deserve, and the linked Istanbul tutorial site mixes older material with current package behavior.
Maintenance3/5GitHub shows 5,766 stars, 208 open issues and pull requests, an unarchived repository, and a push in May 2026. Release 18.0.0 arrived in February 2026 to replace an old glob dependency and adopt its Node floor; 17.0.0 similarly addressed dependency alerts. Security and runtime upkeep are visible, while user-facing feature development is sparse compared with the pace of Node's module and built-in test tooling.
Ecosystem4/5The npm endpoint counted 8,551,870 downloads for the latest completed week. LCOV, JSON, HTML, and terminal reporters integrate with common CI services and editor coverage views, and maintained presets connect Babel and TypeScript transforms. Jest and tap explicitly include Istanbul libraries themselves, while Vitest, Node test, and c8 reduce the need for nyc in new projects, so the report ecosystem is broader than this particular CLI.

Use it if

  • A CommonJS Mocha, AVA, tape, or plain Node test command needs Istanbul reports and has no coverage integration of its own.
  • Integration tests spawn a Node CLI and coverage from those child processes must join the parent report.
  • Separate unit and integration commands need to deposit raw results and produce one final LCOV file.
  • The project already relies on Istanbul ignore comments, shared nyc presets, or established threshold behavior.
Skip it if

Setup reality

We installed nyc 18.0.0 in a fresh Node 22 Bookworm container. npm completed in 8.2 seconds, left 134 packages, and used 31 MB on disk. The nyc package itself is 128 KB unpacked, declares 27 direct dependencies and no peers, and requires Node 20 || >=22. npm audit reported zero known vulnerabilities. CommonJS require and ESM import both loaded the package, but it ships no TypeScript declarations.

The first report excludes every source file that tests never load. Set all: true and a narrow include if untouched modules must count as zero. Defining your own exclude array replaces the defaults from @istanbuljs/schema; it does not append to them. CLI globs need shell quotes. nyc finds its project root by walking upward to a package.json, so monorepo commands should set cwd when that implicit root is wrong.

Raw counters go to .nyc_output, reports to coverage, and transformed code to node_modules/.cache/nyc. Ignore all three outputs as appropriate and clear the instrumentation cache after Babel, TypeScript, source-map, or transform changes. For multiple commands, let the first run clean, pass --no-clean to later runs, use --silent while collecting, then call nyc report. Missing --no-clean leaves only the last command's data.

TypeScript and Babel projects need the matching @istanbuljs/nyc-config-* preset plus the compiler hook. With all: true, the hook must be required by nyc so unloaded files can be transformed. Native ESM can still return missing or partial coverage because the CommonJS hook is not on the import path. Our esbuild browser attempt failed, which matches a Node CLI that wraps processes, reads the filesystem, and instruments server-side modules.

Patterns

Run Mocha under coverage wrap-test-command

// package.json
{
  "scripts": {
    "test": "mocha",
    "coverage": "nyc npm test"
  }
}

Place nyc flags before the command it launches. Do not wrap a script that already invokes nyc or instrumentation will be nested.

Count every source module configure-file-selection

{
  "all": true,
  "include": ["src/**/*.js"],
  "exclude": ["**/*.spec.js", "**/fixtures/**"],
  "reporter": ["text-summary", "lcov"]
}

Save this as `.nycrc`. A custom exclude array replaces nyc's defaults, so add any default test or generated paths you still need.

Protect globs from the shell quote-coverage-globs

npx nyc --all --include 'src/**/*.js' --exclude '**/*.spec.js' npm test

Unquoted patterns can expand before nyc sees them, producing different selection rules across shells and working directories.

Fail a build below the target enforce-coverage-threshold

{
  "check-coverage": true,
  "branches": 80,
  "functions": 85,
  "lines": 90,
  "statements": 90,
  "per-file": false
}

Threshold numbers have no effect unless check-coverage is enabled. Turning on per-file applies each threshold to every selected file.

Apply the TypeScript preset report-typescript

// .nycrc
{
  "extends": "@istanbuljs/nyc-config-typescript",
  "all": true,
  "check-coverage": true
}

// command
npx nyc mocha -r ts-node/register 'test/**/*.spec.ts'

Install the preset, source-map support, and the runtime compiler. Native ESM TypeScript can bypass nyc's CommonJS instrumentation hook.

Emit text and LCOV output write-ci-reports

npx nyc \
  --reporter=text-summary \
  --reporter=lcov \
  mocha 'test/**/*.js'

The reporter option is repeatable. LCOV output includes `coverage/lcov.info` plus browsable HTML under the report directory.

Accumulate unit and integration coverage merge-test-runs

npx nyc --silent npm run test:unit
npx nyc --silent --no-clean npm run test:integration
npx nyc report --reporter=text --reporter=lcov

The later collection commands require `--no-clean`; otherwise each one removes the raw counters written by the previous run.

Use Istanbul ignore hints ignore-unreachable-code

/* istanbul ignore next */
function debugOnly() {
  return process.env.DEBUG;
}

/* istanbul ignore else */
if (process.platform === 'win32') {
  useWindowsPath();
} else {
  usePosixPath();
}

Ignore comments alter the coverage denominator. Keep a reason in review because V8 coverage tools may interpret or ignore these hints differently.

Trace spawned Node commands collect-child-processes

npx nyc --show-process-tree mocha test/cli.spec.js

nyc uses process wrapping to propagate coverage into spawned Node processes. This extra layer can expose platform-specific command and argument issues.

Pin paths to one package set-monorepo-root

npx nyc \
  --cwd packages/api \
  --all \
  --include 'src/**/*.js' \
  npm test

Without cwd, nyc walks upward for package.json. Running from a monorepo root can select files and write artifacts in the wrong package.

Disable stale transformed code clear-instrumentation-cache

npx nyc --cache=false npm test

Use this after changing Babel, TypeScript, or source-map configuration when line mappings no longer match. The regular cache lives under node_modules/.cache/nyc.

Use V8 coverage for native ESM switch-esm-to-c8

npm install --save-dev c8
npx c8 --reporter=text --reporter=lcov mocha 'test/**/*.mjs'

A blank nyc report on imported `.mjs` files can come from the missing CommonJS hook rather than from untested code.

Alternatives

PackageRegistryPick it when
c8npmUse it for V8-native coverage across CommonJS and ESM while keeping Istanbul-compatible report formats.
@vitest/coverage-v8npmUse it when Vitest already owns test execution and coverage belongs in the same configuration.
babel-plugin-istanbulnpmUse it to instrument code during compilation, including code that will run in a browser bundle.
jestnpmUse its built-in coverage when choosing a full test runner rather than adding coverage to an existing one.

More testing guides

pytest · chai · vitest · jsdom · playwright · coverage · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.