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.
- 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.