Spec languages

Matcher, selector, mapper, source and sink expressions used by Toolbox

Many Toolbox commands accept a spec string (options like --artifactVersionMatcherSpec, --sinkSpec, or the source/sink parameters of gav-copy). Every spec is parsed by the same tiny parser (eu.maveniverse.maven.toolbox.shared.internal.SpecParser) and then interpreted by a class-specific builder. This page documents the common syntax and every “language” built on top of it.

LanguageProducesExample
Artifact version matcherPredicate<Version>and(noSnapshotsAndPreviews(), constraint('[,4)'))
Artifact version selectorversion stringcontextualSnapshotsAndPreviews(last())
Artifact matcherPredicate<Artifact>and(artifact(org.apache.maven*), not(snapshot()))
Dependency matcherPredicate<Dependency>and(scopeIncluded(compile,runtime), optional(false))
Artifact name mapperString from artifactcompose(fixed(libs/), AbVE())
Artifact mapperArtifact → Artifactcompose(omitClassifier(), baseVersion())
Dependency mapperDependency → Dependencycompose(scope(compile), optional(false))
Artifact key factorykey StringversionlessId()
Artifact differentiatorkey StringmajorVersion()
Artifact sourcestream of artifactsresolveTransitive(gav(g:a:1.0), test)
Artifact sinkconsumer of artifactsmatching(not(snapshot()), flat(target/libs))
Dependency sinkconsumer of dependenciesmatching(scopeIncluded(test), counting())

Common syntax

A spec is a tree of operations and literals:

spec    := op
op      := name '(' [ arg ( ',' arg )* ] ')'
arg     := op | literal
literal := bare | quoted
  • The root of a spec must be an operation: any() is a spec, any is not.
  • Operation names are case-sensitive. An operation without arguments still needs ().
  • Bare literals may contain letters, digits and the characters * : . - / \ $ { } [ ]. Whitespace outside of quotes is ignored (also inside bare literals: a b is the same as ab).
  • Quoted literals are enclosed in single quotes and may contain any character except ' (there is no escaping). Whitespace is preserved. Use them whenever a value contains (, ), ,, +, _, @, spaces, etc., for example version ranges: constraint('[,32.1)'). '' is the empty string.
  • Property references: a literal that is exactly ${name} is replaced by the value of property name (the resolver session config properties, which include Java system and user properties). Unknown properties become the empty string. Partial interpolation (foo-${name}) is not supported. Note: a few operations read some arguments raw, without interpolation; these are marked with (raw) below.
  • Syntax errors (bad characters, unbalanced parentheses, dangling commas, unterminated quote) and unknown operations fail with an “Invalid … spec” error.

Some operations take another language as argument; e.g. matching(...) in a sink takes an artifact matcher as first argument and a sink as second. This is noted in the argument descriptions below.

Known quirks

  • Variadic arguments (X...) are collected in reverse order. For and/or/tee this rarely matters, but compose(...) of artifact and dependency mappers applies its arguments right to left.

Notation in the tables: str is a literal, bool is a literal true/false (anything else is false), X... means zero or more arguments of type X, [x] means optional.


Artifact version matcher

ArtifactVersionMatcher — a predicate over versions. Used for filtering available versions (e.g. options --artifactVersionMatcherSpec, default usually noSnapshotsAndPreviews(), and --parentVersionMatcherSpec). Versions are parsed using the session version scheme.

OperationMatches
any()every version
snapshot()snapshot versions (-SNAPSHOT or timestamped)
preview()“preview” versions: contains alpha, beta, milestone, rc or cr, or a/b/m immediately followed by a digit (case-insensitive)
noSnapshots()shorthand for not(snapshot())
noPreviews()shorthand for not(preview())
noSnapshotsAndPreviews()shorthand for and(noSnapshots(), noPreviews())
eq(str)versions equal to given version
gt(str) / gte(str)versions greater than / greater or equal to given version
lt(str) / lte(str)versions less than / less or equal to given version
range(str)versions contained in given version range, e.g. range('[1.0,2.0)')
constraint(str)versions contained in given version constraint (a range, or a plain version), e.g. constraint('[,32.1)')
not(matcher)negation
and(matcher...)all matchers match
or(matcher...)any matcher matches

Examples:

noSnapshotsAndPreviews()
and(noSnapshotsAndPreviews(), lt(4.0.0))
and(noPreviews(), constraint('[3.9,4)'))
or(eq(1.0), eq(2.0))

Artifact version selector

ArtifactVersionSelector — given an artifact and the ascending sorted list of its available versions, selects one version. Used by options --artifactVersionSelectorSpec (default usually contextualSnapshotsAndPreviews()). Every selector falls back to the artifact’s own version when it cannot select anything (e.g. empty list).

OperationSelects
identity()the artifact’s current version
first()the first (lowest) version
last()the last (highest) version
prev()the highest version lower than the current one
next()the lowest version higher than the current one
major()the last version with the same major (prefix up to first .) as the current one; if the current version has no major part, does last()
minor()the last version with the same major.minor (prefix up to second .); if the current version has no minor part, does major()
filtered(versionMatcher, selector)applies selector to versions accepted by the version matcher
noSnapshots(selector)selector applied to non-snapshot versions
noPreviews(selector)selector applied to non-preview versions
noSnapshotsAndPreviews(selector)selector applied to versions that are neither snapshots nor previews
contextualSnapshotsAndPreviews([selector])filtering depends on current version: if it is a snapshot, no filtering; if it is a preview, snapshots are filtered out; otherwise both snapshots and previews are filtered out. Then selector is applied (default major())

Examples:

last()
contextualSnapshotsAndPreviews(last())
filtered(lt(4.0.0), noSnapshotsAndPreviews(last()))

Artifact matcher

ArtifactMatcher — a predicate over artifacts.

OperationMatches
any()every artifact
none()no artifact
snapshot()snapshot artifacts
withoutClassifier()artifacts with no (or blank) classifier
artifact(str)artifacts matching a coordinate pattern, see below
unique()stateful: matches an artifact only the first time it is seen (keyed by full coordinates)
uniqueBy(nameMapper)stateful: like unique(), keyed by the given artifact name mapper, e.g. uniqueBy(GAKey())
not(matcher)negation
and(matcher...)all match
or(matcher...)any matches

Coordinate patterns for artifact(...); missing parts mean *:

Pattern formExample
groupIdorg.apache.maven
groupId:artifactIdorg.apache.maven:maven-core
groupId:artifactId:versionorg.slf4j:*:2*
groupId:artifactId:extension:version*:*:pom:*
groupId:artifactId:classifier:extension:version*:*:sources:jar:*

Each part is matched with a simple glob: * (anything), foo* (starts with), *foo (ends with), *foo* (contains), otherwise exact match. Note that the 5-part form is classifier before extension.

Examples:

artifact(org.apache.maven*)
and(artifact(org.slf4j), not(snapshot()))
and(withoutClassifier(), uniqueBy(GAKey()))

Dependency matcher

DependencyMatcher — a predicate over dependencies (artifact + scope + optional flag). Used by tree-related commands (e.g. gav-tree) and by dependency sinks.

OperationMatches
any()every dependency
none()no dependency
scopeIncluded(str...)dependencies whose scope is one of the given scopes
scopeExcluded(str...)dependencies whose scope is none of the given scopes
optional(bool)dependencies whose optional flag equals the given value
artifact(str)dependencies whose artifact matches the coordinate pattern (same as artifact(...) of artifact matcher)
not(matcher)negation
and(matcher...)all match
or(matcher...)any matches

Examples:

scopeExcluded(test,provided)
and(scopeIncluded(compile,runtime), optional(false), not(artifact(org.slf4j)))

Artifact name mapper

ArtifactNameMapper — maps an artifact to a string; used for file names (flat(...), unpack(...) sinks) and keys (uniqueBy(...)). Letters stand for GroupId, ArtifactId, Version, bV (base version, i.e. 1.0-SNAPSHOT instead of 1.0-20240101.123456-1), Classifier and Extension.

Single fields:

OperationResult
G() A() V() bV() C() E()the corresponding single field
P(key, default)artifact property key, or default if absent

Keys (colon separated):

OperationResult
GAKey()g:a
GAVKey()g:a:v
GAbVKey()g:a:bV
GACEVKey()full artifact string g:a:e[:c]:v

File names (classifier part including its - is omitted when the classifier is empty):

OperationResultOperationResult
GACVE()g.a[-c]-v.eACVE()a[-c]-v.e
GACbVE()g.a[-c]-bV.eACbVE()a[-c]-bV.e
GACE()g.a[-c].eAVCE()a-v[-c].e
GAVE()g.a-v.eAbVCE()a-bV[-c].e
GAbVE()g.a-bV.eACE()a[-c].e
GAE()g.a.eAVE()a-v.e
AbVE()a-bV.e
AE()a.e

Others:

OperationResult
repositoryDefault()Maven repository layout path, using the OS file separator
repository(str)Maven repository layout path, using given separator (e.g. repository(/))
empty()empty string
fixed(str)the given (non-blank) string
optionalPrefix(str, mapper)str + mapper result, or empty string if the mapper result is blank
optionalSuffix(str, mapper)mapper result + str, or empty string if the mapper result is blank
compose(mapper...)concatenation of all mapper results, in order

Examples:

AbVCE()
compose(G(), fixed(/), AVE())
compose(A(), optionalPrefix(-, C()), fixed(.), E())

Artifact mapper

ArtifactMapper — transforms an artifact into another artifact. Used by mapping(...) sources/sinks.

OperationResult
identity()artifact unchanged
baseVersion()version replaced with base version (timestamped snapshot → -SNAPSHOT)
versionSuffix(str)version + str
baseVersionSuffix(str)base version + str
omitClassifier()classifier removed
rename(g, a, v)groupId, artifactId and version replaced; * keeps the original value
compose(mapper...)applies mappers one after another

Note: compose(...) currently applies its arguments right to left (the last argument first), so compose(versionSuffix(-x), rename(*,*,2)) turns a:x:1 into a:x:2-x.

Examples:

omitClassifier()
rename(org.example,*,1.0.0)
rename(${groupId},*,*)

Dependency mapper

DependencyMapper — transforms a dependency. Only reachable as the first argument of the mapping(...) dependency sink.

OperationResult
identity()dependency unchanged
scope(str)scope set to str
optional(bool)optional flag set
exclusion(str...)exclusions replaced with given ones; each is groupId:artifactId[:extension[:classifier]] (wildcards like *:* allowed)
compose(mapper...)applies mappers one after another (currently right to left, like the artifact mapper)

Example: compose(scope(compile), exclusion(*:*))

Artifact key factory

ArtifactKeyFactory — computes a key used to group artifacts (e.g. --keyFactorySpec of conflict-listing commands, default versionlessId()).

OperationKey
id()g:a:e[:c]:v
baseId()g:a:e[:c]:bV
versionlessId()g:a:e[:c]
ga()g:a

Artifact differentiator

ArtifactDifferentiator — computes a value that tells artifacts within the same key group apart; a group with more than one distinct value is a conflict (e.g. --artifactDifferentiatorSpec, default majorVersion()).

OperationValue
majorVersion()version up to first . (whole version if there is no dot)
minorVersion()version up to second . (whole version if there is none)
baseVersion()base version
version()version

Artifact source

Artifacts.Source — supplies a stream of artifacts (e.g. first parameter of gav-copy). Relative paths are resolved against the current base directory.

OperationSupplies
null()nothing
gav(str)a single artifact g:a[:e[:c]]:v (not resolved)
gavs(str)artifacts from a comma separated list of GAVs, or from a file containing one GAV per line
directory(str)all artifacts found in the given directory
localRepository(str)all artifacts installed in the local repository at given path
sessionLocalRepository()all artifacts installed in the session’s local repository
recorder()artifacts recorded during this session (see gav-copy-recorded)
concat(source...)concatenation of all sources
resolve(source)artifacts of source resolved (unresolvable ones are skipped with a warning)
resolveTransitive(source[, scope])each artifact of source resolved with its transitive dependencies, in given resolution scope (raw): none, compile, compile_plus_runtime, runtime (default), runtime_plus_system, test (case-insensitive; names with _ must be quoted)
matching(artifactMatcher, source)artifacts of source accepted by the artifact matcher
mapping(artifactMapper, source)artifacts of source transformed by the artifact mapper

Examples:

gav(org.slf4j:slf4j-api:2.0.13)
resolveTransitive(gavs(gavs.txt), 'runtime_plus_system')
matching(not(snapshot()), sessionLocalRepository())

Artifact sink

Artifacts.Sink — consumes artifacts (e.g. --sinkSpec, last parameter of gav-copy; default often null()). Relative paths are resolved against the current base directory. Sinks that modify something honor dry-run mode.

OperationDoes
null()discards everything
counting()counts artifacts
sizing()sums artifact file sizes
logging()prints each artifact
stat([[list,] details])prints statistics; stat() = stat(true,true), stat(x) = stat(true,x); details add module descriptor, checksums, origin URI and PURL info
artifactUri([bool])collects origin repository URIs of artifacts and prints them on close if bool (default true)
moduleDescriptor()extracts JPMS module descriptors
modules(file[, classifier]) (raw)writes a module=uri#SIZE=..&SHA-1=.. properties file for modular resolved JARs (optionally only of given classifier)
flat(dir[, nameMapper]) (raw dir)copies files into directory dir, named by the artifact name mapper (default AbVCE()); does not overwrite
repository(dir)copies files into directory dir using Maven repository layout (release artifacts only)
unpack(dir[, nameMapper]) (raw dir)unpacks archives into dir, each into a subdirectory named by the name mapper (default ACVE()); fixed(.) overlays all into dir
install([localRepoDir])installs into the session local repository, or into the local repository at given path
deploy(remoteRepo)deploys into given remote repository
purge(remoteRepo...)purges whole GAVs from the session local repository, considering given remote repositories
tee(sink...)passes artifacts to all sinks
nonClosing(sink)delegates but never closes sink
matching(artifactMatcher, sink)passes on only artifacts accepted by the artifact matcher
mapping(artifactMapper, sink)passes on artifacts transformed by the artifact mapper

Remote repositories are given as url, id::url or id::layout::url; as URLs contain : and /, they work unquoted, but quoting is safer.

Examples:

flat(target/libs)
flat(target/libs, compose(G(), fixed(/), AVE()))
tee(stat(), matching(withoutClassifier(), install(target/local-repo)))
deploy('myrepo::https://repo.example.com/releases/')

Dependency sink

Dependencies.Sink — consumes dependencies.

OperationDoes
null()discards everything
counting()counts dependencies
tee(sink...)passes dependencies to all sinks
nonClosing(sink)delegates but never closes sink
matching(dependencyMatcher, sink)passes on only dependencies accepted by the dependency matcher
mapping(dependencyMapper, sink)passes on dependencies transformed by the dependency mapper

Last modified November 8, 2026: Toolbox 0.16.2 (0e67adc)