deobfuscate-javascript

Installation
SKILL.md

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, running smart-rename.ts first so you only hand-name the residue. (b) Polish undoes bundler/compiler transforms — the reading-aid subset (--fast: React Compiler cache[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/.tsx recipes, 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), read index.html, auto-discover the entry (check-entry.ts --discover --root <assets-dir>, or omit the positional to build-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/cli absent) → Stage 2 rename (smart-rename first, then hand-name residue) → reading-aid polish (polish.ts --fast) → format → organize in staging, then promote into shared restored/ (semantic subfolders, kebab filenames, provenance headers, one restored/IMPORT_MAP.json); script/batch output never goes straight into restored/. Bundled vendor data (Shiki grammars + themes, data libs like 3Dmol) is detected by content and treated as npm-leaf — NOT restored; consumers import the bare specifier (@shikijs/langs/<id>, @shikijs/themes/<id>), so restored/ 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 to promoted; 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.ts defaults --tier deep (enforces Props/param types), --tier readable relaxes 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.

Output conventions

Installs
5
GitHub Stars
115
First Seen
Jun 26, 2026
deobfuscate-javascript — jimliu/decode-codex