Path replacements
Bleep substitutes a small set of named placeholders in bleep.yaml
whenever a field can hold a path. They look like ${BUILD_DIR},
${PROJECT_DIR}, ${SCALA_VERSION} — you may have run into them in
a build that originated as an sbt or Maven import.
This page exists because the mechanism is real, you'll see it after imports, and it shows up in places like compiler options. But the headline is short:
For everything you write by hand, prefer plain relative paths. Placeholders are an import-time portability mechanism. The handful of cases where they're genuinely useful are listed at the bottom of this page.
Why the mechanism exists
bleep import (from sbt) and bleep import-maven work by reading what
those tools produce, then converting it into bleep's model. Both formats
embed absolute paths everywhere — bloop's JSON contains
/Users/somebody/projects/myrepo/foo/src/main/scala, full stop. If bleep
wrote those values straight into bleep.yaml, the build would only work on
that machine.
So during import, bleep walks every path-like value and runs the reverse
substitution: anything that matches the build root becomes ${BUILD_DIR},
anything that matches the project's folder becomes ${PROJECT_DIR}, the
Scala version embedded in folder names becomes ${SCALA_VERSION}, and so
on. The result is a bleep.yaml that works on any machine that has the
build.
Once the file is written, bleep does the forward substitution every time it reads the build — so the rest of the codebase always sees real paths, not placeholders.
The full list
| Placeholder | Expands to |
|---|---|
${BUILD_DIR} | The folder containing bleep.yaml. |
${PROJECT_DIR} | The project's folder (default ${BUILD_DIR}/<project-name>). |
${TARGET_DIR} | The bleep compile-output folder for this project. |
${HOME_DIR} | The user's home directory ($HOME). |
${TEMP_DIR} | The system temp directory. |
${COURSIER_CACHE_DIR} | The coursier dependency cache. |
${COURSIER_ARC_CACHE_DIR} | The coursier archive cache. |
${BLEEP_VERSION} | The bleep version this build is using. |
${SCALA_VERSION} | Full Scala version, e.g. 3.8.3. |
${SCALA_BIN_VERSION} | Scala binary version, e.g. 3 or 2.13. |
${SCALA_EPOCH} | The Scala epoch, e.g. 3 or 2. |
${PLATFORM} | jvm, js, or native. |
${PLATFORM_VERSION} | Scala.js or Scala Native version, when applicable. |
${SCOPE} | sbt scope from imports (main, test, …). Legacy. |
Where they apply
Replacements run on string values across the build model wherever a path,
URI, dependency version, or compiler option is parsed. In practice that
covers sources, resources, folder, compiler options
(scala.options, java.compilerOptions), dependency coordinates,
resolvers URIs, and the path wiring inside scripts and sourcegen.
The recommendation, again, in writing
If you're authoring or editing a bleep.yaml by hand, prefer plain
relative paths. They read better and they don't require the next person
on the team to know what ${BUILD_DIR} resolves to.
Don't write:
projects:
myapp:
resources: ${BUILD_DIR}/shared/resources
Write:
projects:
myapp:
resources: ../shared/resources
sources and resources are resolved relative to the project's folder
(see Bleep build model), so .. walks up to the build root
and ../shared/resources reads naturally.
The placeholders aren't wrong — bleep happily round-trips either
form — but plain paths read better in code review, work the same
under bleep build normalize, and don't depend on anyone remembering the
placeholder vocabulary.
When the placeholders earn their keep
Three real cases.
Versioned source layouts in cross-builds
src/main/scala-2.13/ versus src/main/scala-3/ only makes sense when
the Scala version is the variable:
projects:
mylib:
sources: src/main/scala-${SCALA_BIN_VERSION}
Bleep recognises the expanded form on read and rewrites the literal back to the placeholder on write — so this works the same across every cross axis.
Reaching into the user's home
When a project depends on something you keep outside the repo:
resolvers:
- file://${HOME_DIR}/.m2/repository
A relative path can't express that — the build root has no
relationship to $HOME.
Targeting bleep's own output
Tooling that consumes the compiled classes (a packaging script, a
performance harness) can refer to ${TARGET_DIR} rather than hard-coding
bleep's internal layout, which is not stable API.
Don't reach for it for
- Cross-project source/resource sharing — use
../shared/…. - The current project's own folder — use a plain relative path.
- Anything that would still resolve correctly without the placeholder.
The build is plain text. Plain text reads better.