CLI tool
nexe/nexe avatar
nexe/nexe

nexe: compiling a Node.js app into one executable

🎉 create a single executable out of your node.js apps

13,566 stars554 forksTypeScriptMIT

At a glance

What is it?
nexe bundles your application and a Node.js runtime into a single binary. It is a packaging tool for people who need to ship JavaScript to machines that will never have npm installed, and the trade-offs show up in the build step.
Who is it for?
Adopt nexe when you need to hand someone a file rather than a repository, and when a target triple like linux-x64 or win32-x86-10.13.0 maps cleanly onto your deployment. Do not adopt it if your application depends on native addons that must be rebuilt per platform, or if you expect a release cadence: the newest published release listed on the repository is v3.3.3 from 2017-08-30, while package.json carries 5.0.0-beta.4.
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?
Activity is slowing. The repository last received commits 7 months 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 1, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What nexe produces, and who needs that

The README describes nexe as "a command-line utility that compiles your Node.js application into a single executable file." The practical consequence is that the recipient does not need Node.js or npm on the machine. You hand over one file, they run it.

The motivation list in the README is explicit about why that matters: self contained applications, distributing binaries without node or npm, running multiple applications with different Node.js runtimes, and locking down specific application versions. That last point is the one worth pausing on. If you ship an executable, the runtime version is frozen inside it. Two services on one host can run different Node.js versions without a version manager arbitrating between them.

This is not a general JavaScript bundler. It is a distribution step. If your users already have Node.js, or your deployment is a container image where you control the base layer, nexe adds a build stage without removing a dependency you actually had.

How the bundling and resource embedding work

nexe takes an entrypoint, resolves the module graph, and produces an output file. The bundling itself is delegated: the NexeOptions documentation shows that the bundle option accepts either a boolean or a string, and when it is a string it "must be a valid relative module path" exporting a function with the signature createBundle(options: NexeOptions): Promise<string>. The default is true, which means nexe's own bundler runs. Passing a path lets you substitute a different one, for example a rollup-driven pipeline, which the README demonstrates through the stdin interface.

Resources are the second mechanism. Passing -r with a glob pattern adds files to the binary, and the README states that "included files can be read in the application by using fs.readFile or fs.readFileSync." The files are not unpacked to disk first. They are embedded and served through the fs API, which is why a template directory or a static HTML tree can travel inside the executable.

There is a switch that changes this arrangement. The mangle option defaults to true; setting it to false means "nexe will not include the virtual filesystem (your application and resources) on the output." The documentation is blunt about the result: the output will error as an "Invalid Binary" unless a userland patch alters lib/_third_party_main.js in the Node.js source. That is a build-time hook for people who need to control exactly what lands in the binary, not a configuration most users should touch.

The Node.js API exposes the same machinery programmatically. The README example calls compile with an input, build: true, and a patches array containing an async function that receives a compiler and a next callback, then calls compiler.setFileContentsAsync to write a file into the build. Patches are the extension point; the build flag is marked in the example as "required to use patches."

Installing nexe and compiling a first binary

The README gives the install line directly: npm i nexe -g. That puts the nexe binary on your path, and the repository's package.json maps the bin entry nexe to index.js.

bash
npm i nexe -g

With nexe installed, the shortest path to an executable is to point it at an entrypoint. The README shows nexe my-app.js as the application entrypoint form.

bash
nexe my-app.js

By default nexe attempts to download a pre-built executable rather than compile one. The README says these are listed on the releases page, and warns that "the exact version you want may be unavailable." If your target is not among the pre-built artifacts, you fall back to building Node from source.

Resources are added with -r and a glob. The README's own example adds HTML files to a server binary.

bash
nexe server.js -r "public/**/*.html"

The target option selects platform, architecture and version. The documentation describes the string form as platform-arch-version, with each segment optional and merged with the current environment. Its examples include linux-x64, darwin-10.13.0, and win32-x86-10.13.0.

bash
nexe -t x86-8.0.0

If you need to build rather than download, the --build flag tells nexe to download and build from source. The README notes that using the flag again reuses the previously built binary, and that you must add --clean first if you want a rebuild. On Linux, the python binary on your path should be an acceptable Python 3; the README offers a symlink or the --python parameter as workarounds.

bash
nexe --build --python=$(which python3)

On Windows, the README points to a Boxstarter-based PowerShell sequence run as Administrator, followed by two npm config settings. It states the approach was tested with Node.js 14.5.4 and 15.8.0, and warns against npm install windows-build-tools unless you hit a problem, because the earlier commands already configure what is needed.

bash
npm config set msvs_version 2019
npm config set python python3.8

What you should see after a successful run is a single file in your working directory, or at the path given by -o. The README's stdin example writes to an explicit name: rollup -c | nexe --resource "./public/**/*" -o my-app.exe.

Where nexe stops being the right tool

The build-from-source path is the sharp edge. When a pre-built binary for your target is missing, you are no longer packaging JavaScript. You are compiling Node.js, and the README sends you to the Node.js BUILDING.md for prerequisites on Unix, macOS and Windows. That is a real toolchain dependency, and it is where most of the build time goes.

The second constraint is target coverage. The target string merges with the current environment, which is convenient, but the README does not promise that every platform-arch-version combination exists as a pre-built artifact. It says the exact version you want may be unavailable. Cross-platform builds are listed as a feature, but the availability of the underlying runtime binaries is the limiting factor, not nexe's interface.

The third is the release situation. The repository's recent releases list shows v3.3.3 (Nexe V3) from 2017-08-30 as the most recent tagged release, while package.json declares version 5.0.0-beta.4. Anyone reading the releases page to decide what they are installing will see a nine-year gap between the tag and the manifest. That mismatch is not a defect in the tool, but it is a fact you need before pinning a version in a pipeline.

Finally, mangle: false is documented as producing an "Invalid Binary" unless you patch Node's lib/_third_party_main.js. Anyone who sets it expecting a smaller or more inspectable output will get a file that does not run.

nexe versus pkg: two ways to attach a runtime

The comparison people search for is nexe against pkg, and the difference is in where the runtime comes from. nexe's default path is to download a pre-built Node.js executable from its releases, or, with --build, to compile Node from source on your machine. The README treats the downloaded binary as the normal case and the source build as the fallback when "the exact version you want may be unavailable."

That gives nexe a specific property: the runtime is a separate artifact you can point at. The remote option accepts an HTTP or HTTPS URL for fetching pre-built nexe binaries, and the asset option accepts a file path to a pre-built nexe binary resolved relative to cwd. If you host your own builds, or you need a runtime that has been modified before packaging, those two options are the reason to pick nexe over a tool that only knows how to fetch its own runtime.

It also means the failure mode is different. When the artifact you need does not exist, you do not get an error telling you to choose another version. You get a source build, with Node's build prerequisites and the associated wait. A tool that ships its own runtime avoids that fallback but gives up the ability to substitute one.

If your target list is short and stable, and you never need a patched runtime, the distinction matters less than the build time. If you ship to unusual architectures, or you maintain a patched Node, nexe's remote and asset options are the deciding factor.

Maintenance, versions and the MIT licence

The repository is not archived, and the last push was on 2026-03-05. The releases list, however, ends at v3.3.3 from 2017-08-30, while package.json carries 5.0.0-beta.4. Read those two facts together: there is ongoing work on the default branch, and the published release history does not reflect it. For a team pinning a version, that means the tag you install from npm and the version in the manifest may not line up with what the releases page shows.

Upgrade cost has a concrete shape here. Because nexe embeds a Node.js runtime, upgrading nexe is not the whole upgrade. You also choose a runtime version through the target option, and if you build from source, that build is cached: the README says using --build again reuses the previously built binary, and that --clean is required before a rebuild. A runtime bump therefore means a deliberate --clean and a fresh compile, not just a version change in package.json.

The licence is MIT, which the repository states in package.json and the README badge. MIT is permissive and imposes no source-disclosure requirement on your application. What it does not do is resolve the licensing of the Node.js runtime you embed. If you build from source, you are distributing a Node.js binary under Node's own terms, and that is a separate question from nexe's licence. Check the terms that apply to the runtime version you select; this is not legal advice.

Editorial conclusion

Adopt nexe when you need to hand someone a file rather than a repository, and when a target triple like linux-x64 or win32-x86-10.13.0 maps cleanly onto your deployment. Do not adopt it if your application depends on native addons that must be rebuilt per platform, or if you expect a release cadence: the newest published release listed on the repository is v3.3.3 from 2017-08-30, while package.json carries 5.0.0-beta.4. Before committing, run nexe --help against your installed version, confirm the exact target string you need appears in the project's release list, and check whether your build machine already has the prerequisites for compiling Node from source, because that is the step that decides how long your pipeline takes.

Frequently asked questions

What is nexe?

nexe is a command-line utility that compiles a Node.js application into a single executable file, so the target machine does not need Node.js or npm installed. It installs globally with npm i nexe -g.

How old is nexe?

The repository's release list goes back to v1.0.0 from 2016-01-22, and the most recent tagged release shown is v3.3.3 from 2017-08-30, while package.json declares 5.0.0-beta.4.

What is the future outlook for nexe?

The repository is not archived and the last push was on 2026-03-05, so work continues on the default branch. The published release list, however, ends at v3.3.3 from 2017-08-30, which is worth knowing before you pin a version.

Official sources

  1. Issues
  2. License: MIT
  3. nexe/nexe on GitHub
  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/nexe-nexe.svg)](https://hysenlabs.com/projects/nexe-nexe)