# CLI reference

> Complete wakaru command surface: global flags, unpack modes, subcommands (extract, debug trace/normalize), stdin/stdout behavior, formatter, diagnostics, and profiling options.

- 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

- `crates/cli/src/main.rs`
- `README.md`
- `crates/cli/src/json_output.rs`
- `crates/cli/src/discovery.rs`
- `crates/cli/src/formatter.rs`

---

---
title: "CLI reference"
description: "Complete wakaru command surface: global flags, unpack modes, subcommands (extract, debug trace/normalize), stdin/stdout behavior, formatter, diagnostics, and profiling options."
---

The `wakaru` binary (`wakaru-cli`, distributed as `@wakaru/cli`) is a single clap-driven entry point with two top-level shapes: a default path that decompiles one file or unpacks bundles, and optional subcommands (`extract`, hidden `debug`) that do not accept positional `inputs`. Root flags such as `--json`, `--formatter`, and `--profile` apply only on the default path; `--force` is global.

## Command synopsis

```bash
wakaru [OPTIONS] [INPUTS...]           # decompile or unpack (default)
wakaru extract <MAP> -o <DIR>          # extract sourcesContent from a .map
wakaru debug trace <INPUT> [OPTIONS]   # per-rule pipeline trace (hidden)
wakaru debug normalize [INPUT] [OPTS]  # structural canonicalization (hidden)
```

Positional `inputs` and subcommands are mutually exclusive (`args_conflicts_with_subcommands`). Run `wakaru --help`, `wakaru extract --help`, or `wakaru debug trace --help` for generated flag lists.

## Default mode: decompile

Without `--unpack`, Wakaru accepts exactly one JavaScript/TypeScript file (or stdin) and runs the single-file decompile pipeline.

```bash
wakaru input.js                        # decompiled code to stdout
wakaru input.js -o output.js           # write to file
cat input.js | wakaru > output.js      # stdin when piped or `-`
```

Constraints:

- Multiple positional inputs require `--unpack`.
- A directory argument without `--unpack` errors with *cannot decompile a directory*.
- `--emit-source-map` requires `-o`/`--output`.

## Default mode: unpack

`--unpack` (short `-u`) splits bundles into module files. It **requires** `-o`/`--output` as an output directory.

| Flag form | Behavior |
|-----------|----------|
| `--unpack` or `--unpack=auto` | Structural bundle detection plus heuristic fallback for scope-hoisted output (default) |
| `--unpack=strict` | Structural detection only; no heuristic scope-hoist splitting |

```bash
wakaru bundle.js --unpack -o out/
wakaru bundle.js --unpack --raw -o out/       # raw split, skip decompiler rules
wakaru bundle.js --unpack=strict -o out/
wakaru entry.js chunk.js --unpack -o out/     # multiple explicit files
wakaru dist/ --unpack -o out/                 # recursive directory scan
```

### `--raw`

Requires `--unpack`. Calls `unpack_raw` / `unpack_files_raw` instead of the full decompile pipeline—modules are split but not rewritten for readability. `--formatter` still runs on output when enabled.

### Directory scanning

When an input path is a directory, the CLI recursively collects `.js`, `.mjs`, and `.cjs` files, skips hidden entries and `node_modules`, and keeps only files that pass core bundle/chunk detection (`is_detected_unpack_input`). Non-matching files are skipped—not copied or decompiled. If a directory yields zero detected bundles, Wakaru exits with *no bundle or chunk files detected in directory input*.

Explicit file inputs (non-directory) keep normal fallback behavior when no structural format matches.

On a TTY, unpack summaries on stderr include scan stats (`scanned`, `detected`, `skipped`), detected format names, module count, and elapsed time.

### Output path safety

Unpack resolves each module filename under the output directory, rejecting `..` traversal, absolute paths, drive prefixes, and symlink escapes. Duplicate module names receive deduplicated suffixes (e.g. `index_2.js`).

## Global flags (default path)

| Flag | Short | Default | Description |
|------|-------|---------|-------------|
| `--output` | `-o` | — | Output file (decompile) or directory (`--unpack`) |
| `--unpack` | `-u` | off | Unpack mode: `auto` (default) or `strict` |
| `--raw` | — | off | Raw unpack only; requires `--unpack` |
| `--source-map` | `-m` | — | Input `.map` for identifier recovery and import dedup. Alias: `--sourcemap`. Single input only. |
| `--level` | — | `standard` | Rewrite level: `minimal`, `standard`, `aggressive` |
| `--dce` | — | off | Full dead-code elimination (reachability sweep). Default without flag: transform-induced DCE only (`TransformOnly`). |
| `--diagnostics` | — | off | Post-transform checks; results appear as warnings |
| `--formatter` | — | off | Final oxc formatting pass |
| `--emit-source-map` | — | off | Write `output.js.map` alongside each output file |
| `--json` | — | off | Machine-readable JSON on stdout |
| `--profile` | — | — | Chrome trace file (`chrome://tracing`) |
| `--profile-rules` | — | off | Per-rule DEBUG spans in profile; requires `--profile` |
| `--force` | — | off | Overwrite existing outputs (global; all commands) |

## Stdin and stdout

| Scenario | Input | Primary output | Secondary output |
|----------|-------|----------------|------------------|
| Decompile, no `-o` | file or stdin | stdout (code) | warnings → stderr |
| Decompile, with `-o` | file or stdin | file | warnings → stderr; `.map` if `--emit-source-map` |
| Unpack | file(s), dir, or stdin | files under `-o` | summary → stderr (TTY); warnings → stderr |
| `--json` decompile, no `-o` | any | stdout (JSON with `code`) | — |
| `--json` decompile, with `-o` | any | stdout (JSON without `code`); file written | — |
| `--json` unpack | any | stdout (JSON metadata) | files still written to `-o` |

Stdin is read when the input is `-`, or when no input is given and stdin is not a terminal. Filename is recorded as `<stdin>`.

With `--json`, human-readable warning lines are suppressed; warnings are embedded in the JSON object. Terminal styling (`NO_COLOR` respected) is disabled for JSON runs.

## Formatter

`--formatter` selects the oxc formatter (`CodeFormatter::Oxc`) for a final pass after decompilation. Off by default.

If formatting fails, Wakaru prints a stderr warning and preserves the unformatted code:

```
warning: oxc formatter failed for <file>, preserving output: <message>
```

## Diagnostics

`--diagnostics` enables post-transform checks in the core driver: temporal-dead-zone (use-before-declaration) detection, recovered input/output parse errors, and duplicate lexical declarations. Findings are returned as `UnpackWarning` entries—error-severity diagnostics cause a non-zero exit after output is written.

## JSON output

`--json` prints a single JSON object to stdout.

**Decompile** (`JsonDecompileOutput`):

| Field | When present |
|-------|--------------|
| `code` | Only when `-o` is omitted (stdout mode) |
| `source_map` | When `--emit-source-map` produced a map |
| `warnings` | Always (may be empty) |
| `elapsed_ms` | Always |

**Unpack** (`JsonUnpackOutput`):

| Field | Description |
|-------|-------------|
| `detected_formats` | Bundle format strings detected |
| `modules` | `{ filename }` per module (code is written to disk, not inlined) |
| `warnings` | Per-module warnings |
| `total` | Module files written |
| `failed` | Count of modules with error-severity warnings |
| `elapsed_ms` | Wall-clock time |

Each warning object: `filename`, `kind`, `is_error`, `message`.

See [JSON output and CI integration](/json-output-and-ci) for piping patterns and warning kinds.

## Profiling

```bash
wakaru input.js --profile trace.json
wakaru input.js --profile trace.json --profile-rules
```

`--profile` writes a Chrome trace event file. `--profile-rules` lowers the tracing filter to DEBUG so individual rule spans appear. The profile guard flushes on normal exit.

Profiling initializes before command dispatch, but `--profile` is a root-level flag—use it on the default decompile/unpack path, not on subcommands.

## Subcommand: `extract`

```bash
wakaru extract bundle.js.map -o src/
```

Reads a v3 source map, writes every `sourcesContent` entry under `-o`, creating parent directories as needed. Respects `--force` for output directory overwrite protection. Prints an extraction count to stderr on a TTY. The legacy `--extract` flag is no longer supported.

## Subcommand: `debug` (hidden)

Internal commands for regression matrices and pipeline bisection. Omitted from default `--help` output.

### `debug trace`

```bash
wakaru debug trace input.js
wakaru debug trace input.js -o trace.txt --from UnEsm --until SmartInline --all
wakaru debug trace input.js -m input.js.map --level aggressive
```

| Flag | Default | Description |
|------|---------|-------------|
| `-o` / `--output` | stdout | Trace output file |
| `-m` / `--source-map` | — | Input source map |
| `--from` | pipeline start | First rule name (must match `rule_names()`) |
| `--until` | pipeline end | Last rule name |
| `--all` | off | Include unchanged rules (default: changed only) |
| `--level` | `standard` | Rewrite level |

Produces a git-style unified diff log: initial source, then per-rule deltas. **Bundle inputs are rejected**—tracing supports single-file inputs only. Use normal decompile or unpack for bundles.

### `debug normalize`

```bash
wakaru debug normalize input.js
wakaru debug normalize --rename --format < input.js
```

| Flag | Description |
|------|-------------|
| `input` | Optional file; `-` or omitted with piped stdin |
| `--rename` | Alpha-rename locals to `$0`, `$1`, … for structural comparison |
| `--format` | Run oxc formatter after canonicalization |

Output always goes to stdout. Used by reproduction matrices to compare mangled and original code structurally.

## Overwrite protection

| Target | Without `--force` | With `--force` |
|--------|-------------------|----------------|
| Output file (`-o` decompile) | Error if file exists | Overwrite |
| Output directory (`--unpack`) | Error if directory exists and is non-empty | Write into directory |
| Non-empty forced directory | — | Uses write-if-changed for identical files |

Empty or newly created output directories write files directly.

## Exit codes

| Outcome | Code |
|---------|------|
| Success | 0 |
| CLI validation, I/O, or processing error (`bail!`) | 1 |
| Warnings with `is_error: true` after successful write | 1 |
| Internal panic | Non-zero; panic hook prints a GitHub issue URL with version and OS |

## Examples

```bash
# Minimal-change audit
wakaru audit.js --level minimal -o audit.pretty.js

# Aggressive readability with full DCE
wakaru min.js --level aggressive --dce --formatter -o readable.js

# CI-friendly unpack
wakaru dist/ --unpack --json -o out/ 2>log.txt

# Source-map-driven decompile
wakaru bundle.min.js -m bundle.min.js.map --emit-source-map -o restored.js

# Bisect a regression between two rules
wakaru debug trace broken.js --from UnBracketNotation --until SmartInline -o trace.txt
```

<Callout type="info">
`--source-map` applies to a single input file. Multi-file unpack with `-m` is rejected at the CLI layer.
</Callout>

## Related pages

<CardGroup>
  <Card title="Quickstart" href="/quickstart">
    First successful decompile and unpack runs with expected stdout and stderr signals.
  </Card>
  <Card title="Unpack bundles" href="/unpack-bundles">
    Operational guide for auto vs strict modes, raw extraction, multi-file inputs, and directory scanning.
  </Card>
  <Card title="Use source maps" href="/use-source-maps">
    Identifier recovery, import dedup, emit maps, and the extract subcommand.
  </Card>
  <Card title="JSON output and CI" href="/json-output-and-ci">
    Machine-readable schemas, warning kinds, and automation patterns.
  </Card>
  <Card title="Trace the rule pipeline" href="/trace-rule-pipeline">
    Bisect regressions with debug trace, profile export, and rule name ranges.
  </Card>
  <Card title="Rewrite levels" href="/rewrite-levels-and-assumptions">
    minimal / standard / aggressive tradeoffs and --dce semantics.
  </Card>
  <Card title="Troubleshooting" href="/troubleshooting">
    Overwrite errors, directory skip behavior, formatter failures, and warning codes.
  </Card>
</CardGroup>
