deobfuscate-javascript
Deobfuscate JavaScript
Reverse-engineer minified/obfuscated JavaScript back to readable code. Three stages: Stage 1 (only if obfuscated) and Stage 2 (rename + polish) do the readable restore; Stage 3 adds the typed rewrite + acceptance review and is the deep-tier add-on.
- Stage 1 — Deobfuscation: unwind obfuscation transforms (Packer/AAEncode unpack, Obfuscator.IO string arrays, hex/unicode/base64 escapes, dead code, opaque predicates). Pure Babel passes, no LLM. Run only on obfuscated input. Detail: stage-1-deobfuscate.md.
- Stage 2 — Restore to readable (two phases). (a) Rename cryptic identifiers (
a,e,t,_0x4f3, …) to meaningful names — a TS+Bun port of humanify where you play the renamer, runningsmart-rename.tsfirst so you only hand-name the residue. (b) Polish undoes bundler/compiler transforms — the reading-aid subset (--fast: React Compilercache[N]strip,(0, fn)(...)unwrap, backtick → string, JSX-runtime → JSX, destructure defaults, aliased exports) is the default; the import-resolution tail (npm/shim/dead-shim elimination) is deep mode only. Detail: stage-2-restore.md. - Stage 3 — Finalize (deep mode only) (two phases). (a) Semantic rewrite turns the mechanical checkpoint into idiomatic typed TypeScript — semantic filenames, provenance header, import map, types/
.tsxrecipes, directory splits, import repair. (b) Acceptance review — the host reads every delivered file end-to-end against the four-category quality bar and iterates until each passes; no sub-agent and no authorization required (an independent reviewer sub-agent is optional). The default tier ships the Stage 2 readable file without Stage 3. Detail: stage-3-finalize.md.
Default scope and depth
Two independent axes: scope (one file vs the whole import tree) and depth (readable vs deep). Pick scope from the input shape. For a whole-tree restore the default depth is deep ("restore the code" means complete + typed); a lone snippet defaults to readable. Drop a whole tree to readable only on an explicit "quick"/"readable"/"快速" request.
- Default scope — whole tree from
index.html. For an app (index.html+ sibling-chunk asset tree), readindex.html, auto-discover the entry (check-entry.ts --discover --root <assets-dir>, or omit the positional tobuild-import-graph.ts), then recursively restore every reachable project-local chunk. Per-chunk pipeline: Stage 1 (if obfuscated) → wakaru pre-pass (wakaru-normalize.ts; recovers ES6 classes, async/await, optional chaining, destructuring, TS enums, …; default-on, auto-skips if@wakaru/cliabsent) → Stage 2 rename (smart-renamefirst, then hand-name residue) → reading-aid polish (polish.ts --fast) → format → organize in staging, then promote into sharedrestored/(semantic subfolders, kebab filenames, provenance headers, onerestored/IMPORT_MAP.json); script/batch output never goes straight intorestored/. Bundled vendor data (Shiki grammars + themes, data libs like 3Dmol) is detected by content and treated asnpm-leaf— NOT restored; consumers import the bare specifier (@shikijs/langs/<id>,@shikijs/themes/<id>), sorestored/holds app code only. Readable depth's hard bar is naming quality; deep depth adds complete types + every reachable chunk promoted. - Fallback scope — single file. When the input is a lone pasted snippet, or there is no
index.html/ asset tree, restore just that one file — workflows/small-minified.md. Same per-file pipeline, no import graph. - Depth — deep (default for whole tree) vs readable (quick opt-out). Deep = meaningful names plus Stage 3 (typed
.tsx+ acceptance review), full npm-import resolution (Stage 2's deep polish tail), and import-graph/ledger orchestration draining every reachable chunk topromoted; also triggered on "deep"/"full"/"完整"/"深度"/"production"/"typed"/"restore the whole tree". Readable = meaningful names, reading-aid polish, untyped — only on "quick"/"readable"/"快速"/"粗略" or a lone snippet. Both organize and promote;promote-organized.tsdefaults--tier deep(enforcesProps/param types),--tier readablerelaxes the typing gate.
Deep is a completion bar, not an upsell: a whole-tree restore is "done" only when every reachable project-local chunk reaches stages.promoted and quality-gate.ts <target> passes (Restoration contract). Readable is a downgrade the user asks for, not the resting state.