Project type · application

Application

An [application] project compiles sources, runs tests, packages a JAR with an embedded classpath manifest, and optionally builds a Docker image or a GraalVM native binary.

Minimal configuration

Curie.toml
[application]
name    = "my-app"
version = "1.0.0"

mainClass is optional. Curie scans the compiled bytecode for a class with a public static void main(String[]) method and uses it automatically. Declare it explicitly when there is more than one candidate:

Curie.toml
[application]
name      = "my-app"
version   = "1.0.0"
mainClass = "com.example.Main"  # explicit override
groupId   = "com.example"       # required for curie publish

Build output

$ curie build
Building my-app v1.0.0
  Resolve deps    3 JAR(s)
  Compile         4 source file(s)
  Tests           ✔ 12 tests successful
  Package         my-app-1.0.0.jar
  Done            target/my-app-1.0.0.jar

The JAR includes a MANIFEST.MF with Main-Class and a Class-Path entry pointing to the dep JARs in target/libs/. Run it with:

$ curie run
Running  my-app v1.0.0
Hello from my-app.

Full configuration reference

Curie.toml — all application keys
[application]
name      = "my-app"
version   = "1.0.0"
mainClass = "com.example.Main"  # optional — auto-detected if omitted
groupId   = "com.example"       # required for curie publish

# Java version for javac --release (optional — omit to target the running JDK)
[java]
releaseVersion = "25"

# JUnit Platform Console Standalone version (workspace-inheritable)
[test]
junitPlatformVersion = "6.0.3"

# kotlinc + kotlin-stdlib (only needed when .kt sources are present)
[kotlin]
version = "2.1.21"

# Production dependencies
[dependencies]
"com.fasterxml.jackson.core:jackson-databind" = "2.17.2"
"com.google.guava:guava"                       = ""  # version from BOM

# Test-only dependencies
[test-dependencies]
"org.assertj:assertj-core" = "3.26.0"

# BOMs to import for version management
[bom-imports]
"com.google.guava:guava-bom" = "33.4.8-jre"

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

# Annotation processors run during compilation
[annotation-processors]
"org.projectlombok:lombok" = "1.18.32"

[test-annotation-processors]
"com.example:test-proc" = "1.0.0"

# Additional Maven repositories (Maven Central is always included)
[[repositories]]
id  = "my-nexus"
url = "https://nexus.example.com/repository/releases/"

# Docker image — enabled by this section or by a Dockerfile at project root
[docker]
baseImage = "eclipse-temurin:21-jre-alpine"  # default
imageName = "my-app"   # default: application.name
imageTag  = "latest"  # default: application.version

# GraalVM native-image compilation
[native-image]
outputName = "my-app"  # default: application.name
configDir  = "src/main/resources/META-INF/native-image"
extraArgs  = ["--no-fallback"]

# Build-info — git commit id embedded in the JAR (enabled by default)
[build-info]
enabled = false

# Publishing to a Maven repository
[publish]
repository  = "my-nexus"
sign        = true
description = "My application"
homepage    = "https://github.com/example/my-app"
licenses    = ["Apache-2.0"]
developers  = [{ id = "alice", name = "Alice", email = "alice@example.com" }]

Key fields

FieldRequiredDefaultNotes
nameYesUsed as the JAR base name and Docker image name
versionYesEmbedded in JAR name and MANIFEST.MF
mainClassNoAuto-detectedMust be set explicitly when multiple main classes exist
groupIdNoRequired for curie publish and SBOM metadata.component

mainClass auto-detection

When mainClass is omitted, Curie scans compiled .class files for a public static void main(String[]) method. If exactly one is found, it is used. If zero or more than one are found, the build fails with a message listing the candidates — set mainClass explicitly to resolve the ambiguity.

Java 21+ "instance main methods" (a class with a void main() instance method, no static, no String[]) are also detected. See examples/simplified-main.

Source layouts

Curie supports two layouts, and they can coexist in the same project:

Test files (*Test.java, *Tests.java, *Spec.java) co-located in the source tree are treated as tests; a separate tests/ or src/test/java/ directory is optional for integration tests.

build-info

When the project is inside a git repository, Curie automatically embeds META-INF/build-info.properties in the JAR:

META-INF/build-info.properties
git.commit.id=a3f1b2c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0

If there are uncommitted changes the value is suffixed with -dirty. Set [build-info] enabled = false to opt out.