This page is available in English only.

AfterPack configuration reference

Every option, where to set it, and what it does.

AfterPack options can be set in afterpack.json, as an environment variable, as a CLI argument or plugin option, or for a specific region of your source (Pro). Each later place overrides the earlier ones.

A build that sets nothing uses the light preset. afterpack.json is looked up from the working directory upward; the nearest one is used.

An option that takes a list replaces its default list. Items are never added to it, so repeat the defaults you want to keep.

Protection

How strongly the output is protected.

preset

A named level of protection. Sets complexity, the output size multiplier and the inflation budget together. Setting complexity explicitly overrides only that.

Type
enum
Default
light
Values
{ "preset": "hard" }

complexity

How much protection the engine applies. 0 applies none; higher values let it negotiate more and heavier transformations per build, with no fixed feature-per-level schedule. There is no upper bound, and output size grows with the value.

Type
number ≥ 0
Default
the preset's value; light is 2
{ "complexity": 40 }

inflation.max

The maximum output size as a multiple of the input size. A build that would exceed a value you set fails; left unset, a build that reaches the preset's ladder stops growing and still emits.

Type
number ≥ 0, or "unlimited"
Default
the preset's output-size ladder: 1.2 / 2 / 2.5 / 4 / 7
{ "inflation": { "max": 4 } }

strings.encode

Encodes every string literal so that none remains readable in the output.

Type
boolean
Default
true at any positive complexity; false at 0
{ "strings": { "encode": false } }

strings.minLength

The shortest string strings.encode encodes. Shorter strings stay readable. Raising it reduces output size at the cost of leaving short literals in the clear.

Type
integer ≥ 0
Default
0
{ "strings": { "minLength": 4 } }

strings.leaks.max

Fails the build when more than this many readable string literals remain in the output. Unset never fails.

Type
integer ≥ 0
Default
unset; the count is reported but never fails a build
{ "strings": { "leaks": { "max": 0 } } }

transforms.<kind>.enabled

Enables or disables one kind of transformation. false reliably removes that kind at any complexity; true permits it, and the engine still decides per build whether to apply it. comparisonHardening and selfIntegrity are Pro.

controlFlowFlattenopaquePredicatemixedBooleanArithmeticintegerBytecodecrossDependencyscopeDeepenobjectConstructionstringEncodingcomparisonHardeningproselfIntegritypro
Type
boolean
Default
true; the two Pro kinds default to false
{ "transforms": { "controlFlowFlatten": { "enabled": false } } }

regionsPro

Region overrides supplied by a build tool instead of source comments. Each entry names a span of your original source and the keys to override inside it.

Type
{ start, end, …keys }[]
Default
[]
{ "regions": [{ "start": 1200, "end": 1840, "complexity": 80 }] }

skipPro

Drops the region to complexity 0, so no transformation is applied inside it and its string literals stay readable. Identifiers inside it are still renamed.

Identifier renaming applies to the whole program and has no per-region form. To keep a name, list it in identifiers.reserved.

Type
boolean
Default
false

Only meaningful in a directive.

Scope and preservation

Files, names and runtime patterns AfterPack must leave alone.

paths.include

Globs that re-admit what the CLI's directory walk skips. Nested node_modules/ is skipped by default; **/node_modules/** walks it and takes every .js/.mjs/.cjs inside. It only ever adds files, and paths.exclude still wins over it.

A walk-only key: it does nothing in a bundled build, where the bundler has already inlined your dependencies into the chunks and no node_modules path is left to match. Same glob grammar as paths.exclude, which means an unanchored pattern is tried at every path segment, so any non-empty value lets the walk descend into node_modules/ and ["src/**"] matches dependency files under node_modules/*/src/ too. Lead with / to anchor a pattern to one absolute location. Quote the glob on a command line or the shell expands it first.

Type
glob[]
Default
[]
{ "paths": { "include": ["**/node_modules/**"] } }

paths.exclude

Files to leave untouched, as globs. A matching file is copied to the output unchanged. Applies to files, not to code a bundler has already merged into your bundle.

Type
glob[]
Default
[]
{ "paths": { "exclude": ["**/*.min.js", "dist/vendor/**"] } }

identifiers.rename

Renames identifiers. false keeps every name and is meant for debugging; use identifiers.reserved to keep specific names. Exported and reflected names are never renamed.

Type
boolean
Default
true
{ "identifiers": { "rename": false } }

identifiers.globals.rename

Also renames the top-level names of a classic script. Safe only for a script nothing else calls into, in a single-file build.

Type
boolean
Default
false
{ "identifiers": { "globals": { "rename": true } } }

identifiers.methods.rename

Obfuscates class method names, including what Function.prototype.name returns. false keeps them, for code that reads fn.name, such as a dependency-injection container or a serializer.

Type
boolean
Default
true
{ "identifiers": { "methods": { "rename": false } } }

identifiers.reserved

Identifier names that are never renamed. A plain name applies to the whole build. Use it for names other code expects, such as a bundled library's public API.

An item can also be { "glob": "src/legacy/**", "names": ["jQuery"] }, which applies only inside matching files. That form is afterpack.json and plugin options only; a flag or a variable carries plain names.

Type
(string | { glob: string, names: string[] })[]
Default
[]
{ "identifiers": { "reserved": ["Hls", "gtag"] } }

reflection.allow

Runtime reflection patterns your code relies on. AfterPack fails the build when it detects a pattern you have not listed. angular and nestjs expand to the patterns those frameworks need.

Type
enum[]
Default
[]
Values
{ "reflection": { "allow": ["functionToString"] } }

Output

Files a build writes next to your code.

sourceMap.enabled

Writes a source map next to the output. A published map reverses the obfuscation. Never deploy it.

Type
boolean
Default
true in development when an input map exists; false in production
{ "sourceMap": { "enabled": false } }

sourceMap.sourcesContent

Embeds your original source in the map. Never publish a map with this on.

Type
boolean
Default
true in development; false in production
{ "sourceMap": { "sourcesContent": false } }

sourceMap.emitUrl

Appends the //# sourceMappingURL= comment to the output. The map file is written regardless.

Type
boolean
Default
true in development; false in production
{ "sourceMap": { "emitUrl": false } }

protectionMap.enabled

Writes the Protection Map, an HTML report of what was applied to each part of your source, into .afterpack/. The report contains your full source. Never publish it.

Type
boolean
Default
true when the bundler emitted a source map
{ "protectionMap": { "enabled": false } }

protectionMap.detailed

Lists, for every region of the Protection Map, the transformations applied to it. false makes the report smaller.

Type
boolean
Default
true
{ "protectionMap": { "detailed": false } }

Build

How a build runs.

seed

The random seed for the build. Unset, every build gets a new seed and different output. Set a number, any string, or "git" for the current commit to reproduce a build.

Type
number | string | "git"
Default
a new random seed per build
{ "seed": "git" }

build.mode

Selects production or development defaults for output settings such as source maps and backups.

Type
enum
Default
detected from the environment
Values
{ "build": { "mode": "production" } }

build.autorun

Runs AfterPack automatically at the end of your bundler's build. With false the plugin only reads directives, and you run the engine yourself.

Type
boolean
Default
true
{ "build": { "autorun": false } }

build.backup

Keeps a verbatim copy of every original file, so a run can be undone. The CLI writes a backup DIRECTORY, .afterpack/backup/ at your project root, with a manifest.json recording what each file became, and afterpack restore puts the originals back; it is on there by default. A framework plugin writes a .backup.<hash> sibling beside each output file instead, and only when you set this to true.

Either form is your source verbatim. The plugin's sibling lands inside the tree you deploy; the CLI's directory sits outside it, gitignored. Never deploy either.

Type
boolean
Default
false for an in-place pass; the CLI's own backup directory is on by default
{ "build": { "backup": true } }

directives.enabled

Reads @afterpack comments in your source and applies them as region overrides.

Type
boolean
Default
true
{ "directives": { "enabled": false } }

diagnostics.level

How much a build prints. summary prints errors in full and counts the rest. all prints everything. none silences the progress and summary lines; errors still print.

Type
enum
Default
summary
Values
{ "diagnostics": { "level": "all" } }

diagnostics.format

Switches the CLI's own output between human-readable text and one JSON document on stdout, with every human-readable line moved to stderr. This is the shape a CI step or an AI agent should read.

CLI only; a plugin build accepts and ignores it, since a bundler owns its own build output, not stdout.

Type
enum
Default
text
Values
{ "diagnostics": { "format": "json" } }

allowUnobfuscated

Ships a file the engine could not obfuscate as cleartext instead of failing the build. The run still exits 2 so a script can detect it. Off by default: AfterPack fails closed, and turning this on ships less protection than you asked for on the affected file.

Type
boolean
Default
false
{ "allowUnobfuscated": true }

telemetry.enabled

Sends an anonymous report when a build reports an error-level diagnostic (a refused or partial build): the diagnostic code, byte offsets, and the tool, OS and architecture versions. Never source, paths or file names. A clean build sends nothing.

Type
boolean
Default
true
{ "telemetry": { "enabled": false } }

keyPro

Your Pro API key. With a key, builds run on the Pro engine. Set it through the environment or a CI secret rather than a committed file.

Type
string
Default
unset; builds run locally on the Free engine
{ "key": "ap_v1_…" }

Example afterpack.json

{
  "preset": "hard",
  "strings": { "minLength": 4 },
  "identifiers": { "reserved": ["Hls"] },
  "paths": { "exclude": ["**/*.min.js", "dist/vendor/**"] },
  "protectionMap": { "enabled": true }
}

Next

  • Presets: what each preset sets.
  • Complexity: what rises with the number, and which transformations config can turn off.
  • Directives: protecting one region of your source differently.
  • Protection Map: checking what a build applied.