CLI tool
privatenumber/pkgroll avatar
privatenumber/pkgroll

privatenumber/pkgroll: Zero-Config Rollup Bundling for Node.js Packages

📦 Zero-config package bundler for Node.js + TypeScript

1,564 stars45 forksTypeScriptNOASSERTION

At a glance

What is it?
pkgroll is a Rollup-powered TypeScript and JavaScript package bundler that derives its entry points from package.json. It is aimed at library authors who want ESM, CommonJS, and declaration outputs without maintaining a separate Rollup configuration.
Who is it for?
Adopt pkgroll when publishing a package whose build inputs are organized under src and whose published entry points are already represented by package.json fields. Do not choose it when a package needs a custom Rollup pipeline, unusual asset transforms, or a build graph that cannot be expressed through supported entry-point mappings.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 9 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

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

Editorial analysis

Why pkgroll targets package authors

pkgroll solves a narrow but common publishing problem: turning source files into a distributable Node.js package while keeping the package metadata and the build configuration aligned. The README says the tool is a JavaScript package bundler powered by Rollup, with entry points defined in package.json and no separate configuration required. That makes it most relevant to authors of libraries and command-line packages written in TypeScript or modern JavaScript. It is not a general application bundler for browsers, and it is not a replacement for every Rollup plugin setup.

The central design choice is to use the package manifest as the build input. Pkgroll reads main, module, types, exports, and related fields. Paths under ./dist/ are mapped back to corresponding files under ./src/. This means the metadata that Node.js and package consumers use can also describe what gets bundled. The trade-off is that the manifest becomes more important. A missing output path, an incorrect condition, or an unexpected wildcard can affect both the package interface and the generated files.

How package.json becomes the build graph

The build process starts from manifest entry points rather than a hand-written Rollup input list. Pkgroll parses main, module, types, exports, and bin, then maps each output path to a source file. For example, a published path such as ./dist/index.mjs can correspond to ./src/index.ts. The --srcdist flag is documented as configurable, so projects are not permanently tied to the conventional src and dist directories.

Conditional exports determine both the module format and the generated artifact. A require condition is associated with CommonJS output, an import condition is auto-detected, and a types condition produces TypeScript declarations. Pkgroll also supports wildcard exports, so a pattern such as ./utils/* can cause multiple source files under src/utils/ to be bundled. The README requires wildcard patterns to include an output extension, which gives the tool enough information to select the output format.

Node.js subpath imports through package.json#imports are supported as well. These can include conditional mappings for different runtimes, such as a node condition and a default browser condition. This is useful for packages that ship internal modules through the package's own # imports syntax. The architecture is still based on file mapping and Rollup bundling, so advanced behavior that is not represented by those manifest patterns is not documented as supported.

Installing pkgroll and building a first package

Install pkgroll as a development dependency in a project that has source files under src and intended output under dist. The documented installation command is:

bash
npm install --save-dev pkgroll

The package manifest then declares the published files and a build script. The following example mirrors the README's setup and defines separate ESM, CommonJS, and declaration outputs. The require and import conditions make the package consumable by both module systems, while bin points to a command that pkgroll will make executable.

json5
{
  "name": "my-package",
  "main": "./dist/index.cjs",
  "module": "./dist/index.mjs",
  "types": "./dist/index.d.cts",
  "exports": {
    "require": {
      "types": "./dist/index.d.cts",
      "default": "./dist/index.cjs"
    },
    "import": {
      "types": "./dist/index.d.mts",
      "default": "./dist/index.mjs"
    }
  },
  "bin": "./dist/cli.js",
  "scripts": {
    "build": "pkgroll"
  }
}

With the manifest in place, run the build using the project script or the documented direct command. The output should be placed under the paths declared by package.json.

bash
npm run build

The README also lists npx pkgroll as an alternative invocation. For projects using pnpm's package.yaml, pkgroll documents support for that manifest in addition to package.json. The repository's package.json declares Node.js >=18 and lists [email protected] as the package manager used by the project itself, but those repository maintenance choices do not automatically constrain every consuming package.

TypeScript declarations, dependency handling, and executable bins

Pkgroll handles more than JavaScript output. It supports TypeScript and .d.ts bundling, and it uses TypeScript declaration processing to generate declaration files for exported entry points. Type dependencies declared in devDependencies are bundled and tree-shaken when declarations are generated. This can produce a smaller type surface for consumers, but it also means dependency classification affects the result. Packages in devDependencies are treated as bundleable, while packages listed in dependencies are externalized. A library that relies on runtime dependencies may therefore need its manifest categories checked carefully.

The README includes a special note for TypeScript 7. Because TypeScript 7 does not include the compiler API needed to bundle declaration files, pkgroll says to install @typescript/typescript6 alongside TypeScript 7. Pkgroll uses that package only for declaration bundling. The repository package metadata lists TypeScript and @typescript/typescript6 as optional peer dependencies, with TypeScript-compatible ranges that include versions 4 through 7. This is a concrete setup constraint for projects using the newest TypeScript line.

The bin field has separate handling. Pkgroll prepends a hashbang and changes the generated file mode to 0755. If the source has no hashbang, the default is #!/usr/bin/env node. A source can select another runtime or pass flags, for example:

ts
#!/usr/bin/env bun

console.log('Hello from bun!')

Pkgroll reads the hashbang from the bin entry file only. Hashbangs in imported modules are removed because they would be invalid inside a generated bundle. The repository does not document cross-platform permission behavior beyond the stated chmod operation, so projects publishing bins should verify the resulting executable mode on each target platform.

Where pkgroll is less suitable than a custom Rollup pipeline

The zero-config model is a constraint as much as a convenience. Pkgroll determines entry points from package.json and applies its own source-to-output mapping and dependency policy. A project that needs multiple unrelated build configurations, custom asset pipelines, elaborate plugin ordering, or a nonstandard output layout may be better served by a direct Rollup setup. The README does not document a general configuration file for overriding the manifest-driven behavior, so such requirements are outside the documented path.

Declaration bundling has another boundary. Pkgroll bundles type dependencies in devDependencies, but runtime externalization follows dependency types in package.json. If a package is incorrectly classified, consumers can receive code that expects a dependency they did not declare, or a declaration file that references types in a way that does not match the published package. The tool reduces configuration, but it does not remove the need to review dependency placement.

There is also a format distinction around package.json#module. The README labels module as an unofficial property used mainly by bundlers, not as a Node.js export field. pkgroll does use it to identify an ESM entry point, but consumers should not assume Node.js itself treats module as equivalent to exports. Projects that need precise Node.js resolution behavior should inspect the generated manifest and test both require and import paths.

Comparing pkgroll with a direct Rollup build

A direct Rollup configuration can express arbitrary input arrays, output controls, plugins, and build variants in JavaScript configuration. That approach costs more setup and makes the relationship between source, output, and package metadata explicit in a separate file. Pkgroll takes the opposite approach: it reads the package manifest, maps dist paths to src paths, and lets the manifest describe the package interface. It is therefore a better fit for conventional package publishing and a weaker fit for highly customized builds.

The comparison is not simply no configuration versus full control. Pkgroll still requires correct package.json metadata, and its supported behavior is defined by the manifest fields and documented mappings. A direct Rollup build can also use pkgroll's underlying ideas, but it does not inherit pkgroll's automatic bin hashbang handling, dependency classification, or declaration-specific workflow unless those steps are implemented separately. Based on the repository layout and README, pkgroll is a specialized Rollup front end rather than a new JavaScript bundler.

Maintenance, licensing, and release considerations

The repository is not archived, and its last push was on 2026-10-14. Recent releases listed in the repository metadata include v3.0.0-beta.1 on 2026-09-21, v2.28.1 on 2026-08-27, and v2.28.0 on 2026-08-27. The beta release is a separate consideration from the stable v2 releases, so projects should check which release line they intend to consume before adopting a new major or beta version.

The repository package.json declares the license as MIT, while the repository description classifies the license as Other because it points to the LICENSE file. That discrepancy should be resolved by reading the actual LICENSE file and checking the package contents before redistribution or incorporation into another product. The project repository is TypeScript and exposes its CLI through dist/cli.mjs. Its package metadata requires Node.js >=18 and lists Rollup, esbuild, and other packages as dependencies, so an upgrade can change the bundling toolchain as well as pkgroll itself.

The repository scripts show that pkgroll's own development build uses node src/cli.ts with --minify and --target node18, followed by tests and type checking. Those are project-maintenance commands, not commands required by consumers. The relevant upgrade cost for users is primarily manifest compatibility, TypeScript declaration behavior, and changes to the generated output.

Editorial conclusion

Adopt pkgroll when publishing a package whose build inputs are organized under src and whose published entry points are already represented by package.json fields. Do not choose it when a package needs a custom Rollup pipeline, unusual asset transforms, or a build graph that cannot be expressed through supported entry-point mappings. Before adoption, verify the license file, TypeScript compiler setup, source-to-output mapping, and the generated files for every exports condition.

Frequently asked questions

How do I install pkgroll for a Node.js package?

Install it as a development dependency with `npm install --save-dev pkgroll`. The README then documents defining package entry points in package.json and running `npm run build` or `npx pkgroll`.

Does pkgroll require a Rollup configuration file?

No. The project describes itself as zero-config and reads entry points from package.json, including main, module, types, exports, and bin. The src and dist directories are configurable through the documented `--srcdist` flag.

How does pkgroll handle TypeScript 7 declarations?

The README says TypeScript 7 does not include the compiler API required for declaration bundling. In that case, pkgroll directs users to install `@typescript/typescript6` alongside TypeScript 7, using it only for declaration bundling.

Official sources

  1. Issues
  2. privatenumber/pkgroll on GitHub
  3. README
  4. 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/privatenumber-pkgroll.svg)](https://hysenlabs.com/projects/privatenumber-pkgroll)

Was this useful?