Build & test · dependencies

Adding dependencies

Dependencies are declared in Curie.toml. Add them by editing the file directly, or use curie add to let Curie resolve the latest version and write the entry for you.

Editing Curie.toml by hand

Each entry is "group:artifact" = "version". Production dependencies go under [dependencies]; test-only dependencies go under [test-dependencies]:

Curie.toml
[dependencies]
"com.fasterxml.jackson.core:jackson-databind" = "2.17.2"
"com.google.guava:guava"                     = "33.4.8-jre"

[test-dependencies]
"org.junit.jupiter:junit-jupiter" = "6.0.3"
"org.assertj:assertj-core"        = "3.26.0"

An empty version ("") means the version comes from a BOM — see BOM imports below. If no BOM provides the version, the build fails immediately with an error.

Excluding transitive dependencies

Some dependencies pull in transitive dependencies you don't need. Use the detailed form with an exclusions list to prevent specific artifacts from appearing on the classpath:

Curie.toml
[dependencies]
# commons-codec is only needed by commons-compress's lz4/snappy compressors
"org.apache.commons:commons-compress" = { version = "1.27.1", exclusions = [
    "commons-codec:*",
] }

Each exclusion is a "group:artifact" string. Exclusions are transitive: if A depends on B which depends on C, excluding C on A will prevent C from appearing anywhere in the resolved tree below A.

Use "*:*" to exclude all transitive dependencies of an artifact (keeping only the artifact itself):

Curie.toml
"com.example:fat-lib" = { version = "1.0", exclusions = ["*:*"] }

Curie also honours <exclusions> declared in upstream POM files. If a library's own POM excludes a transitive dependency, Curie respects that exclusion automatically — matching Maven's behaviour.

Major-version conflicts

Curie resolves version conflicts with Maven's nearest-wins rule: when two paths in the dependency graph need different versions of the same group:artifact, the one declared closest to your project wins. That is usually what you want — but a major-version difference is dangerous: keeping 2.x when a transitive dependency was compiled against 5.x can fail at runtime with NoSuchMethodError or NoClassDefFoundError.

So when a discarded candidate's major version differs from the version Curie keeps, the build fails with an explanation:

curie build
dependency version conflict (major-version mismatch)

  com.google.guava:guava — keeping 33.0-jre, but org.example:lib:1.2 requires 25.1-jre

A major-version difference can cause runtime errors (missing classes/methods).
Fix the version, exclude the transitive dependency, or — if intentional —
allow it in Curie.toml:
  "com.google.guava:guava" = { version = "33.0-jre", allowVersionConflict = true }

You have three ways to resolve it:

Curie.toml
[dependencies]
"com.google.guava:guava" = { version = "33.0-jre", allowVersionConflict = true }

allowVersionConflict only silences the error for that one coordinate; resolution is unchanged (nearest-wins still keeps your version). Minor and patch differences never trigger this check — they are resolved silently, matching Maven. The same rule applies to [test-dependencies].

curie add

curie add queries Maven Central for the artifact, picks the latest version, and writes the entry into Curie.toml:

$ curie add com.google.guava:guava
Resolving latest: com.google.guava:guava
  Added  com.google.guava:guava = "33.4.8-jre"  →  [dependencies]

Pin to a specific version with @version:

$ curie add com.google.guava:guava@33.2.1-jre
  Added  com.google.guava:guava = "33.2.1-jre"  →  [dependencies]

Fat JAR shading (shadeAll, shade, relocations)

When a project has a [fat-jar] section, Curie can produce a self-contained -fat.jar. The global default for whether dependencies are bundled is controlled by shadeAll:

Curie.toml
[fat-jar]
enabled = true
shadeAll = true   # default: bundle (shade) deps unless overridden

[[fat-jar.relocations]]
from = "com.google.common"
to   = "com.example.shaded.com.google.common"

Per-dependency control:

Curie.toml
[dependencies]
"com.google.guava:guava" = { version = "33.2", relocations = [
  { from = "com.google.common", to = "com.example.shaded.com.google.common" }
] }
"org.slf4j:slf4j-api" = { version = "2.0", shade = false }

curie add flags

FlagEffect
--testAdd to [test-dependencies] instead of [dependencies]
--bomAdd to [bom-imports]; subsequent BOM-managed deps can omit the version
--test-bomAdd to [test-bom-imports]
--annotation-processorAdd to [annotation-processors]
examples
# test dependency
curie add --test org.assertj:assertj-core@3.26.0

# add a BOM, then a BOM-managed dep (version will be "")
curie add --bom com.fasterxml.jackson:jackson-bom@2.17.2
curie add com.fasterxml.jackson.core:jackson-databind

# annotation processor
curie add --annotation-processor org.projectlombok:lombok@1.18.32

curie remove

Remove an entry from whichever section it appears in:

$ curie remove com.google.guava:guava
  Removed  com.google.guava:guava  from [dependencies]

BOM imports

A BOM (bill of materials) is a POM-packaged artifact whose <dependencyManagement> section pins versions for a family of related artifacts. Declare BOMs under [bom-imports]; all entries are applied in order (later wins on collision):

Curie.toml
[bom-imports]
"com.fasterxml.jackson:jackson-bom" = "2.17.2"

[dependencies]
# empty version → resolved from the BOM above
"com.fasterxml.jackson.core:jackson-databind"   = ""
"com.fasterxml.jackson.core:jackson-annotations" = ""

Use [test-bom-imports] for BOMs that only apply to test-scope dependencies:

Curie.toml
[test-bom-imports]
"org.junit:junit-bom" = "5.11.0"

[test-dependencies]
"org.junit.jupiter:junit-jupiter" = ""

BOM imports can also be inherited from a workspace root — see Workspaces.

For how Curie resolves transitive dependencies, applies nearest-wins conflict resolution, verifies checksums, and handles offline mode, see Resolver & checksums.