Skip to content

Repository files navigation

Wakaru

Unpack. Unminify. Understand.

Wakaru unpacks webpack, esbuild, and other production bundles, then reverses minifier and transpiler output into readable modern JavaScript.

CInpmTelegram

Try it in the playground — paste minified JavaScript, or compare pinned Babel, SWC, and esbuild output with Wakaru's restoration.

What it does

A formatter only changes whitespace and layout. Wakaru rewrites the JavaScript AST to reverse minifier artifacts, restore transpiled syntax, remove bundler runtimes, and split bundles back into modules.

Feed Wakaru this minified Babel output:

"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.loadProfile=void0;var_api=_interopRequireDefault(require("./api"));function_interopRequireDefault(e){returne&&e.__esModule?e:{default:e}}function_asyncToGenerator(e){returnfunction(){vart=this,r=arguments;returnnewPromise(function(n,o){vara=e.apply(t,r);functioni(e){c(a,n,o,i,u,"next",e)}functionu(e){c(a,n,o,i,u,"throw",e)}i(void0)})}}functionc(e,t,r,n,o,a,i){try{varu=e[a](i),c=u.value}catch(e){returnvoidr(e)}u.done?t(c):Promise.resolve(c).then(n,o)}varloadProfile=function(){vare=_asyncToGenerator(function*(e){vart=yield_api.default.fetchUser(e),r=null!=t.name?t.name:"anonymous";return{name:r,avatar:null==t.profile?void0:t.profile.avatar}});returnfunction(t){returne.apply(this,arguments)}}();exports.loadProfile=loadProfile;

and get this back:

import_apifrom"./api";exportconstloadProfile=async(e)=>{constt=await_api.fetchUser(e);constname=t.name??"anonymous";return{
name,avatar: t.profile?.avatar};};

That is real, unedited output: the runtime helpers are gone, async/await is recovered from the generator state machine, ?? and ?. are restored, and the module is ESM again. (Wakaru applies conservative renaming heuristics where the code gives evidence, but most mangled locals like e stay short unless the source map includes original names.)

Quick start

npx wakaru input.js -o output.js # decompile a file
npx wakaru bundle.js --unpack -o out/ # unpack and decompile a bundle
npx wakaru dist/ --unpack -o out/ # scan a bundle output directory
npx wakaru ./compiled-app --unpack -o out/ # extract a Bun standalone executable
npx wakaru bun extract ./compiled-app -o raw/ # dump every embedded Bun file byte-for-byte

Full flag reference: docs/cli.md.

What it handles

  • Bundle and container splitting — byte-exact extraction of every file in Bun standalone PE/Mach-O/ELF executables, plus JavaScript unpacking; webpack 4/5 (including Vercel ncc CommonJS output with an IIFE webpack bootstrap), esbuild, Bun, Browserify (including Cocos Creator 2.x project-script bundles), Metro, Closure ModuleManager, SystemJS, AMD/UMD, plus heuristic splitting of scope-hoisted ESM output (Rollup, Vite).
  • Transpiler recovery — Babel, TypeScript/tslib, and SWC runtime helpers: async/await from generator state machines, classes, spread/rest, enums, JSX, template literals, optional chaining, nullish coalescing, default parameters, for...of, and more.
  • Minifier recovery — sequence expressions, flipped comparisons, !0/void 0 literal tricks, IIFE flattening, alias inlining.
  • Three rewrite levelsminimal (highest-confidence, semantics-preserving transforms for auditing and diffing), standard (default), aggressive (maximum readability). The semantic contract per level is documented in rewrite-assumptions.md.

Tested like a compiler

Wakaru restores structure while respecting JavaScript semantics:

  • 62,061 passing Test262 semantic round trips, with zero Wakaru correctness failures. The canonical 3-producer × 20-slice matrix contains 66,729 runnable inputs; 4,668 are classified as unsupported or rejected rather than counted as passes. A pass preserves the typed Test262 expectation; positive and runtime/resolution-negative cases run the original source, transformed/minified source, and Wakaru's output through the same harness. Separate canonical baselines cover multi-file ESM module graphs. See test262-roundtrip.md and the current test262-stats.json.
  • 96.4% pattern recovery across 1,743 transpiler × minifier test shapes. Reproduction matrices compile known inputs through real Babel/TypeScript/ SWC/esbuild/Terser version combinations and verify Wakaru recovers the original construct. Current rates per matrix: scripts/repro/stats.json.

Works with other tools

Obfuscated input? Wakaru is deliberately not a deobfuscator — heavy obfuscation (string arrays, control-flow flattening, VM-based protectors) is a different problem. Strip it first with a dedicated tool like webcrack, then let Wakaru recover the readable modules:

npx webcrack --no-unpack --no-unminify obfuscated.js > deobfuscated.js # 1. strip the obfuscation
npx wakaru deobfuscated.js --unpack -o out/ # 2. recover readable modules

Want better names? Pair Wakaru's deterministic structure recovery with an LLM renamer like humanify, or use --source-map when the map includes original names.

Use cases

  • Security review & bug bounty — read what a site actually ships instead of scrolling one 5 MB line. Split the bundle, find the first-party code, audit it as modules.
  • Incident response & malware triage — unminify a suspicious script into something a human can diff and reason about, using minimal level to favor behavioral fidelity.
  • Recovering lost source — the vendor vanished, the laptop died, and all that's left is dist/. Reconstruct a workable codebase from the bundle (and wakaru extract recovers originals when the map includes sourcesContent).
  • Debugging third-party SDKs — turn the vendored blob into readable modules so the stack trace points at code you can actually understand.
  • Supply-chain inspection — see what's inside a dependency's shipped bundle rather than trusting the repo it claims to be built from.

Use it from an agent

Coding agents hit unreadable minified JS constantly. Wakaru ships a SKILL.md — drop it into Claude Code, Codex, Grok, or any agent that reads skills, and the agent knows when and how to unpack a bundle, read the recovered modules like ordinary source, and pick the right rewrite level.

Agents that support the skills format can install it with:

npx skills add pionxzh/wakaru

Install

npm install -g wakaru@latest

Or pre-built binaries from GitHub Releases. Full CLI documentation: docs/cli.md.

Contributing

Contributions are welcome, especially:

  • Share real-world bundles that Wakaru doesn't handle well
  • Report missing helper detection or false positives
  • Report semantic or correctness issues

When reporting a bug, please include: the input code, the command you ran, the current output, and what you expected instead.

See CONTRIBUTING.md for development setup and PR checks. Project docs start at docs/README.md.

License

Apache-2.0

Usage of Wakaru for attacking targets without prior mutual consent is illegal. End users are responsible for complying with all applicable laws.

Releases

Used by

Contributors

Languages