Resolver & checksums
Curie talks to Maven Central directly. No POM you wrote, no plugin ceremony — just group:artifact = "version" in Curie.toml and a transitive closure resolved against the same ~/.m2/repository Maven uses.
Declaring dependencies
[dependencies] "com.fasterxml.jackson.core:jackson-databind" = "2.17.2" "com.google.guava:guava" = "33.2.0-jre" [test-dependencies] "org.junit.jupiter:junit-jupiter" = "5.11.0"
Each entry is "group:artifact" = "version". An empty version ("") means the version comes from a BOM — see below.
BOM imports
A BOM (bill of materials) is a POM-packaged artifact whose <dependencyManagement> section pins versions for a family of related artifacts. List them under [bom-imports] in priority order (later wins on collision):
[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" = ""
If you declare a dependency with "" and no BOM provides it, the build fails up front — there's no silent fallback to "latest".
Transitive resolution
Curie does a breadth-first walk of every dependency's POM, applying Maven's conflict-resolution rules:
- Nearest wins — when the same
group:artifactappears at two depths, the shallower occurrence's version is used. - First declared wins at equal depth.
- Top-level BOM beats transitive explicit — your
[bom-imports]overrides any version a transitive POM hard-codes.
POMs are fetched serially in phase 1 (small, fast). JARs are then downloaded in parallel in phase 2 — up to eight concurrent workers — and arrive in the local cache in a stable, topologically ordered classpath.
Checksum verification
Every artifact Curie downloads is verified against its .sha256 sidecar from the same repository. The sidecar hash is then persisted next to the artifact in ~/.m2/repository/...artifact.jar.sha256, mirroring Maven Central's published layout. On the next build the cached hash is compared against the cached JAR — zero network calls, zero implicit trust.
A missing sidecar is a hard error. Every well-formed Maven repository publishes one — Maven's deploy plugin generates them, and Nexus / Artifactory generate them server-side on upload. A missing sidecar usually means a misconfigured proxy or a manually-uploaded artifact, and either way Curie refuses to install an unverifiable JAR.
Fallback to SHA-1
If a repository only publishes .sha1 sidecars (older mirrors, some private repos), Curie falls back to that. SHA-1 is cryptographically weak for authentication but still catches accidental corruption and unsophisticated substitution — adequate for the integrity-check use case.
Tamper detection
Edit a JAR in ~/.m2/repository by hand and the next build will fail with a checksum mismatch error citing the artifact and both digests. The local cache is now tamper-evident.
Offline mode
Pass --offline to forbid network calls entirely. Any cache miss is an immediate error. Useful for sealed CI environments, reproducibility checks, and incident-response builds where you want to be sure nothing on disk has changed since the last good build.
Building greeter v0.1.0 Compile up to date Tests up to date Package up to date Done target/greeter-0.1.0.jar
Extra repositories
By default the resolver hits Maven Central. Add private mirrors or company-internal Nexus instances with [repositories]:
[repositories] internal = "https://nexus.internal.example.com/repository/maven-public/"
Repositories are tried in order — Central first, then each [repositories] entry in declaration order — until an artifact resolves.