diff --git a/CHANGES.md b/CHANGES.md
index 3d2367ba79..8af2100f6e 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -10,8 +10,10 @@ This document is intended for Spotless developers.
We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `1.27.0`).
## [Unreleased]
+### Added
+- Add the ability to specify a wildcard version (`*`) for external formatter executables. ([#2757](https://github.com/diffplug/spotless/issues/2757))
### Changes
-* Bump default `ktlint` version to latest `1.7.1` -> `1.8.0`. ([2763](https://github.com/diffplug/spotless/pull/2763))
+- Bump default `ktlint` version to latest `1.7.1` -> `1.8.0`. ([2763](https://github.com/diffplug/spotless/pull/2763))
## [4.1.0] - 2025-11-18
### Changes
diff --git a/lib/src/main/java/com/diffplug/spotless/ForeignExe.java b/lib/src/main/java/com/diffplug/spotless/ForeignExe.java
index 8697ca68c3..861b66e8de 100644
--- a/lib/src/main/java/com/diffplug/spotless/ForeignExe.java
+++ b/lib/src/main/java/com/diffplug/spotless/ForeignExe.java
@@ -36,6 +36,7 @@
public class ForeignExe implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
+ private static final String VERSION_WILDCARD = "*";
private @Nullable String pathToExe;
private String versionFlag = "--version";
private Pattern versionRegex = Pattern.compile("version (\\S*)");
@@ -111,7 +112,7 @@ public String confirmVersionAndGetAbsolutePath() throws IOException, Interrupted
throw cantFind("Unable to parse version with /" + versionRegex + "/", cmdVersion);
}
String versionFound = versionMatcher.group(1);
- if (!versionFound.equals(version)) {
+ if (!VERSION_WILDCARD.equals(versionFound) && !versionFound.equals(version)) {
throw wrongVersion("You specified version " + version + ", but Spotless found " + versionFound, cmdVersion, versionFound);
}
return exeAbsPath;
diff --git a/plugin-gradle/CHANGES.md b/plugin-gradle/CHANGES.md
index 69fda0c00f..2f9e1fc66d 100644
--- a/plugin-gradle/CHANGES.md
+++ b/plugin-gradle/CHANGES.md
@@ -3,8 +3,10 @@
We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `3.27.0`).
## [Unreleased]
+### Added
+- Add the ability to specify a wildcard version (`*`) for external formatter executables. ([#2757](https://github.com/diffplug/spotless/issues/2757))
### Changes
-* Bump default `ktlint` version to latest `1.7.1` -> `1.8.0`. ([2763](https://github.com/diffplug/spotless/pull/2763))
+- Bump default `ktlint` version to latest `1.7.1` -> `1.8.0`. ([2763](https://github.com/diffplug/spotless/pull/2763))
## [8.1.0] - 2025-11-18
### Changes
diff --git a/plugin-gradle/README.md b/plugin-gradle/README.md
index 2ed91844c9..fe808a043c 100644
--- a/plugin-gradle/README.md
+++ b/plugin-gradle/README.md
@@ -674,7 +674,7 @@ spotless {
[homepage](https://github.com/psf/black). [changelog](https://github.com/psf/black/blob/master/CHANGES.md).
```gradle
-black('19.10b0') // version is optional
+black('19.10b0') // version is optional. Explicitly allow "any found version" with '*'.
// if black is not on your path, you must specify its location manually
black().pathToExe('C:/myuser/.pyenv/versions/3.8.0/scripts/black.exe')
@@ -1211,7 +1211,7 @@ When formatting shell scripts via `shfmt`, configure `shfmt` settings via `.edit
Refer to the `shfmt` [man page](https://github.com/mvdan/sh/blob/master/cmd/shfmt/shfmt.1.scd) for `.editorconfig` settings.
```gradle
-shfmt('3.8.0') // version is optional
+shfmt('3.8.0') // version is optional. Explicitly allow "any found version" with '*'.
// if shfmt is not on your path, you must specify its location manually
shfmt().pathToExe('/opt/homebrew/bin/shfmt')
@@ -1402,7 +1402,7 @@ spotless {
// you have to set the target manually
target 'src/**/*.cs'
- clangFormat('10.0.1') // version is optional
+ clangFormat('10.0.1') // version is optional. Explicitly allow "any found version" with '*'.
// can also specify a code style
clangFormat().style('LLVM') // or Google, Chromium, Mozilla, WebKit
diff --git a/plugin-maven/CHANGES.md b/plugin-maven/CHANGES.md
index 5160f610e8..f6a942d61b 100644
--- a/plugin-maven/CHANGES.md
+++ b/plugin-maven/CHANGES.md
@@ -3,8 +3,10 @@
We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `1.27.0`).
## [Unreleased]
+### Added
+- Add the ability to specify a wildcard version (`*`) for external formatter executables. ([#2757](https://github.com/diffplug/spotless/issues/2757))
### Changes
-* Bump default `ktlint` version to latest `1.7.1` -> `1.8.0`. ([2763](https://github.com/diffplug/spotless/pull/2763))
+- Bump default `ktlint` version to latest `1.7.1` -> `1.8.0`. ([2763](https://github.com/diffplug/spotless/pull/2763))
## [3.1.0] - 2025-11-18
### Changes
diff --git a/plugin-maven/README.md b/plugin-maven/README.md
index 25138c64da..1664aacdd1 100644
--- a/plugin-maven/README.md
+++ b/plugin-maven/README.md
@@ -606,7 +606,7 @@ Additionally, `editorConfigOverride` options will override what's supplied in `.
```xml
- 14.0.0-1ubuntu1.1
+ 14.0.0-1ubuntu1.1
/path/to/buf
@@ -635,7 +635,7 @@ Additionally, `editorConfigOverride` options will override what's supplied in `.
```xml
- 19.10b0
+ 19.10b0
C:/myuser/.pyenv/versions/3.8.0/scripts/black.exe
+ 3.8.0
/opt/homebrew/bin/shfmt
```
@@ -1216,7 +1216,7 @@ Standard Go formatter, part of Go distribution.
```xml
- go1.25.1
+ go1.25.1
/opt/sdks/go1.25.1/bin/go
```
@@ -1303,7 +1303,7 @@ RDF parsing is done via [Apache Jena](https://jena.apache.org/) in the version t
[homepage](https://buf.build/) [buf repo](https://github.com/bufbuild/buf).
```xml
- 1.44.0
+ 1.44.0
/path/to/buf
```