Workspaces
Curie inherits Cargo's workspace model. One root Curie.toml lists members; each member is a self-contained project; the root inherits shared config down to every member.
Layout
monorepo/ ├── Curie.toml # workspace root — no [application] / [library] ├── app/ │ ├── Curie.toml # declares [application] │ └── src/... ├── core/ │ ├── Curie.toml # declares [library] │ └── src/... └── utils/ ├── Curie.toml # declares [library] └── src/...
Root configuration
The root Curie.toml declares members and any config that should be inherited:
[workspace] members = ["app", "core", "utils"] [java] sourceCompatibility = "21" [bom-imports] "com.fasterxml.jackson:jackson-bom" = "2.17.2" [test-bom-imports] "org.junit:junit-bom" = "5.11.0"
Inheritance rules
[java]— applies to every member that does not declare its own.[bom-imports]/[test-bom-imports]— merged with each member's own imports. Member entries take precedence on a name collision.[repositories]— also inherited; member entries appended.
Members declare dependencies with empty version strings ("") to defer to the inherited BOMs:
[application] name = "app" version = "0.1.0" mainClass = "com.example.App" [dependencies] # resolved from the workspace's jackson-bom "com.fasterxml.jackson.core:jackson-databind" = "" [workspace-dependencies] core = { path = "../core" } utils = { path = "../utils" }
Topo-sorted builds
Run curie build from the workspace root and Curie computes a topological order over [workspace-dependencies], then builds each member in dependency order. Upstream target/classes directories — not just their JARs — are placed on downstream compile classpaths, so downstream tests don't have to wait for upstream JAR packaging to complete.
Workspace . build (3 members) [1/3] utils Compile 3 source file(s) Tests ✔ 8 tests successful [2/3] core Compile 5 source file(s) Tests ✔ 12 tests successful [3/3] app Resolve deps 7 JAR(s) Compile 4 source file(s) Tests ✔ 7 tests successful Done target/app-0.1.0.jar
Targeted builds
Run curie build from a member directory and Curie still respects topology — it builds the member plus its transitive workspace dependencies, but skips siblings the target doesn't depend on. This is the everyday loop in a large monorepo: edit one package, build only what's affected.
List members
curie list from the root prints the member roster and their declared roles (application vs library):
Workspace . (3 members)
app application v0.1.0
core library v0.1.0
utils library v0.1.0
Parallel formatting
curie fmt at the workspace root fans out across every member in parallel. palantir-java-format is resolved once, then the JAR list is shared across the worker threads so there's no contention on the local cache.