afterpack
v0.2.2
Published
AfterPack CLI: obfuscate the JavaScript in any build output, verify a build before deploy, and scan a live site
Maintainers
Readme
afterpack
The command-line JavaScript obfuscator from AfterPack. Run it after your build, over the output directory, to protect JavaScript source code before you ship it. It works with any bundler, or none.
npx afterpack@latest dist # a build directory, walked recursively
npx afterpack@latest dist/bundle.js # or one .js, .mjs or .cjs file
npx afterpack@latest dist --preset=hard --seed=git
npx afterpack@latest verify . # check a build before you deploy it
npx afterpack@latest restore # undo the last run
npx afterpack@latest audit example.com # scan a live siteUse afterpack@latest so npx does not pick up an old cached copy. afterpack --help lists the
common options and afterpack --help --all lists every one.
If your project uses a framework with an AfterPack plugin (Vite, Next.js, webpack, Nuxt, Astro and
others), the plugin is the better fit. Most plugins obfuscate inside the build, so the readable
bundle never reaches disk; the Next.js, esbuild and Angular integrations run right after the tool
writes its output. Run afterpack with no path and it tells you which plugin to install.
afterpack [path]
Files are obfuscated in place. Build first, then run AfterPack once. A second run over the same output is refused, because AfterPack recognises its own output.
Nested node_modules/ folders are skipped. Pass --paths.include='**/node_modules/**'
(quoted) to include them.
Each run writes:
.afterpack-protection.jsonin the output directory, the receipt thatafterpack verifychecks..afterpack/backup/, a copy of the original files, soafterpack restorecan undo the run. Turn it off with--build.backup=false..afterpack/protectionMap.html, the Protection Map, when your build has source maps..mapfiles next to the output, when your build has source maps and the run is not a production build.
The backup and the Protection Map contain your original source. .afterpack/ carries its own
.gitignore and self-ignores. Never deploy or commit them.
With no path, afterpack looks at your project first. If it finds a framework, it prints the plugin
to install (or tells you the one you have already covers the build) and exits 1. Otherwise it
picks the build output (dist/, build/, out/, .output/ or .next/), says what it found and
runs. It never prompts.
afterpack verify [dir]
Checks a build against its protection receipt. Run it in your deploy step.
npx afterpack@latest verify . # looks in ./ and ./.next/
npx afterpack@latest verify distIt exits 1 when the receipt is missing, belongs to a different build, or a file changed after it
was obfuscated. The CLI and the plugins for Vite, Next.js, webpack, Rollup, esbuild and Angular all
write a receipt.
afterpack restore [dir]
Puts back the original files from .afterpack/backup/. A file that changed since the run is
skipped and named, and the command exits 1.
afterpack audit <url>
Scans a live site for leaked secrets, exposed source maps and unprotected JavaScript, and prints a
link to the full report. It sends only the URL and writes nothing. A finished scan exits 0 however
much it found. It is the free website security scanner
in your terminal; see auditing a live site.
Options
Every option has one name, written the same way everywhere:
--preset=hardon the command lineAFTERPACK_preset=hardin the environment (dots become underscores)"preset": "hard"inafterpack.json, the nearest one at or above the working directory
A flag wins over the environment, which wins over the file. A boolean flag on its own means true.
An unknown or misspelled option fails the run and names the right spelling.
| Flag | What it does | Default |
| --- | --- | --- |
| --preset | minify, light, medium, hard or extreme | light |
| --seed | fix the seed; git uses the current commit | a new random seed per build |
| --paths.exclude | globs to leave untouched | none |
| --paths.include | globs to add back to the walk | none |
| --identifiers.reserved | names never to rename | none |
| --build.backup | back up originals to .afterpack/backup/ | true |
| --protectionMap.enabled | write the Protection Map | on when an input map exists |
Each flag is also a key in afterpack.json and an AFTERPACK_* variable. Every other option is in
the configuration reference. The
CLI reference covers the commands.
{
"preset": "hard",
"seed": "git",
"paths": { "exclude": ["dist/vendor/**"] },
"identifiers": { "reserved": ["Hls"] }
}--diagnostics.format=json prints exactly one JSON document on stdout
and sends everything else to stderr. Use it in CI and scripts. verify and audit support it too.
Pro
Without a key, AfterPack runs on your machine with the full pipeline at any preset. Set
AFTERPACK_KEY in your environment (or key in afterpack.json) and the same
command builds in AfterPack's cloud instead, which adds two hardening transforms you can turn on:
self-integrity (anti-tamper) and comparison hardening. If the cloud cannot be reached, the run
fails; it never falls back to a local build. Never commit the key. See AfterPack
Pro.
Exit codes
| Code | Meaning |
| --- | --- |
| 0 | Success. |
| 1 | Failure. Nothing was changed, or verify, restore or audit failed. |
| 2 | Some files shipped unobfuscated. Only possible with allowUnobfuscated. |
| 3 | The size limit (inflation.max) stopped AfterPack before it reached the protection level. |
| 6 | An update is required. The CLI prints the install command to run. |
| 64 | Misuse: an unknown option or command, or a malformed value. |
Every failure prints one line that says how to fix it. A failed run leaves your build output as your bundler wrote it.
Links
License
Apache-2.0. The engine it runs, @afterpack/core, has its own
license.
Feedback
Questions, suggestions and bug reports: afterpack.dev/contact. You can also file a bug on GitHub Issues.
