Is your feature request related to a problem? Please describe.
I'm migrating off IntelliJ's Scala worksheets (.sc) and there's no native scala-cli equivalent for what made them useful. In a real project, a worksheet can execute scratch code against an existing build module's full classpath. That means the module's compiled classes plus every resolved dependency, including private artifacts from authenticated repositories, while staying completely outside the build's compiled sources. That isolation is the key property. A broken or outdated worksheet never breaks compile or CI, so nobody is forced to fix throwaway debug code.
To reproduce this with scala-cli today I have to manually export the classpath from the build tool and wire it up myself:
CP=$(sbt -batch -error "export myModule/Runtime/fullClasspath" | tail -1)
scala-cli run scratch.sc --scala 2.13.18 --classpath "$CP"
This works, but it requires a wrapper script, manual caching of the exported classpath, pinning the Scala version to match the module, and there's a stale-classes caveat (you have to remember to recompile the project for the script to see code changes). It's enough friction that it doesn't feel like a first-class worksheet replacement.
Describe the solution you'd like
A native way to point a scala-cli script at an existing build module and inherit its classpath automatically, ideally over BSP so it works across sbt, mill, and others. Something like:
scala-cli run scratch.sc --bsp-module domain
# or
scala-cli run scratch.sc --sbt-project http --module-classpath runtime
scala-cli would discover the module via the existing BSP connection, use its already-resolved dependency classpath (private repos included, so resolution stays the build tool's job) and its compiled output, compile the script standalone against that, and run it. The script itself would stay outside the build's source set, which preserves the worksheet-style isolation. As a bonus, it could trigger a recompile of the module first (so the script always sees current code) and match the module's Scala version automatically.
Describe alternatives you've considered
- Manual
--classpath from sbt export (my current approach): functional, but needs a wrapper, classpath caching, version pinning, and has the stale-classes gotcha.
- Promoting scratch files into a compiled build module (for example an
object Main run via sbt runMain): this loses the whole point, because the build and CI now compile them, so a stale debug script breaks everyone's build.
sbt console or Ammonite: REPL-oriented, not file-based, version-controllable, or easily repeatable. Ammonite also has to re-resolve the build's private dependencies itself, which is the painful part.
- Staying on IntelliJ worksheets: ties the workflow to one IDE, which is exactly what I'm trying to avoid.
Additional context
The dependencies in these projects come from an authenticated, private artifact registry that the build tool is already configured to resolve. Re-declaring or re-resolving them in scala-cli (via //> using dep and //> using repository plus credentials) is the most painful part, so the goal is specifically to reuse the build's existing resolution rather than duplicate it. BSP seems like the natural mechanism, since scala-cli already speaks it, and IDE worksheets effectively rely on the same build-server information today.
Is your feature request related to a problem? Please describe.
I'm migrating off IntelliJ's Scala worksheets (
.sc) and there's no native scala-cli equivalent for what made them useful. In a real project, a worksheet can execute scratch code against an existing build module's full classpath. That means the module's compiled classes plus every resolved dependency, including private artifacts from authenticated repositories, while staying completely outside the build's compiled sources. That isolation is the key property. A broken or outdated worksheet never breakscompileor CI, so nobody is forced to fix throwaway debug code.To reproduce this with scala-cli today I have to manually export the classpath from the build tool and wire it up myself:
This works, but it requires a wrapper script, manual caching of the exported classpath, pinning the Scala version to match the module, and there's a stale-classes caveat (you have to remember to recompile the project for the script to see code changes). It's enough friction that it doesn't feel like a first-class worksheet replacement.
Describe the solution you'd like
A native way to point a scala-cli script at an existing build module and inherit its classpath automatically, ideally over BSP so it works across sbt, mill, and others. Something like:
scala-cli run scratch.sc --bsp-module domain # or scala-cli run scratch.sc --sbt-project http --module-classpath runtimescala-cli would discover the module via the existing BSP connection, use its already-resolved dependency classpath (private repos included, so resolution stays the build tool's job) and its compiled output, compile the script standalone against that, and run it. The script itself would stay outside the build's source set, which preserves the worksheet-style isolation. As a bonus, it could trigger a recompile of the module first (so the script always sees current code) and match the module's Scala version automatically.
Describe alternatives you've considered
--classpathfromsbt export(my current approach): functional, but needs a wrapper, classpath caching, version pinning, and has the stale-classes gotcha.object Mainrun viasbt runMain): this loses the whole point, because the build and CI now compile them, so a stale debug script breaks everyone's build.sbt consoleor Ammonite: REPL-oriented, not file-based, version-controllable, or easily repeatable. Ammonite also has to re-resolve the build's private dependencies itself, which is the painful part.Additional context
The dependencies in these projects come from an authenticated, private artifact registry that the build tool is already configured to resolve. Re-declaring or re-resolving them in scala-cli (via
//> using depand//> using repositoryplus credentials) is the most painful part, so the goal is specifically to reuse the build's existing resolution rather than duplicate it. BSP seems like the natural mechanism, since scala-cli already speaks it, and IDE worksheets effectively rely on the same build-server information today.