# jdx diff

IDE equivalent: Public-API diff + binary-compat warnings (upgrades)

Compare the public API of two artifacts and report every difference, most breaking first: removed members, narrowed visibility, changed descriptors, final/abstract/static flips, throws clauses and Kotlin-visible changes. Each finding names one rule (MEMBER_REMOVED, RETURN_TYPE_CHANGED, ...) so a caller can filter on the rule rather than on prose. Exits 0 whenever the comparison ran, whatever it found — add --fail-on breaking (or --fail-on any) to exit 1 in a pipeline. Exits 3 on a bad spec or flag, 5 when an artifact cannot be read. Each spec is a jar file, class directory, glob, or Maven coordinate (with --fetch). No workspace is needed.

## Usage

```text
jdx diff [<options>] <oldartifact> <newartifact>
```

## Example

```console
$ jdx diff com.google.code.gson:gson:2.11.0 com.google.code.gson:gson:2.14.0 --fetch
api diff com.google.code.gson:gson:2.11.0 -> com.google.code.gson:gson:2.14.0 (public surface)
info  TYPE_ADDED  com.google.gson.internal.GsonTypes
info  TYPE_ADDED  com.google.gson.internal.bind.JsonElementTypeAdapter
info  MEMBER_ADDED  com.google.gson.FieldNamingStrategy#alternateNames(java.lang.reflect.Field)
info  MEMBER_ADDED  com.google.gson.internal.ConstructorConstructor#get(com.google.gson.reflect.TypeToken, boolean)
info  MEMBER_ADDED  com.google.gson.internal.bind.TypeAdapters#BIG_DECIMAL_FACTORY
info  MEMBER_ADDED  com.google.gson.internal.bind.TypeAdapters#BIG_INTEGER_FACTORY
info  MEMBER_ADDED  com.google.gson.internal.bind.TypeAdapters#DOUBLE_STRICT
info  MEMBER_ADDED  com.google.gson.internal.bind.TypeAdapters#FLOAT_STRICT
info  MEMBER_ADDED  com.google.gson.internal.bind.TypeAdapters#LAZILY_PARSED_NUMBER_FACTORY
info  MEMBER_ADDED  com.google.gson.internal.bind.TypeAdapters#LONG_AS_STRING
info  MEMBER_ADDED  com.google.gson.internal.bind.TypeAdapters#atomicLongAdapter(com.google.gson.TypeAdapter)
info  MEMBER_ADDED  com.google.gson.internal.bind.TypeAdapters#atomicLongArrayAdapter(com.google.gson.TypeAdapter)
info  MEMBER_ADDED  com.google.gson.internal.bind.TypeAdapters#javaTimeTypeAdapterFactory()
info  MEMBER_ADDED  com.google.gson.internal.sql.SqlTypesSupport#SQL_TYPE_FACTORIES
info  MEMBER_ADDED  com.google.gson.stream.JsonReader#getNestingLimit()
info  MEMBER_ADDED  com.google.gson.stream.JsonReader#setNestingLimit(int)
info  FIELD_CONSTANT_VALUE_CHANGED  com.google.gson.internal.GsonBuildConfig#VERSION: "2.11.0" -> "2.14.0"
0 breaking · 0 suspicious · 17 informational · 2 types added · 0 types removed
warning MULTI_RELEASE_VARIANT: in com.google.code.gson:gson:2.11.0: multi-release gson-2.11.0.jar serves version-specific variants for this JDK (21)
warning MULTI_RELEASE_VARIANT: in com.google.code.gson:gson:2.14.0: multi-release gson-2.14.0.jar serves version-specific variants for this JDK (21)
warning UNNAMEABLE_CLASS: in com.google.code.gson:gson:2.11.0: unnameable class name (empty name segment in [, Gson, Preconditions]): com/google/gson/internal/$Gson$Preconditions.class
warning UNNAMEABLE_CLASS: in com.google.code.gson:gson:2.11.0: unnameable class name (empty name segment in [, Gson, Types]): com/google/gson/internal/$Gson$Types.class
warning UNNAMEABLE_CLASS: in com.google.code.gson:gson:2.11.0: unnameable class name (empty name segment in [, Gson, Types, GenericArrayTypeImpl]): com/google/gson/internal/$Gson$Types$GenericArrayTypeImpl.class
warning UNNAMEABLE_CLASS: in com.google.code.gson:gson:2.11.0: unnameable class name (empty name segment in [, Gson, Types, ParameterizedTypeImpl]): com/google/gson/internal/$Gson$Types$ParameterizedTypeImpl.class
warning UNNAMEABLE_CLASS: in com.google.code.gson:gson:2.11.0: unnameable class name (empty name segment in [, Gson, Types, WildcardTypeImpl]): com/google/gson/internal/$Gson$Types$WildcardTypeImpl.class
source: com.google.code.gson:gson:2.11.0 (bytecode)
source: com.google.code.gson:gson:2.14.0 (bytecode)
next: jdx members com.google.gson.internal.GsonTypes
```

## Options

| Option | Description |
|---|---|
| `--visibility=(public\|all)` | Which declarations to compare: public (the default — public and protected types and members, the surface a consumer compiles against) or all (every declared type and member, for refactors and mod/mixin work). |
| `--include-synthetic` | Compare bridge/synthetic members too, hidden by default. |
| `--severity=(all\|suspicious\|breaking)` | How much of the report to print: all (the default), suspicious (breaking and suspicious), or breaking only. The per-severity tally always describes the whole comparison, never only what was printed. |
| `--fail-on=(none\|breaking\|any)` | Turn the report into a process status: breaking exits 1 when a breaking change is present, any exits 1 on any difference. Without it a successful comparison always exits 0. |
| `--limit=<int>` | Maximum findings shown (default 200); the rest become a truncation footer. The tail this cuts is by construction the least severe. |
| `--fetch` | Allow downloading a Maven coordinate from Maven repositories (Central by default, --repo to add mirrors). Without it, coordinates resolve from ~/.gradle/caches and ~/.m2 only. |
| `--repo=<text>` | Maven repository base URL for --fetch (repeatable). Tried in flag order before Maven Central, which stays last as the fallback. |
| `--json` | Emit machine-readable JSON instead of human-readable text (same information, D-007). |
| `--no-color` | Disable ANSI colors even on a TTY (piped output is always plain). |
| `-h, --help` | Show this message and exit |

## Arguments

| Argument | Description |
|---|---|
| `<oldartifact>` | Baseline artifact: jar, class dir, glob, or group:artifact:version. |
| `<newartifact>` | Candidate artifact, compared against the baseline. |

## Full help text

```console
$ jdx diff --help
Usage: jdx diff [<options>] <oldartifact> <newartifact>

  Compare the public API of two artifacts and report every difference, most breaking first: removed members, narrowed visibility, changed descriptors, final/abstract/static flips, throws clauses and Kotlin-visible changes. Each finding names one rule (MEMBER_REMOVED, RETURN_TYPE_CHANGED, ...) so a caller can filter on the rule rather than on prose. Exits 0 whenever the comparison ran, whatever it found — add --fail-on breaking (or --fail-on any) to exit 1 in a pipeline. Exits 3 on a bad spec or flag, 5 when an artifact cannot be read. Each spec is a jar file, class directory, glob, or Maven coordinate (with --fetch). No workspace is needed.

Options:
  --visibility=(public|all)             Which declarations to compare: public (the default — public and protected types and members, the surface a consumer compiles against) or all (every declared type and member, for refactors and mod/mixin work).
  --include-synthetic                   Compare bridge/synthetic members too, hidden by default.
  --severity=(all|suspicious|breaking)  How much of the report to print: all (the default), suspicious (breaking and suspicious), or breaking only. The per-severity tally always describes the whole comparison, never only what was printed.
  --fail-on=(none|breaking|any)         Turn the report into a process status: breaking exits 1 when a breaking change is present, any exits 1 on any difference. Without it a successful comparison always exits 0.
  --limit=<int>                         Maximum findings shown (default 200); the rest become a truncation footer. The tail this cuts is by construction the least severe.
  --fetch                               Allow downloading a Maven coordinate from Maven repositories (Central by default, --repo to add mirrors). Without it, coordinates resolve from ~/.gradle/caches and ~/.m2 only.
  --repo=<text>                         Maven repository base URL for --fetch (repeatable). Tried in flag order before Maven Central, which stays last as the fallback.
  --json                                Emit machine-readable JSON instead of human-readable text (same information, D-007).
  --no-color                            Disable ANSI colors even on a TTY (piped output is always plain).
  -h, --help                            Show this message and exit

Arguments:
  <oldartifact>  Baseline artifact: jar, class dir, glob, or group:artifact:version.
  <newartifact>  Candidate artifact, compared against the baseline.
```

## Learn more

Guide: [API diff for upgrades](https://mohammadmd1383.github.io/jdx/docs/api-diff/) · [All commands](https://mohammadmd1383.github.io/jdx/docs/reference/)
