CLI tool
cnpm/cnpm avatar
cnpm/cnpm

cnpm: the npm client that points at npmmirror.com and uses symlink-based installs

cnpm: npm client for China mirror of npm

2,095 stars210 forksJavaScriptMIT

At a glance

What is it?
cnpm is a global npm client that routes package installs through the npmmirror.com mirror registry in China and uses the npminstall engine by default. The README now recommends migrating to utoo, citing package-lock.json incompatibility as the primary reason.
Who is it for?
cnpm makes sense for developers in China who need faster installs from npmmirror.com and can accept npminstall's symlink-based node_modules layout. Skip it when your project depends on exact package-lock.json compatibility, since the README's own recommendation to migrate to utoo names that gap directly.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 6 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 6, 2026, and from our analysis. They are not legal advice.

Editorial analysis

cnpm routes installs through the npmmirror.com registry and uses npminstall as the default engine

cnpm is a command-line npm client designed to work with the npmmirror.com registry, a China-hosted mirror of the npm registry. Its two main purposes are to give developers in China faster package installs and to serve as the client for private or self-hosted npm registries that follow the same API. The registry URL is the homepage listed in both the README and `package.json`.

Behind the scenes, cnpm uses `npminstall` as its default installer rather than the standard npm install mechanism. `npminstall` creates symlinks in `node_modules` rather than npm's flat directory structure. That difference in layout is consequential: the two approaches resolve peer dependencies differently, and the resulting `node_modules` tree is not interchangeable with what vanilla npm produces. Code that scans `node_modules` directly, or that relies on specific directory structures, may behave differently under cnpm's default installer.

The binary entry point is `bin/cnpm.js`. Source code lives under `bin/` and `lib/`, with tests under `test/`. All dependencies listed in `bundleDependencies` ship inside the npm package itself rather than being resolved at install time, which means a global install of `cnpm` is self-contained and does not require the user's npm to separately resolve those packages.

npm install cnpm -g from npmjs.com, or from the China mirror to bootstrap faster

Installing cnpm globally is done through npm itself. The standard install line from the README is:

bash
npm install cnpm -g

For users in China, fetching from the global npm registry is often slow, so the README gives a version that bootstraps from the mirror directly:

bash
npm install cnpm -g --registry=https://registry.npmmirror.com

The engine requirement in `package.json` is `>= 14.18.0`. The README's requirements table lists the minimum Node.js version as 20 and the recommended version as LTS. These two figures do not agree with each other. For a new environment, the README table is the more conservative guide, since it reflects the project's current testing baseline rather than a historical `package.json` entry.

Version v9.4.0 appeared on 2023-12-28. The two releases before it, v9.3.2 and v9.3.1, also arrived in December 2023. No release has been tagged since then, though the repository received a push as recently as 2026-10-06.

cnpm supports all npm commands, plus sync and doc for registry-specific tasks

cnpm's command surface extends standard npm with two registry-specific additions. Standard package management operations run through the cnpm binary rather than the system npm, pointing requests at the configured registry. The binary entry, `bin/cnpm.js`, delegates to the appropriate underlying tool based on the `--by` flag and the command given.

`cnpm sync [moduleName]` requests a sync of a named package from the upstream npm registry to the cnpm mirror. When a package is published to npm but not yet visible on the mirror, this command forces an immediate pull rather than waiting for the scheduled sync window.

bash
cnpm sync [moduleName]

`cnpm doc [name]` opens a package's documentation in the browser. Passing `-g` opens the package's git repository URL instead.

bash
cnpm doc [name]
cnpm doc -g [name]

Outside these two additions, the command surface matches standard npm: install, update, run, publish and similar operations work the same way, directed at the configured registry endpoint rather than the default npm registry.

npminstall's symlink mode differs from npm's flat layout, and --by=npm removes the speed benefit

By default, cnpm uses `npminstall` as the install engine. `npminstall` creates a symlink-based `node_modules` directory rather than the flat layout npm produces. These two structures behave differently when resolving peer dependencies.

In `npminstall`'s symlink mode, each package gets its own copy of its dependencies linked under its own directory rather than hoisted to the top level. In npm's flat layout, common dependencies are deduplicated and hoisted. A package that works correctly in one layout may behave differently in the other, and peer dependencies that npm resolves silently can appear as missing in the symlink layout.

`--by=npm` is the flag that switches cnpm to the original npm installer.

bash
cnpm i --by=npm react-native

The speed benefit that cnpm advertises is tied to `npminstall`, and switching away from it removes that benefit even when the registry endpoint stays at npmmirror.com. The speed benefit comes from `npminstall`'s approach, not from the registry endpoint. Switching the installer to npm while keeping the npmmirror.com registry gives network benefits without the installation speed improvement. That trade-off is the central decision when evaluating cnpm for a project where install time is the stated reason for adopting it.

The README recommends migrating to utoo, citing package-lock.json as the compatibility gap

The README opens with a recommendation to migrate to utoo, described as a modern npm package manager. Three differences are listed as reasons to switch.

The lockfile is the first. cnpm's default installer produces a lockfile format that is not `package-lock.json`. utoo uses `package-lock.json` natively, which means a project that switches from cnpm to utoo does not need to rewrite or regenerate the lockfile. For teams that share lockfiles across environments using different npm tools, this gap between cnpm and standard npm is a real friction point.

The second is binary acceleration: utoo serves pre-built native binaries via npmmirror, which reduces the time spent compiling native modules from source on each install.

The third point positions utoo as working in the same scenarios where cnpm is used today, not as a different category of tool.

This recommendation comes from the cnpm project itself, not from an external source. Projects evaluating cnpm for new adoption should treat this as a meaningful signal. The README does not say cnpm will stop working or receiving pushes, but the forward direction described there is utoo.

Building a private registry alias from --registry, --registryweb, and --userconfig

One documented use case for cnpm beyond the public mirror is pointing it at a private npm registry. The README shows the pattern: install cnpm globally, then create a shell alias that sets three flags.

bash
npm install cnpm -g

# then alias it
alias mynpm='cnpm --registry=https://registry.npm.example.com \
  --registryweb=https://npm.example.com \
  --userconfig=$HOME/.mynpmrc'

`--registry` sets the registry URL that package installs use. `--registryweb` sets the web interface URL of the registry. `--userconfig` points to a custom configuration file at `$HOME/.mynpmrc`, keeping the private registry credentials separate from the default global configuration. The alias runs as `mynpm` while the original `cnpm` continues to point at npmmirror.com.

This pattern gives teams a way to create a named client for an internal registry without touching the global npm configuration. The `--userconfig` flag is what keeps authentication separate between environments: the private registry token stays in `$HOME/.mynpmrc` rather than in the shared global configuration file. That isolation matters when different registries use different authentication tokens and the same machine serves multiple environments.

v9.4.0 from December 2023, MIT licence, bundled dependencies

The latest GitHub release is v9.4.0, tagged on 2023-12-28. Releases v9.3.2 and v9.3.1 also appeared in December 2023, making three releases in a single month. No release has been tagged since then, while the repository received a push on 2026-10-06, suggesting the project is maintained at the code level even without a formal release cadence.

The MIT licence appears in both the README (`[MIT](LICENSE.txt)`) and `package.json`. MIT requires attribution and makes no warranty. `LICENSE.txt` at the top level is the file to read before redistribution.

Runtime dependencies include `npminstall` at `^7.0.0`, `npm` at `^9.6.2`, `commander` at `~2.10.0`, `urllib` at `^3.1.0`, and several smaller packages. All of these appear in both `dependencies` and `bundleDependencies`. A package in `bundleDependencies` ships inside the published tarball, so a global install of `cnpm` does not need to separately fetch these at install time. That bundling is why installing `cnpm` works even in environments where the npm registry is slow or unavailable.

The `package.json` engine field says `>= 14.18.0`, while the README table sets the minimum at 20. Both constraints apply in practice: a Node.js version between 14.18.0 and 20 satisfies the engine field but falls below what the README documents as the project's minimum.

Editorial conclusion

cnpm makes sense for developers in China who need faster installs from npmmirror.com and can accept npminstall's symlink-based node_modules layout. Skip it when your project depends on exact package-lock.json compatibility, since the README's own recommendation to migrate to utoo names that gap directly. Before adopting cnpm in CI or a team environment, run an install against your full dependency tree and compare the resulting node_modules layout with npm's output, because the symlink structure exposes peer dependencies differently from npm's flat layout and can reveal conflicts that npm would have silently resolved.

Frequently asked questions

What is cnpm?

cnpm is a global npm client that installs packages from the npmmirror.com registry, a China-hosted mirror of the npm registry. It uses the npminstall engine by default instead of standard npm.

How do I install cnpm?

Run `npm install cnpm -g` to install from the global npm registry. For users in China, the README also gives a version that installs from the mirror: `npm install cnpm -g --registry=https://registry.npmmirror.com`.

Does cnpm support all npm commands?

The README states cnpm supports all commands just like npm. It adds two registry-specific commands: `cnpm sync [moduleName]` to trigger a package sync, and `cnpm doc [name]` to open a package's documentation page.

What is the difference between cnpm and npm?

cnpm points at the npmmirror.com registry by default and uses the npminstall engine, which creates a symlink-based node_modules rather than npm's flat directory structure. Using `--by=npm` switches back to the standard installer but removes the speed benefit.

Should I migrate from cnpm to utoo?

The cnpm README recommends migrating to utoo, citing full package-lock.json compatibility with no lockfile rewrites. The README lists this alongside npmmirror binary acceleration as reasons to prefer utoo.

Official sources

  1. cnpm/cnpm on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/cnpm-cnpm.svg)](https://hysenlabs.com/projects/cnpm-cnpm)