# Quickstart

> First successful runs: decompile a single file, unpack a bundle to a directory, verify stdout vs -o output, and expected success signals for each mode.

- Repository: pionxzh/wakaru
- GitHub: https://github.com/pionxzh/wakaru
- Human docs: https://grok-wiki.com/public/docs/pionxzh-wakaru-77a438a6cc6b
- Complete Markdown: https://grok-wiki.com/public/docs/pionxzh-wakaru-77a438a6cc6b/llms-full.txt

## Source Files

- `README.md`
- `crates/cli/src/main.rs`
- `testcases/webpack5/README.md`
- `testcases/webpack5/dist/index.js`
- `docs/architecture.md`

---

---
title: "Quickstart"
description: "First successful runs: decompile a single file, unpack a bundle to a directory, verify stdout vs -o output, and expected success signals for each mode."
---

The `wakaru` CLI exposes two primary operations: **decompile** (transform one JavaScript file through the rule pipeline) and **unpack** (split a bundle into modules, then decompile each). Decompile writes to stdout by default; unpack always requires `-o/--output` as a destination directory.

## Prerequisites

Install Wakaru before running the commands below. Three entry points are supported:

<Tabs>
  <Tab title="npx (no install)">
    ```bash
    npx @wakaru/cli <input> [flags]
    ```
  </Tab>
  <Tab title="npm global">
    ```bash
    npm install -g @wakaru/cli@latest
    wakaru <input> [flags]
    ```
  </Tab>
  <Tab title="cargo (from source)">
    ```bash
    cargo run -p wakaru-cli -- <input> [flags]
    ```
    Run all `cargo` commands from the repository root.
  </Tab>
</Tabs>

<CardGroup>
  <Card title="Installation" href="/installation">
    Platform packages, Node engine constraints, and GitHub release binaries.
  </Card>
  <Card title="Overview" href="/overview">
    What Wakaru decompiles, unpacks, and how the core/cli/wasm crates fit together.
  </Card>
</CardGroup>

## Decompile a single file

Single-file mode runs `decompile()` on one input: parse → resolver marks → ~60 rewrite rules → fixer → emit. No bundle detection runs unless you pass `--unpack`.

<Steps>
  <Step title="Pick an input">
    Pass a file path, pipe stdin, or use `-` explicitly:

    <CodeGroup>
      ```bash File path
      wakaru input.js
      ```
      ```bash Stdin pipe
      cat input.js | wakaru
      ```
      ```bash Explicit stdin
      wakaru - < input.js
      ```
    </CodeGroup>

    If no file is given and stdin is not a terminal, Wakaru reads stdin automatically. Otherwise it exits with `no input specified; pass a file path or pipe code on stdin`.
  </Step>

  <Step title="Choose stdout or a file">
    <ParamField body="-o, --output" type="path">
      Optional output file. When omitted, decompiled JavaScript is printed to **stdout**.
    </ParamField>

    <CodeGroup>
      ```bash Stdout (default)
      wakaru input.js
      ```
      ```bash Write to file
      wakaru input.js -o output.js
      ```
    </CodeGroup>
  </Step>

  <Step title="Verify success">
    A successful decompile has these signals:

    | Signal | Stdout (`-o` omitted) | File (`-o` set) |
    |--------|----------------------|-----------------|
    | Exit code | `0` | `0` |
    | Primary output | Decompiled JS on stdout | File created at `-o` path |
    | Warnings | Printed to stderr (when not `--json`) | Same |
    | Summary line | None | None |

    <RequestExample>
      ```bash
      echo 'var a=1,b=2;console.log(a+b);' | wakaru
      ```
    </RequestExample>

    <ResponseExample>
      ```javascript
      const a = 1;
      const b = 2;
      console.log(a + b);
      ```
    </ResponseExample>

    Warnings use `warning:` labels on stderr. Error-level warnings (for example parse-recovery failures) print `error:` and cause a non-zero exit.
  </Step>
</Steps>

<Note>
Passing a **directory** without `--unpack` fails with `cannot decompile a directory. Pass a JavaScript file or use --unpack`. Directory inputs are valid only with `--unpack`.
</Note>

## Unpack a bundle to a directory

Unpack mode detects the bundle format (webpack 4/5, browserify, SystemJS, esbuild/Bun scope-hoisted, and others), splits it into modules, and decompiles each in parallel. Output is always written as multiple files under `-o`.

<Steps>
  <Step title="Provide bundle input and output directory">
    <ParamField body="--unpack" type="enum (auto | strict)" required>
      Enables bundle splitting. `--unpack` and `--unpack=auto` (default) use structural detection plus heuristic fallback for scope-hoisted bundles. `--unpack=strict` uses structural detection only.
    </ParamField>

    <ParamField body="-o, --output" type="directory" required>
      Destination directory. **Required** with `--unpack`; omitting it fails immediately with `--unpack requires -o/--output to choose an output directory`.
    </ParamField>

    ```bash
    wakaru bundle.js --unpack -o out/
    ```
  </Step>

  <Step title="Inspect the output layout">
    Wakaru creates one `.js` file per extracted module, preserving relative paths from the bundle (for example `src/a.js`, `entry.js`).

    <RequestExample>
      ```bash
      wakaru testcases/webpack5/dist/index.js --unpack -o /tmp/wakaru-out
      ls /tmp/wakaru-out/src/
      ```
    </RequestExample>

    <ResponseExample>
      ```javascript
      // /tmp/wakaru-out/src/a.js
      class A {
          constructor(){
              this.label = 'a';
          }
          print() {
              console.log('a', this.version);
          }
      }
      class A_A {
          constructor(){
              this.label = 'a_a';
          }
      }
      export { A };
      export { A_A };
      ```
    </ResponseExample>

    :::files
    out/
    ├── entry.js
    └── src/
        ├── 1.js
        ├── a.js
        ├── b.js
        └── ...
    :::
  </Step>

  <Step title="Verify success">
    When stderr is a terminal and `--json` is not set, Wakaru prints a summary to **stderr** (not stdout):

    <ResponseExample>
      ```
      detected: webpack5
      total: 7 module(s) in 30ms
      ```
    </ResponseExample>

    For directory inputs, an additional scan line appears:

    <ResponseExample>
      ```
      scanned: 4 file(s), detected: 4 bundle/chunk file(s), skipped: 0 file(s)
      detected: webpack5, scope-hoisted
      total: 85 module(s) in 1.05s
      ```
    </ResponseExample>

    | Signal | Meaning |
    |--------|---------|
    | Exit code `0` | All modules decompiled without error-level warnings |
    | `detected: <formats>` | Bundle formats matched during detection |
    | `total: N module(s)` | Module files written under `-o` |
    | `(K failed)` suffix | Present when `K` modules had error-level warnings; exit is non-zero |
    | Files on disk | One `.js` per module under the output directory |

    <Warning>
      Summary lines are suppressed when stderr is not a terminal (for example in CI pipes). Use `--json` for machine-readable status in that case.
    </Warning>
  </Step>
</Steps>

### Additional unpack inputs

<CodeGroup>
  ```bash Directory scan
  wakaru dist/ --unpack -o out/
  ```
  ```bash Multiple explicit files
  wakaru entry.js chunk.js --unpack -o out/
  ```
  ```bash Raw extraction (no decompile rules)
  wakaru bundle.js --unpack --raw -o out/
  ```
</CodeGroup>

Directory scans recurse into `.js`, `.mjs`, and `.cjs` files, skip hidden paths and `node_modules`, and include only files detected as bundles or chunks. Non-matching files are skipped—not copied or decompiled.

## Stdout vs `-o` behavior

| Mode | `-o` omitted | `-o` set |
|------|--------------|----------|
| Decompile | JS to **stdout** | JS to file; stdout silent |
| Unpack | **Error** — `-o` required | Module files to directory; stdout silent |
| `--json` decompile | JSON to stdout (includes `code`) | JSON to stdout (`code` omitted; file written) |
| `--json` unpack | JSON to stdout | JSON to stdout; modules written to `-o` |

<Info>
With `--json`, structured output always goes to **stdout**. Human-readable summaries and warnings go to **stderr** (warnings are folded into the JSON object and not duplicated on stderr when `--json` is active).
</Info>

### JSON success shapes

<ParamField body="--json" type="flag">
  Emit machine-readable JSON to stdout instead of human-readable summaries.
</ParamField>

**Single-file decompile** (stdout mode — `code` included):

<ResponseExample>
```json
{"code":"const a = 1;\n","warnings":[],"elapsed_ms":10}
```
</ResponseExample>

**Single-file decompile** (with `-o` — `code` omitted, file on disk):

<ResponseExample>
```json
{"warnings":[],"elapsed_ms":9}
```
</ResponseExample>

**Unpack**:

<ResponseExample>
```json
{
  "detected_formats": ["webpack5"],
  "modules": [
    {"filename": "src/1.js"},
    {"filename": "src/a.js"},
    {"filename": "entry.js"}
  ],
  "warnings": [],
  "total": 7,
  "failed": 0,
  "elapsed_ms": 19
}
```
</ResponseExample>

<ResponseField name="total" type="number">
  Module files written to the output directory.
</ResponseField>

<ResponseField name="failed" type="number">
  Modules with error-level warnings. Non-zero `failed` causes a non-zero exit code.
</ResponseField>

<ResponseField name="detected_formats" type="string[]">
  Bundle formats detected (for example `webpack5`, `scope-hoisted`).
</ResponseField>

## Run against repository testcases

The repo ships webpack, browserify, and other fixtures under `testcases/`. Use them to confirm a local build before working on your own bundles.

<CodeGroup>
  ```bash Decompile (cargo)
  cargo run -p wakaru-cli -- testcases/webpack5/dist/index.js -o /tmp/out.js
  ```
  ```bash Unpack webpack5 bundle
  cargo run -p wakaru-cli -- testcases/webpack5/dist/index.js --unpack -o /tmp/unpacked/
  ```
  ```bash Unpack entire dist directory
  cargo run -p wakaru-cli -- testcases/webpack5/dist/ --unpack -o /tmp/unpacked/
  ```
</CodeGroup>

Reference output for webpack5 lives in `testcases/webpack5/dist/index.pretty.js` (prettier-formatted bundle, not per-module unpack output).

## Common first-run failures

| Error | Cause | Fix |
|-------|-------|-----|
| `--unpack requires -o/--output` | Unpack without output directory | Add `-o out/` |
| `no input specified` | No file and stdin is a terminal | Pass a file or pipe stdin |
| `output file … already exists` | `-o` points to an existing file | Delete the file or pass `--force` |
| `output directory … is not empty` | Unpack into a populated directory | Use an empty directory or pass `--force` |
| `errors in N module(s): …` | Error-level warnings during decompile/unpack | Inspect stderr or `--json` warnings; see troubleshooting |

<Tip>
Default rewrite level is `standard`. Pass `--level minimal` for near-zero semantic changes or `--level aggressive` for maximum readability. See [Rewrite levels and assumptions](/rewrite-levels-and-assumptions).
</Tip>

## Next

<CardGroup>
  <Card title="Unpack bundles" href="/unpack-bundles">
    Operational guide for `--unpack` modes, `--raw`, multi-file inputs, directory scanning, and `--force`.
  </Card>
  <Card title="Decompile pipeline" href="/decompile-pipeline">
    Parse → rules → fixer flow for single-file decompilation.
  </Card>
  <Card title="CLI reference" href="/cli-reference">
    Complete flag surface, subcommands, stdin/stdout behavior, and profiling options.
  </Card>
  <Card title="Webpack bundle recipe" href="/webpack-bundle-recipe">
    End-to-end workflow with webpack4/webpack5 testcases.
  </Card>
  <Card title="Troubleshooting" href="/troubleshooting">
    Overwrite protection, skip behavior, warning kinds, and bug-report fields.
  </Card>
</CardGroup>
