[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/CKAndroidProject/ddc/main/docs/cli.md [Back]  [Original]

# CLI reference

[English] | [](zh-CN/cli.md)

Everything `ddc --help` tells you, in more detail: invocation modes,
every option's semantics, every subcommand's output format and behavior.
The binary's help is the quick card; this is the manual.

Two invocation modes:

```
ddc [OPTIONS] ... [OUTPUT]      # full decompile
ddc  [ARGS...]             # progressive analysis (query)
```

## Language

Messages (help, errors, summaries, table headers) localize automatically:
`DDC_LANG` (explicit `zh`/`en`) overrides `LC_ALL` > `LC_MESSAGES` > `LANG`;
any `zh*` value selects Chinese, everything else falls back to English.

```bash
DDC_LANG=zh ddc --help    # 
LANG=zh_CN.UTF-8 ddc -V   # also Chinese
DDC_LANG=en ddc -V        # forced English even under a zh locale
```

## Full decompile

`ddc [OPTIONS] ... [OUTPUT]`

**Inputs** (multiple merge into one class pool; duplicate classes are
deduplicated, first definition wins):

- `.dex`  versions 035041
- `.apk` / `.jar` / `.zip`  every `classes.dex`, `classes2.dex`,  entry,
  merged in numeric order
- `.xapk` / `.apks` / `.apkm`  a zip of APKs: every inner APK's dexes
  merge, base first; labels are three-level (`container!base.apk!
  classes.dex`)
- a directory  scanned recursively for all of the above

**Output**  the last positional argument or `-o`:

- ``  output root, package structure preserved; default
  `-out/` next to the input
- ``  a single class only (single-class input or `-c`)
- `-`  stdout, classes separated by `// ===== class =====` lines, in pool
  order (forces one thread)

Positional-argument disambiguation: with no `-o` and two or more
positionals, a **last** argument that isn't input-shaped (no dex-bearing
extension, not an existing file, not a directory containing dex files) is
the output  so `ddc app.apk out/` writes into the pre-created `out/`,
while `ddc a.dex dump/` treats a real dex directory as an input.

| Option | Semantics |
|---|---|
| `-o, --output ` | output location: dir / `file.java` / `-` |
| `-c, --class FQCN` | decompile only this class (dotted or slashed; nested/anonymous/local classes of it come along) |
| `-l, --list` | list class names and exit |
| `-t, --threads ` | worker count (default: CPU count; stdout forces one for pool order) |
| `--no-comments` | omit the provenance header |
| `-v, --verbose` | per-dex stats and slow classes on stderr |
| `-h, --help` / `-V, --version` | help / name+version+homepage |

`--opt=value` and `-o=path` forms both work. Bare `ddc help` / `ddc
version` do the same as `-h` / `-V`.

**Provenance header** (unless `--no-comments`):

```java
// Decompiled by https://github.com/ejfkdev/ddc 1.2.3
// From: app!classes3.dex (DEX 038)
// Source file: Foo.java
```

`From:` names the input file, the dex image, and the DEX version  the
fastest clue for which image a class lives in (jadx's `loaded from:`
pattern). Headers carry no timestamps, so two runs diff cleanly; a few
variable IDs may still differ between runs (std HashMap seed), with
identical semantics.

**Exit codes**: `0` success; `1` some classes failed (e.g. a
pathological-CFG timeout); `2` usage error (the error, then the full
help). A one-line summary goes to stderr when a run finishes: `ddc:
wrote 98348 file(s) to out/, 1 failed in 6.13s`.

## Progressive-analysis subcommands

All of them accept `-d/--dex NAME` (repeatable; entry-name substring 
the filter runs before parsing, so `getclass --dex classes20` parses
exactly one image) and most accept `-o FILE` to write the result.
Queries never enter the lift/structure/render pipeline; stdout stays
clean (timing prints only with `-o`).

### Get oriented

- **`ddc info `**  one command, the whole picture. A context
  header first (when a manifest exists): app label  an `@0x` ref is
  resolved through a minimal resources.arsc walk, literals print
  as-is  package, `versionName (versionCode)`, custom Application
  class, launcher activity, `uses-sdk` bounds, file size and MD5 (the
  label lookup mirrors the manifest's base-first container rule). Then
  the per-dex table: one row per image with version, class, method,
  field, string counts, plus a total row. Bare `.dex` inputs skip the
  header (no manifest) and print the table only.
- **`ddc listclasses  [pattern]`**  class names (internal
  `com/foo/Bar` form); pattern is a case-insensitive substring.
- **`ddc manifest  [--component C] [-o FILE]`**  decodes the
  binary AndroidManifest.xml to text XML. `--component` filters to one
  element kind: `launcher` (the MAIN/LAUNCHER activity), `activity`,
  `service`, `receiver`, `provider`, `permission`, `activity-alias`,
  `application`. Raw `.axml` files are accepted directly. In XAPK/APKS
  containers the base APK's manifest is used.
- **`ddc mainactivity `**  package, custom Application class (if
  any), and the launcher activity, resolved through relative-name rules
  (`.MainActivity`  package-prefixed; bare word  package + word) and
  activity-alias `targetActivity`; then verified against the dex images
  (the defining image is reported).
- **`ddc res  [entry] [-o FILE]`**  without an entry: every archive
  entry (method, compressed size; XAPK inner APKs flattened into
  `apk!name` labels). With an entry: dumps it  binary XML (first chunk
  `0x0003`) decodes through the AXML decoder, text prints as-is, binary
  content is saved via `-o` (or the error tells you to). Entry matching:
  exact name first, then a unique substring.

### Find things

- **`ddc strings  [-f TEXT] [--with-locations]`**  the string
  table (one row per string). `-f` filters by substring;
  `--with-locations` walks every method's const-string sites and adds a
  `used-by` column mapping each hit to its owner methods.
- **`ddc findrefs    [--class
  FQCN] [--fuzzy-class] [-o FILE]`**  every reference to a string
  literal / type / method call site / field access. Output is columnar
  with a header (`dex kind class method refs`), **one row per method**:
  multiple hits aggregate into `refs` (`; `-separated, deduped); `kind`
  is the first hit's instruction. Match semantics: queries are
  case-insensitive substrings; `--class` defaults to exact (dots,
  slashes and `L;` descriptor forms all normalize) and `--fuzzy-class`
  widens it to substring.
- **`ddc callers  NAME [FQCN]`**  who invokes method NAME (the
  findrefs method machinery, scoped to one class optionally).
- **`ddc members  [NAME] [--class FQCN] [--fuzzy-class]
  [--method|--field]`**  method/field name search over the method and
  field id tables; `--method` / `--field` restrict the kind.

### Understand structure

- **`ddc hierarchy  FQCN`**  the class's lineage: `class` /
  `extends` / `implements` forward, `sub` / `impl` for every class that
  extends or implements it. Works across images (name-matched when the
  parent lives in another dex).
- **`ddc largest  [-n N]`**  top-N methods by instruction count
  (find the monsters; default 20).
- **`ddc disasm  FQCN[.method]`**  raw bytecode of a class or
  one method: one line per instruction (`pc opcode mnemonic`). The
  target resolves as a whole-string class first, then splits at the last
  dot  so both `org.foo.Cells.t1` (a class) and `Greeter.greet` (a
  method) work.

### Decompile surgically

- **`ddc getclass  FQCN [-o FILE] [--dex NAME]`**  one class
  with its nested/anonymous/local classes, through the full pipeline.
  Ambiguous names (defined in several images) get a warning listing the
  images; the defining image is registered first so the pool resolves
  from it.
- **`ddc getmethod  FQCN[.method] [-o FILE]`**  one method,
  sliced out of the decompiled class: provenance header + package line +
  every matching overload, dedented. A miss lists the class's method
  names. A bare class name falls back to the whole class.
- **`ddc pkg  PACKAGE [-o DIR] [-t N] [--app]`**  decompile a
  whole package subtree through the full pipeline (default output:
  `-pkg/` next to the input). `""` or `.`
  means the root (default package included). `--app` takes the package
  from the manifest  and when that package has no classes (Telegram:
  manifest says `org.telegram.messenger.web`, code lives in
  `org.telegram.messenger`) it retries with the launcher class's
  package, which is where an app's own code clusters.

## Output quality passes

Four passes clean the decompiled body, all on by default:

- **jadx-style local names**  a synthetic `v12`/`p3` never survives
  when a better name exists: a Kotlin
  `Intrinsics.checkNotNullParameter(x, "name")` names `x` from the
  message string (the compiler wrote the real parameter name into the
  check); the single consistent defining call (`getFoo()  foo`,
  `new File()  file`); jadx's type-alias table (`str/cls/it/`)
  with the lowercased class simple name as fallback. Collisions take
  `2, 3, `; debug-info names are never touched.
- **Kotlin null-check elision**  statement-position
  `Intrinsics.checkNotNull` calls are runtime assertions; they are
  dropped after the naming pass harvested their strings (lark:
  59,106  9).
- **Synthetic-accessor inlining**  `access$NNN` static bridges inline
  at call sites when the body is an identity, a field getter, or a
  method forwarder (the d8 APM trace wrappers around the core are
  tolerated). Only STATIC+SYNTHETIC callees qualify. lark: 43% of
  9,214 call sites.
- **IntDef constant rendering**  see below.

## Platform symbols

ddc renders IntDef/LongDef literal arguments as their constant names
out of the box (`setVisibility(8)`  `android.view.View.GONE`). The
domain table (android-37) lives in the repo as a READABLE,
diffable text file  `crates/ddc-cli/src/platform_symbols.txt`, one
domain per line  which build.rs raw-DEFLATEs into the binary (72KB).
Regenerate with `scripts/gen-platform-symbols.sh [platform-dir]` and
commit the .txt. The table is exact-match  combined flag values stay
numeric  and version-independent in effect: methods missing from the
baked API level simply stay numeric. Startup cost is under 5ms.

`--symbols ` (e.g.
`~/Library/Android/sdk/platforms/android-37.0`, needs `android.jar`
and `data/annotations.zip`) rebuilds the table from that platform for
this invocation, overriding the built-in  full decompile and
subcommands alike.

## Exit codes for subcommands

Usage errors (missing arguments, unknown options, bad `--dex`) print the
error plus the full help and exit `2`. Query misses (class/method/entry
not found) are also `2` but carry the specific miss in the error 
`getmethod` lists the available methods, `--dex` the available images.

Web Proxy Viewer  |  New URL  |  Original Page