Skip to main content

Release notes

v1.2.0

Scala 3.3.3, 3.4.0, 2.13.13 & 2.12.19 support

This version of Scala CLI adds support for a whooping 4 new Scala versions, it's been busy these past few days! The default version used when using the CLI will from now on be the Scala 3 Next version (3.4.0 as of this release). Using the lts tag will now point to Scala 3.3.3. The LTS is also the version used for building the internals of Scala CLI (although we now also cross-compile with 3.4.0).

scala-cli version
# Scala CLI version: 1.2.0
# Scala version (default): 3.4.0

Added by @Gedochao in #2772, #2736, #2755, #2753 and #2752

Given the following importMap.json file:

{
"imports": {
"@stdlib/linspace": "https://cdn.skypack.dev/@stdlib/linspace"
}
}

It is now possible to remap the imports at link time with the jsEsModuleImportMap directive.

//> using jsEsModuleImportMap importMap.json
//> using jsModuleKind es
//> using jsMode fastLinkJS
//> using platform js

import scala.scalajs.js
import scala.scalajs.js.annotation.JSImport
import scala.scalajs.js.typedarray.Float64Array

object Foo {
def main(args: Array[String]): Unit = {
println(Array(-10.0, 10.0, 10).mkString(", "))
println(linspace(0, 10, 10).mkString(", "))
}
}

@js.native
@JSImport("@stdlib/linspace", JSImport.Default)
object linspace extends js.Object {
def apply(start: Double, stop: Double, num: Int): Float64Array = js.native
}

The same can be achieved with the --js-es-module-import-map command line option.

scala-cli --power package RemappingEsModuleImports.scala --js --js-module-kind ESModule -o main.js --js-es-module-import-map importMap.json

Added by @Quafadas in #2737 and scala-js-cli#47

Fixes

  • Updated method for choosing a free drive letter (fixes #2743) by @philwalk in #2749
  • Make sure tasty-lib doesn't warn about Scala 3 Next by @Gedochao in #2775

Enhancements

  • Add the ability to remap EsModule imports at link time by @Quafadas in #2737

Internal changes

  • Fix overeager Scala version docs tests by @Gedochao in #2750
  • Lock script wrapper tests on the internally used Scala 2.13 version by @Gedochao in #2754
  • Use Scala LTS as the default version while cross compiling all Scala 3 modules on both LTS & Next by @Gedochao in #2752
  • Explicitly set sonatype publishing to use the default cross Scala version by @Gedochao in #2757
  • Fix publishing of artifacts to include non-cross-compiled modules by @Gedochao in #2759
  • Run integration tests with both Scala 3 LTS & Next versions by @Gedochao in #2760

Documentation changes

Updates and maintenance

New Contributors

Full Changelog: https://github.com/VirtusLab/scala-cli/compare/v1.1.3...v1.2.0

v1.1.3

Support for LTS Scala version aliases

It is now possible to use lts and 3.lts as Scala version aliases in Scala CLI. They refer to the latest LTS version of Scala (the 3.3.x line at the time of this release).

scala-cli run -S lts --with-compiler -e 'println(dotty.tools.dotc.config.Properties.simpleVersionString)'
# Compiling project (Scala 3.3.1, JVM (17))
# Compiled project (Scala 3.3.1, JVM (17))
# 3.3.1

Using the 2.lts, 2.13.lts & 2.12.lts aliases returns a meaningful error, too.

scala-cli run -S 2.lts -e 'println(scala.util.Properties.versionString)'                                 
# [error] Invalid Scala version: 2.lts. There is no official LTS version for Scala 2.
# You can only choose one of the 3.x, 2.13.x, and 2.12.x. versions.
# The latest supported stable versions are 2.12.18, 2.13.12, 3.3.1.
# In addition, you can request compilation with the last nightly versions of Scala,
# by passing the 2.nightly, 2.12.nightly, 2.13.nightly, or 3.nightly arguments.
# Specific Scala 2 or Scala 3 nightly versions are also accepted.
# You can also request the latest Scala 3 LTS by passing lts or 3.lts.

Added by @kasiaMarek in #2710

--semanticdb-targetroot and --semanticdb-sourceroot options

It is now possible to set the SemanticDB target root and source root directories with unified syntax, independent of the target Scala and/or Java versions.

For a given semanticdb-example.sc script:

println("SemanticDB targetroot gets set to ./targetRootDir, while sourceroot gets set to the current working directory.")

You now can specify the targetroot and sourceroot directories like this:

scala-cli compile src/semanticdb-example.sc --semanticdb-targetroot ./targetRootDir --semanticdb-sourceroot .

Added by @Gedochao in #2692

Fixes

Documentation changes

Updates and maintenance

New Contributors

Full Changelog: https://github.com/VirtusLab/scala-cli/compare/v1.1.2...v1.1.3

v1.1.2

Support for Scala.js 1.15.0

This version adds Scala CLI support for Scala.js 1.15.0. Added by @scala-steward in #2672 & @Gedochao in scala-js-cli#43.

Fixes

  • Fix repeatable compiler options handling from the command line by @Gedochao in #2666
  • Fix script wrapper tests & script object wrapper using directive by @Gedochao in #2668
  • Prevent consecutive -language:* options from being ignored by @Gedochao in #2667

Documentation changes

Build and internal changes

  • Update release procedure steps for v1.1.x by @Gedochao in #2665
  • Tag GitHubTests.create secret as flaky on all Mac tests (including M1) by @Gedochao in #2677

Updates and maintenance

Full Changelog: https://github.com/VirtusLab/scala-cli/compare/v1.1.1...v1.1.2

v1.1.1

Deprecate Scala Toolkit latest version in favour of default

Using toolkits with the latest version is now deprecated and will cause a warning. It will likely be removed completely in a future release.

scala-cli --toolkit latest -e 'println(os.pwd)'
# Using 'latest' for toolkit is deprecated, use 'default' to get more stable behaviour:
# --toolkit default
# Compiling project (Scala 3.3.1, JVM (17))
# Compiled project (Scala 3.3.1, JVM (17))
# /home

It is now advised to either use an explicit toolkit version or rely on the new default alias.

scala-cli --toolkit default -e 'println(os.pwd)'
# Compiling project (Scala 3.3.1, JVM (17))
# Compiled project (Scala 3.3.1, JVM (17))
# /home

The default version for toolkits is tied to a particular Scala CLI version. You can check which version is used by referring to Scala CLI help.

scala-cli version                 
# Scala CLI version: 1.1.1
# Scala version (default): 3.3.1
scala-cli run -h|grep toolkit
# --toolkit, --with-toolkit version|default Add toolkit to classPath (not supported in Scala 2.12), 'default' version for Scala toolkit: 0.2.1, 'default' version for typelevel toolkit: 0.1.20

Added by @MaciejG604 in #2622

Enhancements

Fixes

  • Fallback to UTF-8 in setup-ide by @JD557 in #2599
  • Separate Scala REPL classpath from user dependencies by @Gedochao in #2607
  • Prevent resource directories from breaking sources hash by @Gedochao in #2654
  • Fix special handling for the -Xplugin-list compiler option by @Gedochao in #2635
  • Remove superfluous traits by @MaciejG604 in #2618
  • Prevent the toolkit latest deprecation warning from being logged more than once by @Gedochao in #2657

Documentation changes

Build and internal changes

Updates and maintenance

New Contributors

Full Changelog: https://github.com/VirtusLab/scala-cli/compare/v1.1.0...v1.1.1

v1.1.0

Breaking update to Scala 2 scripts

Keep in mind that it ONLY applies to Scala 2! Scala 3 script wrappers are not affected!

Scala CLI now uses a different kind of script wrappers for Scala 2 by default, which support running background threads. This has been introduces as an answer to the issue #2470, where a running a script in Scala 2 would end up in a deadlock due to background threads being run. Also the change makes the Scala 2 scripts run significantly faster, as the code can be optimized due to not residing in the object's initialization clause.

However, the new solution brings some incompatibilities with the old behaviour:

  • main classes are now named the same as the file they are defined in, they do not have the '_sc' suffix anymore, so any calls like:
scala-cli foo.sc bar.sc --main-class foo_sc

should be replaced with

scala-cli foo.sc bar.sc --main-class foo
  • it is impossible to access the contents of a script named main.sc from another source, any references to the script object main will result in a compilation error. E.g. Accessing the contents of main.sc using the following code:
println(main.somethingDefinedInMainScript)

Will result in the following compilation error:

[error] ./foo.sc:2:11
[error] missing argument list for method main in trait App
[error] Unapplied methods are only converted to functions when a function type is expected.
[error] You can make this conversion explicit by writing `main _` or `main(_)` instead of `main`.

When main.sc is passed as argument together with other scripts, a warning will be displayed:

[warn]  Script file named 'main.sc' detected, keep in mind that accessing it from other scripts is impossible due to a clash of `main` symbols

Added by @MaciejG604 in #2556

"Drive relative" paths on Windows

Scala CLI now correctly recognizes "drive relative" paths on Windows, so paths like /foo/bar will be treated as relative from the root of the current drive - e.g. C:\foo\bar. This allows for compatibility of programs referencing paths with e.g. //> using file /foo/bar with Windows.

Added by @philwalk in #2516

UX improvements

Enhancements

  • Default to publish repository configured for local machine when inferring publish.ci.repository by @MaciejG604 in #2571
  • Skip validation for default Scala versions, add build test by @MaciejG604 in #2576

Fixes

Documentation changes

Build and internal changes

Updates and maintenance

New Contributors

Full Changelog: https://github.com/VirtusLab/scala-cli/compare/v1.0.6...v1.1.0

v1.0.6

Scala CLI won't default to the system JVM if it's not supported anymore

If your JAVA_HOME environment variable has been pointing to a JVM that is no longer supported by Scala CLI (so anything below 17, really), you may have run into an error like this one with Scala CLI v1.0.5:

scala-cli --power bloop exit 
# Stopped Bloop server.
export JAVA_HOME=$(cs java-home --jvm zulu:8)
scala-cli -e 'println(System.getProperty("java.version"))'
# Starting compilation server
# Error: bloop.rifle.FailedToStartServerExitCodeException: Server failed with exit code 1
# For more details, please see '/var/folders/5n/_ggj7kk93czdt_n0jzrk8s780000gn/T/1343202731019130640/.scala-build/stacktraces/1699527280-9858975811713766588.log'
# Running
# scala-cli --power bloop output
# might give more details.

This is because we no longer support JVM <17 with Scala CLI v1.0.5, but we still have been defaulting to whatever JVM was defined in JAVA_HOME. As a result, Bloop has been failing to start when running with, say, JAVA_HOME pointing to Java 8.

This is no longer the case. Scala CLI will now automatically download Java 17 for Bloop in such a situation (and still use the JVM from JAVA_HOME for running the code, while Bloop runs on 17).

scala-cli --power bloop exit 
# Stopped Bloop server.
export JAVA_HOME=$(cs java-home --jvm zulu:8)
scala-cli -e 'println(System.getProperty("java.version"))'
# Starting compilation server
# Compiling project (Scala 3.3.1, JVM (8))
# Compiled project (Scala 3.3.1, JVM (8))
# 1.8.0_392

Added by @tgodzik in #2508.

Other changes

Fixes

  • Fix --watch failing on invalid PathWatchers.Event & skip wonky tests on Mac CI by @Gedochao in #2515
  • bugfix: Don't try to always get system jvm first by @tgodzik in #2508

Documentation changes

Build and internal changes

Updates and maintenance

New Contributors

Full Changelog: https://github.com/VirtusLab/scala-cli/compare/v1.0.5...v1.0.6

v1.0.5

What's new

Accept --power from anywhere

The --power flag used to be a launcher option, which means it used to only be accepted when passed before the sub-command name. Now, it can be passed anywhere in the command line.

scala-cli --power package --help
scala-cli package --power --help
scala-cli package --help --power

Added by @MaciejG604 in #2399

Offline mode (experimental)

It is now possible to run Scala CLI in offline mode for the cases when you don't want the runner to make any network requests for whatever reason. This changes Coursier's cache policy to LocalOnly, preventing it from downloading anything.

scala-cli compile . --offline --power

Of course, this means that you will have to have all the dependencies relevant to your build already downloaded and available in your local cache. Reasonable fallbacks will be used where possible, e.g. the Scala compiler may be used instead of Bloop if Bloop isn't available.

Added by @MaciejG604 in #2404

Scala CLI's install script is now available behind a conveniently shorter web address: https://scala-cli.virtuslab.org/get

Added by @Gedochao in #2450

The fix sub-command (experimental)

The fix sub-command is a new addition to Scala CLI. It allows to scan your project for using directives and extract them into the project.scala file placed in the project root directory. This allows to easily fix warnings tied to having using directives present in multiple files.

scala-cli fix . --power

Added by @MaciejG604 in #2309

Build static & shared libraries with Scala Native (experimental)

You can now use the --native-target option to build Scala Native projects as static or shared libraries.

scala-cli package . --power --native-target static
scala-cli package . --power --native-target dynamic

Added by @keynmol in #2196

Platform version is now always logged during compilation.

scala-cli compile .
# Compiling project (Scala 3.3.1, JVM (17))
# Compiled project (Scala 3.3.1, JVM (17))
scala-cli compile . --js
# Compiling project (Scala 3.3.1, Scala.js 1.13.2)
# Compiled project (Scala 3.3.1, Scala.js 1.13.2)
scala-cli compile . --native
# Compiling project (Scala 3.3.1, Scala Native 0.4.16)
# Compiled project (Scala 3.3.1, Scala Native 0.4.16)

Added by @Gedochao in #2465

Other changes

Enhancements

Fixes

Documentation changes

Build and internal changes

  • Add test for actionable diagnostics from compiler by @MaciejG604 in #2327
  • Pin the versions of Github CI runners by @MaciejG604 in #2370
  • Remove bloop timeouts in tests by @MaciejG604 in #2407
  • Add post-update hook for reference doc generation by @MaciejG604 in #2406
  • Add tests which check availability of scalafmt native launcher for de… by @lwronski in #2418
  • Default to a Scala version for REPL if there are no Scala artifacts. by @trilleplay in #2431
  • Remove unused snippet checker by @lwronski in #2423
  • Allow to override internal & user default Scala versions for mill builds by @Gedochao in #2461
  • NIT: Refactor: Rely on global --power option where able in cli commands by @Gedochao in #2480

Updates and maintenance

New Contributors

Full Changelog: https://github.com/VirtusLab/scala-cli/compare/v1.0.4...v1.0.5

v1.0.4

Hotfix for buildTarget/jvmRunEnvironment in BSP

We've addressed a bug that surfaced when opening your ScalaCLI projects in Metals or IntelliJ. If you encountered the following log:

2023.08.09 15:48:34 INFO  BSP server: Caused by: java.lang.IllegalArgumentException: Type ch.epfl.scala.bsp4j.JvmMainClass is instantiated reflectively but was never registered. Register the type by adding "unsafeAllocated" for the type in reflect-config.json.
2023.08.09 15:48:34 INFO BSP server: at com.oracle.svm.core.graal.snippets.SubstrateAllocationSnippets.instanceHubErrorStub(SubstrateAllocationSnippets.java:309)
2023.08.09 15:48:34 INFO BSP server: at [email protected]/sun.misc.Unsafe.allocateInstance(Unsafe.java:864)
2023.08.09 15:48:34 INFO BSP server: ... 36 more

those logs should no longer appear.

Thanks to @lwronski for providing the fix in #2342.

v1.0.3

What's new

Access project configuration with the new BuildInfo

BuildInfo access your project's build configuration within your Scala code. This feature automatically gathers and generates build information about your project, making project details instantly accessible at runtime.

To generate BuildInfo, either use the --build-info command line option or include the //> using buildInfo directive in your code.

Upon activation, a BuildInfo object becomes accessible on your project's classpath. To use it, simply add the following import into your code:

import scala.cli.build.BuildInfo

This BuildInfo object encapsulates information such as the Scala version used, target platform, main class, scalac options, dependencies, and much more for both Main and Test scopes. The generation ensures up-to-date configuration data from both the console options and using directives in your project's sources.

Added by @MaciejG604 in #2249.

CompileOnly Dependencies

Now, users can declare dependencies that are exclusively included at the compile time. These dependencies are added to the classpath during compilation, but won't be included when the application is run, keeping your runtime environment lightweight.

To declare such a dependency:

  1. Via the using directive:
//> using compileOnly.dep "com.github.plokhotnyuk.jsoniter-scala::jsoniter-scala-macros:2.23.2"
  1. Via the command line:
scala-cli Hello.scala --compile-dep "com.github.plokhotnyuk.jsoniter-scala::jsoniter-scala-macros:2.23.2"

Added by @alexarchambault and @lwronski in #2299, Thanks!

Set globally Java properties

Scala CLI allows users to globally set Java properties for its launcher using the config command. This will simplify the JVM properties management process, eliminating the need to pass these properties with each scala-cli execution.

To set global Java properties execute the following command:

scala-cli config java.properties Djavax.net.ssl.trustStore=cacerts Dfoo=bar2

When modifying Java properties, remember that you must redefine all of them. It's not possible to update just a single property. Essentially, each time you use the config command for Java properties, you replace the entire list of properties.

Whenever overwriting existing Java properties Scala CLI will let you know what was the previous value and in interactive mode ensure that you are ok with replacing them.

Added by @lwronski in #2317, Thanks!

Rename parameter for publish command

We've updated the --version parameter for the publish command. Now, when specifying the project version, use --project-version instead.

scala-cli publish --project-version 1.0.3 ...

Other changes

  • Add custom exception and throw it when node not found in the path by @lwronski in #2323
  • Skip reading ide-options-v2.json if doesn't exist to avoid throwing a… by @lwronski in #2333
  • Skip setting release flag when user pass directly -release or -java-o… by @lwronski in #2321
  • Prevent downloading Java 17 when running a REPL without sources by @lwronski in #2305
  • Extract JAVA_HOME from /usr/libexec/java_home for Mac by @lwronski in #2304
  • Bump case-app, add names limit to HelpFormat, move some name aliases, add test by @MaciejG604 in #2280
  • Build info with compute version @MaciejG604 in #2310

Fixes

  • Fix - install ps, which is necessary for starting Bloop by @lwronski in #2332
  • Load virtual data as byte arrays without encoding using UTF-8 by @lwronski in #2313
  • Accept directive packageType native when using native platform by @lwronski in #2311
  • Ignore url query params @MaciejG604 in #2334

Documentation changes

Build and internal changes

Updates and maintenance

Full Changelog: https://github.com/VirtusLab/scala-cli/compare/v1.0.2...v1.0.3

v1.0.2

What's new

This release brings enhancements to Scala CLI:

  • WinGet installation for Windows users
  • better navigation with improved build target names
  • introducing new command for Giter8 project generation
  • easier JVM properties management with .scalaopts file support.

The release also includes numerous bug fixes, updates, and new contributors.

Installation via WinGet on Windows

Scala CLI can now be installed via WinGet on Windows, with a command such as

winget install virtuslab.scalacli

Added by @mimoguz in #2239, Thanks!

Enhanced build target names

Now, the build target name will be derived from the workspace directory that contains it, making it easier for users to navigate between different projects within a multi-root workspace. Instead of a build target named as project_XYZ-XYZ, you will now see the name like workspace_XYZ-XYZ, where workspace refers to the name of the workspace directory.

.
├── scripts
│ ├── .scala-build
│ │ └── scripts_59f2159dd5
│ └── one.sc
├── skan
│ ├── .scala-build
│ │ └── skan_88b44a2858
│ └── main.scala
└── skan.code-workspace

Added by @MaciejG604 in #2201

Introducing 'new' command for Giter8 project generation

Giter8 is a project templating tool for Scala, and its integration within Scala CLI offers efficient way to set up new projects. By using the new command, users can generate new projects based on predefined or custom templates.

For example:

scala-cli --power new VirtusLab/scala-cli.g8

Added by @zetashift in #2202, Thanks!

Loading Java Properties from .scalaopts into ScalaCLI launcher

ScalaCLI allows to load Java properties into scala-cli launcher directly from a .scalaopts file located in your current working directory. This will simplify the JVM properties management process, eliminating the need to pass these properties with each scala-cli execution.

For instance, if -Djavax.net.ssl.trustStore=cacerts and -Dfoo2=bar2 are defined within your .scalaopts file, these values will be loaded into scala-cli launcher:

$ cat .scalaopts
-Djavax.net.ssl.trustStore=cacerts
-Dfoo2=bar2
$ scala-cli run ...

Added by @lwronski in #2267

Please be aware that ScalaCLI will only process Java properties that it recognizes from the .scalaopts file. Other JVM options, such as -Xms1024m, will be ignored as they can't be used within native image, and users will be alerted with a warning message when such non-compliant options are passed.

Other changes

Fixes

Documentation changes

Build and internal changes

Updates and maintenance

New Contributors

Full Changelog: https://github.com/VirtusLab/scala-cli/compare/v1.0.1...v1.0.2

v1.0.1

What's new

This release only contains bug fixes and minor internal improvements.

Fixes

  • Fix - add test to output from name of script example by @lwronski in #2153
  • Fix publishing with implicit publish.version coming from a git tag by @Gedochao in #2154
  • Fix conflicts when watch and interactive try to read StdIn by @MaciejG604 in #2168
  • Bsp wrapper fixes by @MaciejG604 in #2171
  • Add the .exe suffix to output provided by user for graalvm-native-image by @lwronski in #2182

Build and internal changes

  • refactor: Remove JavaInterface, which causes compilation issues with Bloop by @tgodzik in #2174
  • Enforce to use jvm 17 on linux aarch64 by @lwronski in #2180

Updates and maintenance

Full Changelog: https://github.com/VirtusLab/scala-cli/compare/v1.0.0...v1.0.1

v1.0.0

The official scala runner release

Scala CLI has reached the highly anticipated 1.0.0 milestone! Having addressed all the SIP-46 requirements, this version is going to become the official scala runner, replacing the old scala command.

For a deeper understanding of Scala CLI as the new scala runner and to explore its benefits and features, we encourage you to check out our blogpost.

Also be sure to get familiar with all the differences introduced by this change in our migration guide.

What's Changed

New default Scala version - 3.3.0

Scala 3.3.0 is now the default version for Scala CLI projects. It's the first LTS (Long Term Support) release of Scala 3 to be used by Scala CLI. Right on time for 1.0.0!

Added by @lwronski in #2140

Toolkit-test

By incorporating the Scala Toolkit into your project, you gain the advantage of two additional dependencies seamlessly integrated into your classpath:

  • org.scala-lang:toolkit:<version> is added to the main scope, allowing its utilization throughout your project.
  • org.scala-lang:toolkit-test:<version> is included in the test scope, making it available exclusively for testing purposes.

Scala CLI now supports the following features for the toolkit:

  • including e.g. //> using toolkit latest in any main scope file will automatically add the toolkit dependency to the main scope and the toolkit-test dependency to the test scope
  • if you place e.g. //> using toolkit latest within a test scope file, both toolkit and toolkit-test will be limited to the test scope only
  • inserting e.g. //> using test.toolkit latest anywhere in the project will add both toolkit and toolkit-test to the test scope only

This convention is encouraged for other toolkit-like libraries as well.

Added by @Gedochao in #2127 and #2137

Forcing an object wrapper for scripts

Scala CLI now supports the //> using objectWrapper directive, along with the corresponding --object-wrapper option, which allows to force wrapping script code in an object body instead of a class.

Using object wrappers should be avoided for scripts relying on multi-threading (as it may cause deadlocks), but may prove to be the only option in some cases.

Added by @MaciejG604 in #2136

Other changes

  • Add alias for snapshots repository in Maven by @lwronski in #2125
  • Bump typelevel-toolkit to 0.0.11, configure toolkit-test by @armanbilge in #2135
  • Fix updating toolkit dependencies by @Gedochao in #2138
  • Improve directive parsing errors & special-case toolkit directive version parsing by @Gedochao in #2133
  • Fix determining position for value in directive without quotes by @lwronski in #2141

Fixes

Documentation changes

  • Add docs for bootstrapped standalone fat JAR by @lwronski in #2122
  • Add developer docs on modifying reflect-config.json by @Gedochao in #2114

Build and internal changes

Updates and maintenance

New Contributors

Full Changelog: https://github.com/VirtusLab/scala-cli/compare/v1.0.0-RC2...v1.0.0

v1.0.0-RC2

What's Changed

Exclude

To exclude specific source files or entire directories from a Scala CLI project, you can now use the //> using exclude directive in your project.scala file. Alternatively, you can do the same from the command line with the --exclude option.

  • absolute path: /root/path/to/your/project/Main.scala
  • relative path: src/main/scala/Main.scala
  • glob pattern: *.sc

For example, to exclude all files in the example/scala directory, add the following directive to your project.scala file:

//> using exclude "example/scala"

Added by @lwronski in #2053.

Directives with a Test Scope equivalent

Some directives now have a test scope equivalent, such as using dep and its test scope counterpart using test.dep. This allows you to declare dependencies that are only used in tests outside of test-specific sources.

For example, you can declare a dependency on munit in your project.scala file like this:

//> using test.dep "org.scalameta::munit::0.7.29"

The dependency will only be available in test sources.

Here's a list of directives with a test scope equivalent with example values:

 //> using test.dep "org.scalameta::munit::0.7.29"
//> using test.jar "path/to/jar"
//> using test.javaOpt "-Dfoo=bar"
//> using test.javacOpt "source", "1.8", "target", "1.8"
//> using test.javaProp "foo1=bar1"
//> using test.option "-Xfatal-warnings"
//> using test.resourceDir "testResources"
//> using test.toolkit "latest"

Added by @Gedochao in #2046

Changes to using-directives syntax

We've made several updates to simplify the using directives syntax in this release:

  • allowed omitting commas in lists of values.
  • disallowed multiline comments.
  • removed multiline strings.
  • removed require and @require syntax support.
  • allowed values without quotes.
  • removed @using.

For example, the following using directives are now valid without the need for commas and quotes:

//> using scala 3.2.2
//> using javacOpt -source 1.8 -target 1.8

Added by @tgodzik in #2076

Bootstrapped standalone fat JAR.

The Scala CLI launcher is available as a standalone fat JAR. You can download the stable version of the Scala CLI fat JAR from Maven and try it now:

cs launch org.virtuslab.scala-cli:cliBootstrapped:1.0.0-RC2 -M scala.cli.ScalaCli

Added by @romanowski in #2005.

Access the path of the script being run from its code

With the special scriptPath function, you can now easily access the path of the script being run from the script code itself. Here's an example of how to use the scriptPath value:

#!/usr/bin/env -S scala-cli shebang

println(scriptPath)
chmod +x scripts/hello.sc
./scripts/hello.sc
./scripts/hello.sc

Added by @lwronski in #1990

Explicit Handling of Paths in using-directives

The ${.} pattern in directive values can now be replaced by the parent directory of the file containing the directive. This makes it possible to generate coverage output files relative to the source file location, for example:

//> using options "-coverage-out:${.}"

Added by @lwronski in #2040

Fix deadlocks in Script Wrappers

We have resolved an issue that caused deadlocks when threads were run from the static initializer of the wrapper object (#532 and #1933). Based on the feedback from the community (Thanks @dacr), we found that encapsulating the script code into a class wrapper fixes the issue. The wrapper is generated by the Scala CLI and is not visible to the user.

This change alters the behavior of scripts that use the @main annotation. The @main annotation is no longer supported in .sc files.

@main def main(args: String*): Unit = println("Hello")
scala-cli script.sc
[warn]  Annotation @main in .sc scripts is not supported, use .scala format instead
Compiling project (Scala 3.2.2, JVM)
[error] ./script.sc:1:1
[error] method main cannot be a main method since it cannot be accessed statically
[error] @main def main(args: String*): Unit = println("Hello")
[error] ^^^^^
Error compiling project (Scala 3.2.2, JVM)
Compilation failed

Fixed by @MaciejG604 in #2033

Other changes

Publishing changes

Fixes

Documentation changes

  • Docs: Update build output folder in Internal docs by @amaalali in #2071
  • Add docs for test scope directives by @Gedochao in #2058
  • Improve error messages for malformed config values by @Gedochao in #2014
  • Update export documentation by @MaciejG604 in #2023
  • Add weaver test framework instruction by @lenguyenthanh in #2021

Build and internal changes

Updates and maintenance

Full Changelog: https://github.com/VirtusLab/scala-cli/compare/v1.0.0-RC1...v1.0.0-RC2

v1.0.0-RC1

Official scala runner release candidate

v1.0.0-RC1 is the first release candidate version of Scala CLI.

Either this or a future release candidate is meant to become the new official scala runner to accompany the Scala compiler (scalac) and other scripts, replacing the old scala command.

To learn more about Scala CLI as the new scala runner, check out our recent blogpost: https://virtuslab.com/blog/scala-cli-the-new-scala-runner/

Scala CLI should now have better performance

With a number of newly added performance tweaks, you can expect Scala CLI to run considerably faster. Added by @lwronski in #1939

Using experimental features will now cause Scala CLI to print an appropriate warning.

scala-cli --power -e '//> using publish.name "my-library"'
# The '//> publish.name "my-library"' directive is an experimental feature.
# Please bear in mind that non-ideal user experience should be expected.
# If you encounter any bugs or have feedback to share, make sure to reach out to the maintenance team at https://github.com/VirtusLab/scala-cli

The warning can be suppressed with the --suppress-experimental-warning option, or alternatively with the suppress-warning.experimental-features global config key.

scala-cli config suppress-warning.experimental-features true

Added by @Gedochao in #1920

Experimental and restricted configuration keys will now require to be accessed in --power mode

Some configuration keys available with the config sub-command have been tagged as experimental or restricted and will only be available in --power mode.

scala-cli config httpProxy.address
# The 'httpProxy.address' configuration key is restricted.
# You can run it with the '--power' flag or turn power mode on globally by running:
# scala-cli config power true.

Added by @Gedochao in #1953

Dropped deprecated using directive syntax

The following syntax for using directives have been dropped:

  • skipping //>
  • multiline directives
  • directives in /*> ... */ comments
  • directives in plain // comments
  • @using

Added by @tgodzik in #1932

Added support for packaging native images from Docker

It is now possible to package a GraalVM native image with Scala CLI from docker.

docker run -v $(pwd)/Hello.scala:/Hello.scala virtuslab/scala-cli package --native-image /Hello.scala

Added by @lwronski in #1961

Added support for Scala Native's LTO

It is now possible to set the Link Time Optimization (LTO) when using Scala CLI with Scala Native. The available options are "thin", "full" and "none". You can do it with the --native-lto option from the command line:

scala-cli -e 'println("Hello")' --native --native-lto thin

Or with a using directive:

//> using platform "scala-native"
//> using nativeLto "thin"
@main def main(): Unit = println("Hello")

Added by @lwronski in #1964

Other changes

Publishing changes

Fixes

  • Print an informative error if the project workspace path contains File.pathSeparator by @Gedochao in #1985
  • Enable to pass custom docker-cmd to execute application in docker by @lwronski in #1980
  • Fix - uses show cli.nativeImage command to generate native image by @lwronski in #1975
  • Vcs.parse fix by @KuceraMartin in #1963
  • move args definition to the top of the script by @bishabosha in #1983

Documentation changes

Build and internal changes

Updates and maintenance

New Contributors

Full Changelog: https://github.com/VirtusLab/scala-cli/compare/v0.2.1...v1.0.0-RC1

v0.2.1

Add a guide for migrating from the old scala runner to Scala CLI

As of SIP-46, Scala CLI has been accepted as the new scala command. To make the transition smooth we added a guide highlighting the differences between the two runners.

Added by @Gedochao in #1900

Improve the publish and publish setup sub-commands' user experience

We're currently focusing on improving the experimental publish feature of Scala CLI and making publish setup + publish more stable and user-friendly.

Using pgp keys created by config --create-pgp-key subcommand is now supported as a default option, no additional user input is needed.

Addressed by @alexarchambault in #1432 and by @MaciejG604 in #1898

Remove unsupported kebab-case style in using directives

All using directives names are now using camelCase, kebab-case is no longer available.

Added by @lwronski in #1878

Add a reference for available config keys in help & docs

You can now view the available config keys using config --help:

scala-cli config -h
# Usage: scala-cli config [options]
# Configure global settings for Scala CLI.
#
# Available keys:
# actions Globally enables actionable diagnostics. Enabled by default.
# interactive Globally enables interactive mode (the '--interactive' flag).
# power Globally enables power mode (the '--power' launcher flag).
# suppress-warning.directives-in-multiple-files Globally suppresses warnings about directives declared in multiple source files.
# suppress-warning.outdated-dependencies-files Globally suppresses warnings about outdated dependencies.
#
# You are currently viewing the basic help for the config sub-command. You can view the full help by running:
# scala-cli config --help-full
# For detailed documentation refer to our website: https://scala-cli.virtuslab.org/docs/commands/misc/config
#
# Config options:
# --unset, --remove Remove an entry from config

Also, config --full-help will show the list of all keys.

Added by @Gedochao in #1910

Pass user arguments to JS runner

It's now possible to pass user arguments to a JS application:

import scala.scalajs.js
import scala.scalajs.js.Dynamic.global

val process = global.require("process")
val argv = Option(process.argv)
.filterNot(js.isUndefined)
.map(_.asInstanceOf[js.Array[String]].drop(2).toSeq)
.getOrElse(Nil)
val console = global.console
console.log(argv.mkString(" "))
scala-cli ScalaJsArgs.sc --js -- Hello World
Hello World

Added by @alexarchambault in #1826

Other changes

  • Add 'dependency' and 'dependencies' alias for using directive by @MaciejG604 in #1903

Documentation updates

Internal changes

  • Fix handling for experimental features by @Gedochao in #1915
  • Change default home directory for tests integration and docs-test modules to avoid overriding global user config by @lwronski in #1917
  • NIT Use enums for help groups and help command groups by @Gedochao in #1880

Updates & maintenance

New Contributors

v0.2.0

Require the --power option for restricted features by default

Until now, Scala CLI has been limiting some of its functionalities in its scala distribution. Starting with v0.2.0, those limitation will be applied to all distributions, including scala-cli.

This was done in order to make the behaviour consistent with Scala CLI acting as the Scala runner.

Restricted features can be accessed by using the --power launcher flag. Do note that launcher flags have to be passed before the sub-command.

scala-cli --power package .

Alternatively, the power mode can be turned on globally by running:

scala-cli config power true 

Please note that this change may affect your existing scripts or workflows that rely on the limited commands from ScalaCLI (such as package, publish). You can still use those commands with power mode enabled.

When you try to use a limited command in restricted mode, you will now see a warning message with suggestions on how to enable this command:

$ scala-cli package Hello.scala
# This command is restricted and requires setting the `--power` option to be used.
# You can pass it explicitly or set it globally by running:
# scala-cli config power true
$ scala-cli config power true
$ scala-cli package Hello.scala
# Wrote Hello, run it with
# ./Hello

Added by @lwronski in #1835 and #1849

Allow executable Scala scripts without a file extension

As of this release Scala scripts without the *.sc file extension will be supported for execution when using the shebang command.

#!/usr/bin/env -S scala-cli shebang -S 3

println(args.size)
println(args.headOption)
chmod +x hello
./hello Hello World
#2
#Some(Hello)

Note that files with no extension are always run as scripts even though they may contain e.g. a valid .scala program.

Also, do note that this feature has only been added for shebang - the run sub-command (which is the default way of running inputs when a sub-command is not specified explicitly) will not support this.

Added by @MaciejG604 in #1802

Export Project configuration to Json

It is now possible to export configuration from Scala CLI project to Json format with the export sub-command.

scala-cli --power export --json .

It is currently exporting basic information about the project and includes, for example, the following fields:

  • ScalaVersion
  • Platform
  • Sources
  • Dependencies
  • Resolvers

Example of generated Json output:

{
"scalaVersion": "3.2.2",
"platform": "JVM",
"scopes": {
"main": {
"sources": [
"Hello.scala"
],
"dependencies": [
{
"groupId": "com.lihaoyi",
"artifactId": {
"name": "pprint",
"fullName": "pprint_3"
},
"version": "0.6.6"
}
],
...
}
}
}

Added by @MaciejG604 in #1840

Rename using lib to using dep

To be more consistent with dependency command line options --dep, the dependency using directive is now passed by using dep. Please note that we have kept the alias of the old directive (lib, libs) for backwards compatibility.

 //> using dep "org.scalameta::munit:0.7.29"

Renamed by @lwronski in #1827

Other breaking changes

Remove ammonite imports support

The support for $ivy and $dep ammonite imports has been removed. To easily convert existing $ivy and $dep imports into the using dep directive in your sources, you can use the provided actionable diagnostic.

convert_ivy_to_using_dep

Removed by @MaciejG604 in #1787

Drop the metabrowse sub-command

With this release, support for Metabrowse has been removed from Scala CLI. This change was made in order to limit the number of features that we need to support, especially since the Metabrowse project is no longer being actively worked on.

Remove by @lwronski in #1867

Other changes

  • Add a warning for the -run option of the legacy scala runner, instead of failing by @Gedochao in #1801
  • Add warnings for the deprecated -Yscriptrunner legacy scala runner option instead of passing it to scalac by @Gedochao in #1804
  • Filter out restricted & experimental options from SIP mode help by @Gedochao in #1812
  • Warn in sip mode when using restricted command by @lwronski in #1862
  • Add more detail for sub-commands' help messages by @Gedochao in #1852
  • Fix printing not supported option in restricted mode by @lwronski in #1861
  • Shorter options help by @Gedochao in #1872

Fixes

  • Fix warning about using directives in multiple files when two java files are present by @MaciejG604 in #1796
  • Quit flag not suppresses compilation errors by @lwronski in #1792
  • Dont warn about target directives by @MaciejG604 in #1803
  • Fix - actionable actions not suggest update to previous version by @lwronski in #1813
  • Fix actionable action when uses latest sytanx version in lib by @lwronski in #1817
  • Prevent NPE from being thrown by the export sub-command if testFramework isn't defined by @Gedochao in #1814
  • Fix message checking in test by @MaciejG604 in #1847
  • blooprifle: add -XX:+IgnoreUnrecognizedVMOptions to hardCodedDefaultJavaOpts by @Flowdalic in #1845
  • Trim passwords obtained as command result by @MaciejG604 in #1871

Build and internal changes

Documentation updates

Updates & maintenance

New Contributors

Full Changelog: https://github.com/VirtusLab/scala-cli/compare/v0.1.20...v0.2.0

v0.1.20

Add support for Scala Toolkit

Scala CLI now has support for Scala Toolkit.

Scala Toolkit is an ongoing effort by Scala Center and VirtusLab to compose a set of approachable libraries to solve everyday problems.

It is currently in its pre-release phase and includes the following libraries:

  • MUnit for testing;
  • Sttp for HTTP client;
  • UPickle/UJson for reading, writing and operating on JSONs;
  • OS-Lib for operating on files and the operating system.

You can add it to your Scala CLI build from the command line with the --with-toolkit option.

scala-cli . --with-toolkit latest

There's also an appropriate using directive.

//> using toolkit "0.1.6"

Added by @lwronski in #1768

Scala CLI is built with Scala 3.2.2

We now rely on Scala 3.2.2 as the default internal Scala version used to build the project.

Added by @lwronski and @Gedochao in #1772

Removal of the about and doctor sub-commands

The about command has been removed, its features merged back to the version command. As a result, the version command will now check if your locally installed Scala CLI is up-to-date. It is possible to skip the check with the --offline option, or when printing raw CLI or default Scala versions with --cli-version and --scala-version, respectively.

scala-cli version --offline                     
# Scala CLI version: 0.1.20
# Scala version (default): 3.2.2

Similarly, the doctor sub-command has been removed, with its past and previously planned functionalities to be delivered in a more interactive manner in the future.

Added by @Gedochao in #1744

The Scala CLI aarch64/arm64 binary is now available via sdkman

You can now get the platform-appropriate Scala CLI binary on aarch64/arm64 architecture via sdkman.

Added by @mkurz in #1748

aarch64/arm64 artifact with the launcher script

The scala-cli.sh launcher script now correctly downloads the aarch64/arm64 artifact on the appropriate architecture.

Added by @mkurz in #1745

Run a .jar file as a regular input

JARs can now be run just like any other input, without the need of passing the -cp option.

scala-cli Hello.jar
# Hello

Added by @lwronski in #1738

Java properties without the need for --java-prop

The --java-prop option can be skipped when passing Java properties to Scala CLI now.

scala-cli Hello.scala -Dfoo=bar

Added by @lwronski in #1739

Docker packaging with using directives

It is now possible to configure packaging into a docker image via using directives.

//> using packaging.dockerFrom "openjdk:11"
//> using packaging.dockerImageTag "1.0.0"
//> using packaging.dockerImageRegistry "virtuslab"
//> using packaging.dockerImageRepository "scala-cli"

Added by @lwronski in #1753

Pass GraalVM args via a using directive

It is now possible to pass args to GraalVM via the following using directive:

//> using packaging.graalvmArgs "--no-fallback", "--enable-url-protocols=http,https"

Added by @lwronski in #1767

Other changes

  • Remove irrelevant options from version help message by @lwronski in #1737
  • Include launcher options in the help for the default and help sub-commands by @Gedochao in #1725
  • Remove suffix .aux from progName when installed by cs by @lwronski in #1736
  • Don't fail in case of connection errors in the version sub-command by @Gedochao in #1760
  • Set workspace dir to os.tmp.dir for virtual sources by @lwronski in #1771
  • Add support for deprecated Scala 2.13.x-specific scala runner options by @Gedochao in #1774
  • Add support for the -with-compiler runner option by @Gedochao in #1780

Fixes

Build and internal changes

Documentation updates

Updates & maintenance

New Contributors

Full Changelog: https://github.com/VirtusLab/scala-cli/compare/v0.1.19...v0.1.20

v0.1.19

The Linux aarch64 native launcher is here! (experimental)

We are happy to announce that there is a new dedicated launcher for the Linux Aarch64. You can find it here.

Added in #1703 by @lwronski

Fix workspace/reload for Intellij IDEA

Dependencies (and other configurations) from using directives should now always be picked up after a BSP project reload.

Fixed by @Gedochao in #1681.

shebang headers in Markdown

The shebang headers in scala code blocks inside a markdown input are always ignored.

# Scala with `shebang`
A sample code block with the `shebang` header.
```scala
#!/usr/bin/env -S scala-cli shebang
println("Hello world")
```

Added by @Gedochao in #1647

Export Scala compiler plugins to Mill projects

It is now possible to export scalac compiler plugins from a Scala CLI project to Mill with the export sub-command.

Added by @carlosedp in #1626

Other changes

SIP Changes

  • Fix the order of help command groups for the default help by @Gedochao in #1697
  • Adjust SIP help output & ensure ScalaSipTests are run on Windows by @Gedochao in #1695
  • Add warnings for -save & -nosave legacy scala runner options instead of failing by @Gedochao in #1679

Fixes

Documentation updates

Build and internal changes

Updates & maintenance

New Contributors

Full Changelog: https://github.com/VirtusLab/scala-cli/compare/v0.1.18...v0.1.19

v0.1.18

Filter tests with --test-only

It is now possible to filter test suites with the --test-only option.

//> using dep "org.scalameta::munit::1.0.0-M7"
package tests.only
class Tests extends munit.FunSuite {
test("bar") {
assert(2 + 2 == 5)
}
test("foo") {
assert(2 + 3 == 5)
}
test("foo-again") {
assert(2 + 3 == 5)
}
}
package tests
class HelloTests extends munit.FunSuite {
test("hello") {
assert(2 + 2 == 4)
}
}
scala-cli test BarTests.scala HelloTests.scala --test-only 'tests.only*' 
# tests.only.Tests:
# ==> X tests.only.Tests.bar 0.037s munit.FailException: ~/project/src/test/BarTests.scala:5 assertion failed
# 4: test("bar") {
# 5: assert(2 + 2 == 5)
# 6: }
# at munit.FunSuite.assert(FunSuite.scala:11)
# at tests.only.Tests.$init$$$anonfun$1(BarTests.scala:5)
# at tests.only.Tests.$init$$$anonfun$adapted$1(BarTests.scala:6)
# + foo 0.004s
# + foo-again 0.001s

Filtering particular tests by name requires passing args to the test framework. For example, with munit:

scala-cli test BarTests.scala HelloTests.scala --test-only 'tests.only*'  -- '*foo*'
# tests.only.Tests:
# + foo 0.032s
# + foo-again 0.001s

Added by @lwronski in #1604

Accept authenticated proxy params via Scala CLI config

If you can only download artifacts through an authenticated proxy, it is now possible to configure it with the config subcommand.

scala-cli config httpProxy.address https://proxy.company.com
scala-cli config httpProxy.user _encoded_user_
scala-cli config httpProxy.password _encoded_password_

Replace _encoded_user_ and _encoded_password_ by your actual user and password, following the password option format. They should typically look like env:ENV_VAR_NAME, file:/path/to/file, or command:command to run.

Added by @alexarchambault in #1593

Support for running Markdown sources from zipped archives and gists

It is now possible to run .md sources inside a .zip archive. Same as with directories, .md sources inside zipped archives are ignored by default, unless the --enable-markdown option is passed.

scala-cli archive-with-markdown.zip --enable-markdown

This also enables running Markdown sources fom GitHub gists, as those are downloaded by Scala CLI as zipped archives.

scala-cli https://gist.github.com/Gedochao/6415211eeb8ca4d8d6db123f83f0f839 --enable-markdown

It is also possible to point Scala CLI to a .md file with a direct URL.

scala-cli https://gist.githubusercontent.com/Gedochao/6415211eeb8ca4d8d6db123f83f0f839/raw/4c5ce7593e19f1390555221e0d076f4b02f4b4fd/example.md

Added by @Gedochao in #1581

Support for running piped Markdown sources

Instead of passing paths to your Markdown sources, you can also pipe your code via standard input:

echo '# Example Snippet
```scala
println("Hello")
```' | scala-cli _.md

Added by @Gedochao in #1582

Support for running Markdown snippets

It is now possible to pass Markdown code as a snippet directly from the command line.

scala-cli run --markdown-snippet '# Markdown snippet
with a code block
```scala
println("Hello")
```'

Added by @Gedochao in #1583

Customize exported Mill project name

It is now possible to pass the desired name of your Mill project to the export sub-command with the --project option.

scala-cli export . --mill -o mill-proj --project project-name

Added by @carlosedp in #1563

Export Scala compiler options to Mill projects

It is now possible to export scalac options from a Scala CLI project to Mill with the export sub-command.

Added by @lolgab in #1562

Other changes

Fixes

Documentation updates

Build and internal changes

Updates & maintenance

New Contributors

Full Changelog: https://github.com/VirtusLab/scala-cli/compare/v0.1.17...v0.1.18

v0.1.17

SDKMAN and Homebrew support installation of Scala CLI for M1

To install Scala CLI via SDKMAN, run the following command from the command line:

sdk install scalacli

and to install Scala CLI via homebrew:

brew install Virtuslab/scala-cli/scala-cli

Added by @wleczny in #1505 and #1497

Specifying the --jvm option via using directives

The --jvm option can now be added via using directives, like

//> using jvm "adopt:11"

Added by @lwronski in #1539

Accept more scalac options without escaping

Scala CLI now accepts options such as -rewrite, -new-syntax, -old-syntax, -source:<target>, -indent and -no-indent, without requiring them to be escaped by -O.

Fixed by @Gedochao in #1501

Enable python support via using directives

The --python option can now be enabled via a using directive, like

//> using python

Added by @alexarchambault in #1492

Other changes

Publish

Spark

Fixes

Build and internal changes

Documentation / help updates

Updates / maintainance

New Contributors

Full Changelog: https://github.com/VirtusLab/scala-cli/compare/v0.1.16...v0.1.17

v0.1.16

This release consists mainly of updates, fixes, and various enhancements of existing features.

Specifying javac options via using directives

javac options can now be added via using directives, like

//> using javacOpt "source", "1.8", "target", "1.8"

Added by @lwronski in #1438

Pressing enter in watch mode proceeds to run / compile / test / … again

In watch mode (using the -w or --watch option), pressing Enter when Scala CLI is watching for changes makes it run again what it's supposed to be doing (compiling, running, running tests, or packaging, etc.) This is inspired by Mill's behaviour in watch mode, which supports the same feature.

Added by @alexarchambault in #1451

Installation via Scoop on Windows

Scala CLI can now be installed via Scoop on Windows, with a command such as

scoop install scala-cli

Added by @nightscape in #1416, thanks to him!

Actionable diagnostics in Metals

Scala CLI should now send text edit suggestions with some of its diagnostics, via BSP, so that editors can suggest those edits to users. This should work in upcoming versions of Metals in particular.

Added by @lwronski in #1448

Other

Fixes

Fixes in Scala Native binaries caching

When running a sequence of commands such as

$ scala-cli run --native .
$ scala-cli --power package --native . -o my-app

Scala CLI should cache a Scala Native binary during the first command, so that the second command can just re-use it, rather than generating a binary again. This also fixes the re-use of compilation artifacts between both commands, so that the Scala CLI project isn't re-compiled during the second command either.

Fixed by @alexarchambault in #1406

Accept more scalac options without escaping

Scala CLI now accepts options such as -release, -encoding, -color, -feature, -deprecation and -nowarn, without requiring them to be escaped by -O. It also accepts --scalac-verbose, which is equivalent to -O -verbose (increases scalac verbosity). Lastly, it warns when -release and / or -target:<target> are inconsistent with --jvm.

Fixed by @Gedochao in #1413

Fix --java-option and --javac-option handling in package sub-command

--java-option and --javac-option should now be accepted and handled properly in the package sub-command.

Fixed by @lwronski in #1434

Fix wrong file name when publising Scala.js artifacts locally

The publish local sub-command used to publish Scala.js artifacts with a malformed suffix. This is now fixed.

Fixed by @lwronski in #1443

Fix spurious stack traces in the publish and publish local sub-commands

The publish and publish local commands could print spurious stack traces when run with non-default locales, using native Scala CLI binaries. This is now fixed.

Fixed by @romanowski in #1423

Make run --python --native work from Python virtualenv

Using both --native and --python in the run sub-command should work fine from Python virtualenv.

Fixed by @kiendang in #1399

Documentation / help updates

Updates / maintainance

New Contributors

Full Changelog: https://github.com/VirtusLab/scala-cli/compare/v0.1.15...v0.1.16

v0.1.15

The M1 native launcher is here! (experimental)

We are happy to announce that there is a new dedicated launcher for M1 users. You can find it here.

Please note that the package sub-command is unstable for this launcher.

Added in #1396 by @lwronski

--python option for repl sub-command (experimental)

Passing the --python option allows using ScalaPy with the repl sub-command:

▶ scala-cli --python
Welcome to Scala 3.2.0 (17.0.2, Java OpenJDK 64-Bit Server VM).
Type in expressions for evaluation. Or try :help.

scala> import me.shadaj.scalapy.py

scala> py.Dynamic.global.range(1, 4)
val res0: me.shadaj.scalapy.py.Dynamic = range(1, 4)

Added in #1336 by @alexarchambault

-d, -classpath and compile sub-command's --output options changes

To be backward compatible with the scala command, some changes have been made to the following options:

  • The compile sub-command's --output option has been renamed to --compilation-output. This option is now also available from the run and package sub-commands.
▶ scala-cli compile Hello.scala --compilation-output out
▶ scala-cli --main-class Hello -classpath out
Hello
  • The -d option is no longer an alias for --dependency, but for --compilation-output.
    • -O -d -O path/to/compilation/output now defaults to -d path/to/compilation/output.
▶ scala-cli compile Hello.scala -d out
▶ scala-cli --main-class Hello -classpath out
Hello
  • The old --classpath option has been renamed to --print-classpath.
    • --classpath, --class-path and -classpath options are now aliases for the --extra jars option.
    • -O -classpath -O path/to/classpath now defaults to --extra-jars path/to/classpath.
▶ scala-cli compile --print-classpath Hello.scala
# ~/Projects/debug-test/.scala-build/project_103be31561_103be31561-7a1ed8dde0/classes/main:~/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala3-library_3/3.2.0/scala3-library_3-3.2.0.jar:~/Library/Caches/ScalaCli/local-repo/v0.1.15/org.virtuslab.scala-cli/runner_3/0.1.15/jars/runner_3.jar:~/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.8/scala-library-2.13.8.jar

Added in #1340 by @Gedochao

Make inputs optional when -classpath and --main-class are passed

The following changes have been made to improve backward compatibility with the scala command:

  • Passing the --main-class option along with -classpath to the default command now defaults to run instead of repl:
▶ scala-cli --main-class Hello -classpath out
Hello
  • If the run sub-command is passed explicitly, it's sufficient to have a main class on the classpath (inputs aren't necessary then):
▶ scala-cli compile Hello.scala -d out
▶ scala-cli run -classpath out
Hello

Added in #1369 by @Gedochao

Debugging with the run and test sub-commands

It is now possible to debug code ran by run and test sub-commands:

▶ scala-cli Main.scala --debug
Listening for transport dt_socket at address: 5005
Hello

This addresses #1212

Added in #1389 by @wleczny

--platform option

This option can be used to choose the platform, which should be used to compile and run the application.

▶ scala-cli Main.scala --platform js
Hello

Note that --platform js is an alias for --js and --platform native is an alias for --native.

This addresses #1214

Added in #1347 by @wleczny

Other changes

Fixes

  • Ensure directories are created recursively when the package sub-command is called by @Gedochao in #1371
  • Fix calculation of Scala version and turn off the -release flag for 2.12.x < 2.12.5 by @Gedochao in #1377
  • Fix finding main classes in external jars by @Gedochao in #1380
  • Fix Js split style SmallModulesFor in pure JVM by @lwronski in #1394

Build and internal changes

Updates

Full Changelog: https://github.com/VirtusLab/scala-cli/compare/v0.1.14...v0.1.15

v0.1.14

Hotfix printing stacktraces from Scala CLI runner for Scala 3.x < 3.2.0

We fixed a nasty bug breaking any Scala CLI run using any Scala 3 version earlier than 3.2.0 on printing stacktraces. Only Scala CLI 0.1.13 was affected.

$ scala-cli about
Scala CLI version: 0.1.13
Scala version (default): 3.2.0
$ scala-cli -S 3.1.3 -e 'throw Exception("Broken")'
Compiling project (Scala 3.1.3, JVM)
Compiled project (Scala 3.1.3, JVM)
Exception in thread "main" java.lang.NoSuchMethodError: 'long scala.runtime.LazyVals$.getOffsetStatic(java.lang.reflect.Field)'
at scala.cli.runner.StackTracePrinter.<clinit>(StackTracePrinter.scala:101)
at scala.cli.runner.StackTracePrinter$.coloredStackTraces(StackTracePrinter.scala:104)
at scala.cli.runner.StackTracePrinter$.$lessinit$greater$default$4(StackTracePrinter.scala:11)
at scala.cli.runner.Runner$.main(Runner.scala:18)
at scala.cli.runner.Runner.main(Runner.scala)

Added in #1358 by @romanowski

Build and internal changes

Updates

Full Changelog: https://github.com/VirtusLab/scala-cli/compare/v0.1.13...v0.1.14

v0.1.13

Change the default sub-command to repl when no args are passed

We no longer default to the help sub-command when no arguments are passed. Starting with 0.1.13 running Scala CLI with no args will launch the repl.

$ scala-cli -S 3
Welcome to Scala 3.1.3 (17.0.3, Java OpenJDK 64-Bit Server VM).
Type in expressions for evaluation. Or try :help.

scala>

When inputs are provided, Scala CLI defaults to the run sub-command, as before.

$ cat hello.sc
println("Hello World")
$ scala-cli hello.sc
Hello World

This change was added by @Gedochao in #1268

Marking the project's workspace root with the project.settings.scala file

Scala CLI now supports marking the workspace root directory with an optional configuration file: project.settings.scala. The workspace root determines where the .bsp and .scala-build directories will be saved (which mostly affects what path should be opened in your IDE to import the Scala CLI project through BSP).

The settings file is also the recommended input for your project's using directives. Otherwise, it functions similarly to other .scala sources.

$ cat project.settings.scala
//> using scala "2.13.4"
$ cat hello.sc
println(util.Properties.versionString)
$ scala-cli hello.sc .
version 2.13.4

To see how exactly is the root directory resolved, see this document

Added in #1260 by @wleczny

Scala CLI is now built with Scala 3.2.0

We now rely on Scala 3.2.0 as the default internal Scala version used to build the project.

This change was added by @lwronski in #1314

Add resources support for Scala Native

Scala CLI now allows embedding resources (by default) in a Scala Native binary with the --native flag.

$ cat resources/scala-native/foo.c
int foo(int i) {
return i + 42;
}
$ cat hello.scala
//> using platform "native"
//> using resourceDir "resources"

import scalanative.unsafe.*

@extern
def foo(int: CInt): CInt = extern

@main def main =
println(foo(3))
$ scala-cli hello.scala --native
45

Added in #812 by @jchyb

Default to the run sub-command instead of repl when the -e, --execute-script, --execute-scala or --execute-java options are passed.

Even though we default to the repl sub-command when no arguments are passed to Scala CLI, an exception to that rule is when a snippet is passed with one of the following options: -e, --execute-script, --execute-scala or --execute-java. In that case, the passed snippets are treated as inputs to be executed and switch the default to the run sub-command.

$ scala-cli -e 'println("Hello")'
Hello

If you still want to pass a snippet to the repl, you can either pass the repl sub-command explicitly or use one of the following options, as before: --script-snippet, --scala-snippet or --java-snippet.

$ scala-cli --script-snippet 'println("Hello")'
Welcome to Scala 3.1.3 (17.0.2, Java OpenJDK 64-Bit Server VM).
Type in expressions for evaluation. Or try :help.

scala> snippet_sc.main(Array.empty)
Hello

This change was introduced to make the -e option backwards compatible with the scala command.

Added in #1313 by @Gedochao

Work in progress

Support for Markdown (experimental)

Scala CLI can now accept .md inputs and run/compile a snippet of Scala code inside the markdown. Markdown sources are ignored by default unless passed explicitly as inputs. You can also enable including non-explicit .md inputs by passing the --enable-markdown option.

Plain scala snippets are treated similarly to .sc scripts which can be run by scala-cli:

$ cat Example.md
This is a simple example of an `.md` file with a Scala snippet.

```scala
val message = "Hello from Markdown"
println(message)
```
scala-cli Example.md
Hello from Markdown

See this document for more details about the experimental Markdown support.

Added in #1268 by @Gedochao

Add --python option for the run sub-command (experimental)

The run sub-command can now run ScalaPy when the --python option is passed.

$ cat helloscalapy.sc
import py.SeqConverters
val len = py.Dynamic.global.len(List(0, 2, 3).toPythonProxy)
println(s"Length is $len")
$ scala-cli helloscalapy.sc --python -S 2.13
Length is 3

Added in #1295 by @alexarchambault

Other changes

Documentation

Fixes

Build and internal changes

Updates

New Contributors

Full Changelog: https://github.com/VirtusLab/scala-cli/compare/v0.1.12...v0.1.13

v0.1.12

Add --spark, --spark-standalone and --hadoop options for the run sub-command

The run sub-command can now run Spark jobs when the --spark option is passed.

$ scala-cli run --spark SparkJob.scala

Similarly, it's possible to run Hadoop jobs by passing the --hadoop option.

scala-cli run --hadoop HadoopJob.java

It's also possible to run Spark jobs without a Spark distribution by passing the --spark-standalone option.

$ scala-cli run --spark-standalone SparkJob.scala

Added in #1129 by alexarchambault

Add the default Scala version to the output of the version sub-command

The version sub-command now includes both the Scala CLI version and the default Scala version.

$ scala-cli --version
Scala CLI version 0.1.12
Default Scala version: 3.1.3
$ scala-cli -version
Scala CLI version 0.1.12
Default Scala version: 3.1.3
$ scala-cli version
Scala CLI version 0.1.12
Default Scala version: 3.1.3

You can also pass the --cli-version option to only get the Scala CLI version or the --scala-version option to only get the default Scala version.

$ scala-cli version --cli-version
0.1.12
$ scala-cli version --scala-version
3.1.3

This is potentially a breaking change if your automation relies on the output of the version sub-command.

Added in #1262 by lwronski

Enable passing the scalafmt configuration with --scalafmt-conf and --scalafmt-conf-str

It is now possible to pass a custom location of the scalafmt configuration with the --scalafmt-conf option for the fmt sub-command.

$ scala-cli fmt --scalafmt-conf path/to/the/conf/.scalafmt.conf

You can also pass the configuration straight from the terminal with --scalafmt-conf-str.

$ scala-cli fmt --scalafmt-conf-str  "version=3.5.5
runner.dialect=scala213"

Added in #1227 by wleczny

Enable turning the --interactive mode on permanently

It is now possible to set the --interactive mode on by default, so that passing it explicitly isn't necessary.

The next time when you run a command with the --interactive option set to on, Scala CLI will suggest to turn it on permanently.

This is recommended for environments where scala-cli is used by a human user only (and not by any automation).

$ scala-cli . --interactive
You have run the current scala-cli command with the --interactive mode turned on.
Would you like to leave it on permanently?
[0] Yes
[1] No
0
--interactive is now set permanently. All future scala-cli commands will run with the flag set to true.
If you want to turn this setting off at any point, just run `scala-cli config interactive false`.
Found several main classes. Which would you like to run?
[0] ScalaMainClass2
[1] ScalaMainClass1
[2] scripts.ScalaScript_sc

You can also configure it manually with the config sub-command, by setting the interactive property to true.

$ scala-cli config interactive true

Added in #1238 by Gedochao

Other changes

Work in progress

Documentation

Build and internal changes

Updates

New Contributors

Full Changelog: https://github.com/VirtusLab/scala-cli/compare/v0.1.11...v0.1.12

v0.1.11

Make .scalafmt.conf optional when running the fmt command

Scala CLI can now run the fmt command without a .scalafmt.conf file present. Previously, if such a file was absent, a Scalafmt requires explicitly specified version. error was raised while using the fmt command.

The Scala CLI fmt command now supports passing the scalafmt version and dialect directly from the command line, using the --scalafmt-dialect and --scalafmt-version options respectively:

scala-cli fmt --scalafmt-dialect scala3 --scalafmt-version 3.5.8

Either of those (or both) can be skipped, which will make Scala CLI infer a default value.

The configuration used can be saved in the workspace by passing the --save-scalafmt-conf option.

Added in #1192 by wleczny

Define output option for package command with using directives

It is now possible to pass the output option of the package command with using directives instead of passing it directly from bash.

Added in #1213 by wleczny

Add support for running multiple snippets of the same kind

Scala CLI now allows to pass multiple snippets of the same kind.

It was previously possible to mix different kinds (so to pass a Java snippet alongside a Scala one), but not for example 2 separate Scala snippets. That limitation no longer applies.

When passed this way, each snippet is then treated as a separate input by Scala CLI.

$ scala-cli --scala-snippet '@main def main() = println(Messages.hello)' --scala-snippet 'object Messages { def hello = "Hello" }'
Hello

Added in #1182 by Gedochao

Add bloop sub-command

Scala CLI now has a (hidden for now) bloop sub-command, that runs a command using the Scala CLI Bloop server (while the mainline Bloop bloop CLI uses its default Bloop server). This is handy when debugging things on Scala CLI for example, allowing one to manually run scala-cli bloop projects or scala-cli bloop compile.

Added in #1199 by alexarchambault

Make main class optional in preamble-less assemblies

It is now allowed to generate an assembly, even for code that has no main class, when --preamble=false is passed. This can be useful for libraries, if users want to pass the assembly to tools such as proguard. This also accepts a (hidden) --main-class-in-manifest=false option if users want not only no preamble, but also no mention of main class in the assembly manifest (META-INF/MANIFEST.MF in the assembly JAR). The latter option is useful for tools, such as the hadoop jar command, that behave differently depending on the presence or not of a main class in the manifest.

Added in #1200 by alexarchambault

Important fixes & enhancements

Prevent erroneous using directives from blocking the initial run of BSP

Up till now, running the setup-ide sub-command on sources containing using directives with syntax errors or pointing to dependencies which could not be fetched would create a BSP setup which could not be imported correctly by IDEs. This is no longer the case and such a BSP connection should now import correctly, so that it's possible to fix the faulty code within the comfort of one's IDE of choice.

This fixes #1097

Added in #1195 by Gedochao

Work in progress

Allow to globally turn actionable diagnostics on or off

It is now possible to globally enable or disable actionable diagnostics using the config sub-command.

The relevant configuration is under the actions key.

$ scala-cli config actions true

Added in #1193 by lwronski

Other changes

Documentation

Build and internal changes

Updates

Full Changelog: https://github.com/VirtusLab/scala-cli/compare/v0.1.10...v0.1.11

v0.1.10

Initial support for importing other sources via using directives

It is now possible to add sources to a Scala CLI project from a source file, with using file directives:

//> using file "Other.scala"
//> using file "extra/"

Note that several sources can be specified in a single directive

//> using file "Other.scala" "extra/"

Added in #1157 by lwronski.

Add dependency update sub-command

Scala CLI can now update dependencies in user projects, using the dependency-update sub-command, like

scala-cli dependency-update --all .

When updates are available, this sub-command asks whether to update each of those, right where these dependencies are defined.

Added in #1055 by lwronski.

Running snippets passed as arguments

Scala CLI can now run Scala or Java code passed on the command-line, via -e / --script-snippet / --scala-snippet / --java-snippet:

$ scala-cli -e 'println("Hello")'
Hello

$ scala-cli --script-snippet 'println("Hello")'
Hello

$ scala-cli --scala-snippet '@main def run() = println("Hello")'
Hello

$ scala-cli --java-snippet 'public class Main { public static void main(String[] args) { System.out.println("Hello"); } }'
Hello

These options are meant to be substitutes to the -e option of the scala script that ships in scalac archives.

Added in #1166 by Gedochao.

Uninstall instructions and uninstall sub-command

Uninstalling Scala CLI is now documented in the main installation page, right after the installation instructions. In particular, when installed via the installation script, Scala CLI can be uninstalled via a newly added uninstall sub-command.

Added in #1122 and #1152 by wleczny.

Important fixes & enhancements

ES modules

Scala CLI now supports the ES Scala.js module kind, that can be enabled via a //> using jsModuleKind "esmodule" directive, allowing to import other ES modules in particular.

Added in #1142 by hugo-vrijswijk.

Putting Java options in assemblies, launchers, and docker images, in package sub-command

Passing --java-opt and --java-prop options to the package sub-command is now allowed. The passed options are hard-coded in the generated assemblies or launchers, and in docker images.

Added in #1167 by wleczny.

--command and --scratch-dir options in run sub-command

The run sub-command can now print the command it would have run, rather than running it. This can be useful for debugging purposes, or if users want to manually tweak commands right before they are run. Pass --command to run to enable it. This prints one argument per line, for easier automated processing:

$ scala-cli run --command -e 'println("Hello")' --runner=false
~/Library/Caches/Coursier/arc/https/github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.2%252B8/OpenJDK17U-jdk_x64_mac_hotspot_17.0.2_8.tar.gz/jdk-17.0.2+8/Contents/Home/bin/java
-cp
~/Library/Caches/ScalaCli/virtual-projects/ee/project-3c6fdea1/.scala-build/project_ed4bea6d06_ed4bea6d06/classes/main:~/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala3-library_3/3.1.3/scala3-library_3-3.1.3.jar:~/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.8/scala-library-2.13.8.jar
snippet_sc

When run relies on temporary files (when Scala.js is used for example), one can pass a temporary directory via --scratch-dir, so that temporary files are kept even when scala-cli doesn't run anymore:

$ scala-cli run --command -e 'println("Hello")' --js --runner=false --scratch-dir ./tmp
node
./tmp/main1690571004533525773.js

Added in #1163 by by alexarchambault.

Don't put Scala CLI internal modules in packages

Scala CLI doesn't put anymore its stubs module and its "runner" module in generated packages, in the package sub-command.

Fixed in #1161 by alexarchambault.

Don't write preambles in generated assemblies in the package sub-command

Passing --preamble=false to scala-cli --power package --assembly makes it generate assemblies without a shell preamble. As a consequence, these assemblies cannot be made executable, but these look more like "standard" JARs, which is required in some contexts.

Fixed in #1161 by alexarchambault.

Don't put some dependencies in generated assemblies in the package sub-command

Some dependencies, alongside all their transitive dependencies, can be excluded from the generated assemblies. Pass --provided org:name to scala-cli --power package --assembly to remove a dependency, like

$ scala-cli --power package SparkJob.scala --assembly --provided org.apache.spark::spark-sql

Note that unlike "provided" dependencies in sbt, and compile-time dependencies in Mill, all transitive dependencies are excluded from the assembly. In the Spark example above, for example, as spark-sql depends on scala-library (the Scala standard library), the latter gets excluded from the assembly too (which works fine in the context of Spark jobs).

Fixed in #1161 by alexarchambault.

In progress

Experimental Spark capabilities

The package sub-command now accepts a --spark option, to generate assemblies for Spark jobs, ready to be passed to spark-submit. This option is hidden (not printed in scala-cli --power package --help, only in --help-full), and should be considered experimental.

See this document for more details about these experimental Spark features.

Added in #1086 by alexarchambault.

Other changes

Documentation

Build and internal changes

Updates

New Contributors

Full Changelog: https://github.com/VirtusLab/scala-cli/compare/v0.1.9...v0.1.10

v0.1.9

--list-main-classes for publish & package

publish and package sub-commands now support the --list-main-classes option, which allows to list all the available main classes. Previously it was only available in the run command.

Added in #1118 by Gedochao

Important fixes & enhancements

fmt options improvement

Added missing documentation on how to pass native scalafmt options in the fmt sub-command with the -F option.

$ scala-cli fmt -F --version
scalafmt 3.5.2

Additionally, a couple of scalafmt's native options received aliases in Scala CLI:

--respect-project-filters is an alias for -F --respect-project-filters. Because of the way sources are passed by Scala CLI to scalafmt under the hood, we now turn it on by default to respect any project.excludePaths settings in the user's .scalafmt.conf. It can be disabled by passing --respect-project-filters=false to revert to previous behaviour. This addresses #1121

--scalafmt-help is an alias for -F --help. It shows the --help output from scalafmt, which might prove as helpful reference when in need of using native scalafmt options with -F.

Added in #1135 by Gedochao

Include libsodium.dll on Windows

Static linking of libsodium in Windows launcher has been fixed. This addresses #1114

Added in #1115 by alexarchambault

Force interactive mode for update command

Interactive mode for update sub-command is now enabled by default.

Added in #1100 by lwronski

In progress

Better BSP support for Scala scripts

Other changes

Documentation PRs

Build and internal changes

Updates

Full Changelog: https://github.com/VirtusLab/scala-cli/compare/v0.1.8...v0.1.9

v0.1.8

--list-main-classes option for the run command

You can pass the option --list-main-classes to the run command to list all the available main classes, including scripts.

$ scala-cli . --list-main-classes
Hello scripts.AnotherScript_sc scripts.Script_sc

Added in #1095 by Gedochao

Add config command

The config sub-command allows to get and set various configuration values, intended for use by other Scala CLI sub-commands.

This feature has been added in preparation for the publish command, stay tuned for future announcements.

Added in #1056 by alexarchambault

Prioritise non-script main classes

When trying to run a directory containing scripts and just a single non-script main class, the non-script main class will now be prioritised and run by default.

$ scala-cli .
Running Hello. Also detected script main classes: scripts.AnotherScript_sc, scripts.Script_sc
You can run any one of them by passing option --main-class, i.e. --main-class scripts.AnotherScript_sc
All available main classes can always be listed by passing option --list-main-classes
Hello world

Changed in #1095 by Gedochao

Important bugfixes

Accept latest Scala versions despite stale Scala version listings in cache

Scala CLI uses version listings from Maven Central to check if a Scala version is valid. When new Scala versions are released, users could sometimes have stale version listings in their Coursier cache for a short period of time (the Coursier cache TTL, which is 24 hours by default). This prevented these users to use new Scala versions during that time. To work around that, Scala CLI now tries to re-download version listings when they don't have the requested Scala version. This addresses #1090

Fixed in #1096 by lwronski

Bloop now uses JAVA_HOME by default

Bloop should now pick up the JDK available in JAVA_HOME. It was formerly necessary to pass --bloop-jvm system explicitly. This addresses #1102

Fixed in #1084 by lwronski

The -coverage-out option now accepts relative paths

Scala CLI now correctly processes relative paths when passed to the -coverage-out option. Formerly, the scoverage.coverage file would not be properly generated when a relative path was passed. This addresses #1072

Fixed in #1080 by lwronski

Other changes

Documentation PRs

Fixes

  • Add suffix to project name which contains virtual files by lwronski in #1070

Build and internal changes

Full Changelog: https://github.com/VirtusLab/scala-cli/compare/v0.1.7...v0.1.8

Older versions

The release notes for all the past versions of Scala CLI can be viewed on our releases page on GitHub.