Single command Scala setup
You can now set up your machine for Scala development with a single command via the coursier CLI:
$ cs setup
This command ensures that both a JVM and the most common Scala CLI tools are installed on your machine.
cs is distributed as a native application without any external dependencies.
As such, it can be run immediately after download and thus provides a very
simple and convenient way to set up one's machine for Scala development.
In this post, we're going to have a closer look at:
- what
cs setupdoes in more detail - the lower level commands that back
cs setup, that are also useful on their own:cs javacs launchcs bootstrapcs install
We'll see that these lower level commands can do what
cs setup does, but in a more fine-grained fashion.
We'll also see that their features can be used independently of each other, allowing to
- install some applications with coursier, but keeping managing JVMs however you'd like, or
- manage some JVMs with coursier, while installing applications another way.
We'll also see that these commands can be used without actually installing or setting up anything: getting JVMs or application details only via the coursier CLI, without touching any profile file or global environment variable. This allows to get a quick peek at the coursier CLI features while not installing anything proper — everything stays in the coursier cache, that you can remove entirely any time you'd like.
Table of contents
setup command
Getting the coursier launcher and run setup
On Linux and macOS, download the coursier CLI, and run it with:
$ curl -fLo cs https://git.io/coursier-cli-"$(uname | tr LD ld)"
$ chmod +x cs
$ ./cs setup
$ rm -f cs
On Windows,
you can download cs.exe from your browser,
and double-click it to open a terminal, where cs setup will run.
Upon a successful run of cs setup, cs is available in the PATH (see below).
The downloaded launcher can be safely removed.
What happens when setup runs
cs setup asks for confirmation prior to do anything. If neither a JVM nor the usual Scala applications
are installed, and you press Enter every time it asks for confirmation, it should print something like this:
$ cs setup
Checking if a JVM is installed
No JVM found, should we try to install one? [Y/n]
Extracting
/home/user/.cache/coursier/v1/https/github.com/AdoptOpenJDK/openjdk8-binaries/releases/download/jdk8u252-b09/OpenJDK8U-jdk_x64_linux_hotspot_8u252b09.tar.gz
in
/home/user/.cache/coursier/jvm/adopt@1.8.0-252
Done
Should we update ~/.profile? [Y/n]
Some shell configuration files were updated. It is recommended to close this terminal once the setup command is done, and open a new one for the changes to be taken into account.
Checking if ~/.local/share/coursier/bin is in PATH
Should we add ~/.local/share/coursier/bin to your PATH via ~/.profile? [Y/n]
Checking if the standard Scala applications are installed
Installed ammonite
Installed cs
Installed coursier
Installed scala
Installed scalac
Installed sbt
Installed scalafmt
On Linux and macOS, it edits profile files in your home directory.
On Windows, it updates the so-called User environment variables, that you can also access by via Control Panel > Advanced system settings > Environment Variables.
The JVM archive is unpacked in a subdirectory of the managed JVM directory, which depends on your OS:
| OS | Managed JVM directory |
|---|---|
| Linux | ~/.cache/coursier/jvm |
| macOS | ~/Library/Caches/Coursier/jvm |
| Windows | C:\Users\_username_\AppData\Local\Coursier\Cache\jvm
(%LOCALAPPDATA%\Coursier\Cache\jvm in the general case) |
If cs setup installs a JVM, it sets JAVA_HOME and appends $JAVA_HOME/bin to the PATH.
Applications are installed in the installation directory, which is:
| OS | Application directory |
|---|---|
| Linux | ~/.local/share/coursier/bin |
| macOS | ~/Library/Application Support/Coursier/bin |
| Windows | C:\Users\_username_\AppData\Local\Coursier\data\bin
(%LOCALAPPDATA%\Coursier\data\bin in the general case) |
If cs setup installs applications, it appends this directory to the PATH.
Overall, cs setup wraps together new JVM and application handling capabilities of the coursier CLI.
These can be used in a more fine grained fashion, or assembled together differently if you wish. Let's
dive into those!
Managing JVMs
The java command of coursier can be called with cs java.
It backs how cs setup handles JVMs.
The cs java command itself aims at being a drop-in and more featureful replacement for java.
cs java simply runs the java executable:
$ java -version
openjdk version "1.8.0_252"
OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_252-b09)
OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.252-b09, mixed mode)
$ cs java -version
openjdk version "1.8.0_252"
OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_252-b09)
OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.252-b09, mixed mode)
If a JVM is already available on your system, calling cs java is equivalent to just calling
the already installed java.
If no JVM is found, cs java transparently downloads and unpacks the latest Adopt OpenJDK 8, and calls its java executable.
That way, cs java works even when no JVM is installed and a java executable is not in your PATH:
$ java -version
bash: java: command not found
$ cs java -version
Downloading https://github.com/shyiko/jabba/raw/master/index.json
Downloaded https://github.com/shyiko/jabba/raw/master/index.json
Downloading https://github.com/AdoptOpenJDK/openjdk8-binaries/releases/download/jdk8u252-b09/OpenJDK8U-jdk_x64_linux_hotspot_8u252b09.tar.gz
Downloaded https://github.com/AdoptOpenJDK/openjdk8-binaries/releases/download/jdk8u252-b09/OpenJDK8U-jdk_x64_linux_hotspot_8u252b09.tar.gz
Extracting
~/.cache/coursier/v1/https/github.com/AdoptOpenJDK/openjdk8-binaries/releases/download/jdk8u252-b09/OpenJDK8U-jdk_x64_linux_hotspot_8u252b09.tar.gz
in
~/.cache/coursier/jvm/adopt@1.8.0-252
Done
openjdk version "1.8.0_252"
OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_252-b09)
OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.252-b09, mixed mode)
$ cs java -version
openjdk version "1.8.0_252"
OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_252-b09)
OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.252-b09, mixed mode)
See explicit JVM below to download and use a different JVM.
The java command parses its arguments the following way: it processes arguments as long as
it recognizes options it handles itself, and stops at the first unrecognized argument. All arguments
from the first non-recognized one are passed as is to the java executable.
cs java --help prints a list of the arguments accepted by the cs java command. In the command above,
-version is not recognized as an option of cs java. -version, and any argument that would be passed
after it, is thus passed as is to the java executable. If cs java encounters -- as argument,
all the remaining arguments are passed to java:
$ cs java -- -version
openjdk version "1.8.0_252"
OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_252-b09)
OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.252-b09, mixed mode)
Compared to other JVM managers, cs java works equally well on Linux, macOS, and
Windows. It doesn't need any other CLI tool to be installed.
On Windows, it does not require WSL or Git BASH to work well.
It can also be used alongside other JVM managers.
We'll see that cs java doesn't require a
JVM installation step, unlike other JVM managers – JVMs are transparently downloaded and unpacked. It
also accepts more user-friendly JVM names, allowing to pick JVMs
without even listing its JVM index.
Managed JVM directory
JVM archives are unpacked in subdirectories of the managed JVM directory, mentioned above too, which is
| OS | Managed JVM directory |
|---|---|
| Linux | ~/.cache/coursier/jvm |
| macOS | ~/Library/Caches/Coursier/jvm |
| Windows | C:\Users\_username_\AppData\Local\Coursier\Cache\jvm
(%LOCALAPPDATA%\Coursier\Cache\jvm in the general case) |
In the example above, Adopt OpenJDK 1.8.0-252 on Linux would be unpacked under
~/.cache/coursier/jvm/adopt@1.8.0-252
Explicit JVM
You can pass a custom JVM name with --jvm, like
$ cs java --jvm graalvm-ce-java11:19 -version
openjdk version "11.0.7" 2020-04-14
OpenJDK Runtime Environment GraalVM CE 19.3.2 (build 11.0.7+10-jvmci-19.3-b10)
OpenJDK 64-Bit Server VM GraalVM CE 19.3.2 (build 11.0.7+10-jvmci-19.3-b10, mixed mode, sharing)
$ cs java --jvm 14 -version
openjdk version "14.0.1" 2020-04-14
OpenJDK Runtime Environment AdoptOpenJDK (build 14.0.1+7)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 14.0.1+7, mixed mode, sharing)
To know which JVMs are available for the current system, pass --available to cs java, like
$ cs java --available
adopt:1.8.0-172
adopt:1.8.0-181
adopt:1.8.0-192
adopt:1.8.0-202
adopt:1.8.0-212
…
To list the JVMs already unpacked on your system, pass --installed, like
$ cs java --installed
adopt:1.8.0-252
adopt:1.9.0-0
adopt:1.10.0-2
adopt:1.11.0-7
adopt:1.13.0-2
adopt:1.14.0-1
graalvm:19.3.2
graalvm:20.1.0
graalvm-ce-java11:19.3.2
openjdk:1.14.0
zulu:1.7.262
Note that if no exact match is found for the version passed to --jvm, a + is appended to the version, so that we
get a version interval, and the highest version in the interval is picked. That way, graalvm:19 is accepted,
and matches graalvm:19.3.2 as of writing this.
Also note that 1. is prepended to the version
when it makes sense, so that the 1. in the output of --available and --installed can be ignored most of the time. For example, openjdk:14 is equivalent to openjdk:1.14.
Lastly, note that if no JVM type is passed, only a version, like --jvm 1.14.0-1, Adopt OpenJDK is used (JVM
type: adopt). This can be used in conjunction with the automatic version interval expansion above, as well as
the automatic handling of the 1. prefix, so that things like --jvm 14 are valid (and expanded
to adopt:1.14.0-1 as of writing this), like
$ cs java --jvm 14 -version
openjdk version "14.0.1" 2020-04-14
OpenJDK Runtime Environment AdoptOpenJDK (build 14.0.1+7)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 14.0.1+7, mixed mode, sharing)
Set up a JVM for the current shell session
(Only for Linux and macOS.)
Pass --env to cs java to print a shell snippet setting up a JVM:
$ cs java --jvm 14 --env
export CS_FORMER_JAVA_HOME="$JAVA_HOME"
export JAVA_HOME="/home/user/.cache/coursier/jvm/adopt@1.14.0-1"
export PATH="/home/user/.cache/coursier/jvm/adopt@1.14.0-1/bin:$PATH"
Eval it to set up a JVM in the current session:
$ eval "$(cs java --jvm 14 --env)"
$ java -version
openjdk version "14.0.1" 2020-04-14
OpenJDK Runtime Environment AdoptOpenJDK (build 14.0.1+7)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 14.0.1+7, mixed mode, sharing)
Set up a JVM for the current user
Pass --setup to cs java to update profile files (on Linux and macOS) or user
environment variables (on Windows):
$ cs java --jvm 14 --setup
Checking if ~/.profile need(s) updating.
Some shell configuration files were updated. It is recommended to close this terminal once the setup command is done, and open a new one for the changes to be taken into account.
$ source ~/.profile
$ java -version
openjdk version "14.0.1" 2020-04-14
OpenJDK Runtime Environment AdoptOpenJDK (build 14.0.1+7)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 14.0.1+7, mixed mode, sharing)
This installs a JVM on your system just like cs setup would have.
JVM index
To know where to download JVMs, the java command currently uses
the JVM index
of jabba, another JVM manager.
For each OS / CPU, this index lists available JVMs, their available versions,
and where to download them. For example, for
Linux on AMD64, Adopt OpenJDK 1.8.0-252
can be downloaded at
https://github.com/AdoptOpenJDK/openjdk8-binaries/releases/download/jdk8u252-b09/OpenJDK8U-jdk_x64_linux_hotspot_8u252b09.tar.gz
The coursier CLI downloads the JVM archives via its cache, so that on Linux, this archive would be downloaded in
~/.cache/coursier/v1/https/github.com/AdoptOpenJDK/openjdk8-binaries/releases/download/jdk8u252-b09/OpenJDK8U-jdk_x64_linux_hotspot_8u252b09.tar.gz
On Linux, it would then be unpacked under
~/.cache/coursier/jvm/adopt@1.8.0-252
The JVM index of jabba lists numerous JVMs, like AdoptOpenJDK, OpenJDK, Zulu, etc.
It does so for Linux / macOS / Windows, targeting various architectures
(amd64, aarch64, etc.). See cs java --available to list all currently available JVMs
on your system.
Managing applications
Launching applications
The launch command can start some applications with just their name, like
$ cs launch scala
Welcome to Scala 2.13.3 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_121).
Type in expressions for evaluation. Or try :help.
scala>
You can optionally pass a version, like
$ cs launch scala:2.12.11
Welcome to Scala 2.12.11 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_121).
Type in expressions for evaluation. Or try :help.
scala>
Note that nothing is actually "installed" when launching applications this way: the relevant application index and JARs are fetched via the coursier cache if needed, and the right set of JARs from the coursier cache is loaded and run, to start the application.
Channels
Applications are defined in "channels". Channels define lists of applications that can be launched. Some channel types are versioned, while the content of others is simply overridden and newer data gets pulled upon updates.
The default channel sources live
at this address. It pushes artifacts
here, so that its Maven coordinates
are io.get-coursier:apps. As a Maven-based channel, the content of this channel is versioned.
When looking for an application, the coursier CLI downloads the latest version of io.get-coursier:apps.
It looks inside its JAR for "application descriptors". Application descriptors are JSON files that
look like
this:
{
"repositories": [
"central"
],
"dependencies": [
"org.scala-lang:scala-compiler:latest.stable"
],
"mainClass": "scala.tools.nsc.MainGenericRunner",
"properties": {
"scala.usejavacp": "true"
}
}
Application descriptors specify which repositories should be used (here, central, for Maven Central), which
dependencies should be pulled (here, org.scala-lang:scala-compiler:latest.stable).
Some other optional parameters
can be specified, like the main class to launch, or Java properties to set before launching the app, etc.
The README of the default application channel contains a list of applications available in this channel.
Adding applications to the contrib channel
The contrib channel, whose sources live here, accepts any application available from public repositories. Feel free to submit applications there by opening a pull request, adding new application descriptors.
Users can then use your application by specifying the --contrib option, like
$ cs launch --contrib proguard
$ cs install --contrib proguard
Creating your own channels
The coursier website briefly describes how to create and use your own channels. There is also a giter8 model to create a repository for such a channel.
Creating launchers for applications
Unlike cs launch which starts an application straightaway,
cs bootstrap creates launchers starting applications, like
$ cs bootstrap scala -o scala
$ ./scala
By default, the generated launchers are very small (around 28 kB as of writing this).
These launchers are tiny Java applications, with a minimal coursier cache logic.
Upon start-up, this Java application ensures that all the relevant JARs are available in the
coursier cache, and starts the actual application (here, scala) from those JARs. The
cs bootstrap documentation describes
these launchers in more detail, and lists the other kinds of launcher that cs bootstrap
can generate, such as "uber JARs", or GraalVM native images, among others.
Installing launchers for applications
The install command creates and installs launchers for applications. Use it like
$ cs install scala
$ scala
Launchers are installed in the installation directory mentioned above, which is
| OS | Application directory |
|---|---|
| Linux | ~/.local/share/coursier/bin |
| macOS | ~/Library/Application Support/Coursier/bin |
| Windows | C:\Users\_username_\AppData\Local\Coursier\data\bin
(%LOCALAPPDATA%\Coursier\data\bin in the general case) |
You can pass a custom installation directory with --install-dir,
or by setting COURSIER_INSTALL_DIR in the environment, like
$ cs install --install-dir /usr/local/bin scala
$ which scala
/usr/local/bin/scala
$ export COURSIER_INSTALL_DIR=/usr/local/bin
$ cs install ammonite
$ which amm
/usr/local/bin/amm
The launchers installed by cs install are very similar to the ones
created by cs bootstrap. These are JARs too.
cs install writes additional metadata in those JARs, mentioning the channel
the application originates from, including the channel version, and the list of
URLs the JARs of the application are downloaded from, along with their checksums. This allows to
update applications later on.
Updating launchers
The update command can update launchers, checking for new / updated
- channel data,
- application artifacts.
$ cs update scala
Updated scala
If you installed applications in a custom directory, pass that directory with
--install-dir, or via COURSIER_INSTALL_DIR in the environment, like for install above.
Removing launchers
The uninstall command removes an installed launcher, like
$ cs uninstall scala
Uninstalled scala
If you installed applications in a custom directory, pass that directory with
--install-dir, or via COURSIER_INSTALL_DIR in the environment, like for install above.
Wrapping things together
Manual setup
A few invocations of the cs java and cs install commands allow to effectively
do the same as the cs setup command.
You can ensure a JVM is available, just like the cs setup command, with
$ cs java --setup
If a JVM is already installed on your system, this command does nothing. If no JVM is found, the following happens:
- the latest AdoptOpenJDK 8 is unpacked in the managed JVM directory (mentioned above),
- profile files or user environment variables are updated so that
JAVA_HOMEis set, andPATHcontains$JAVA_HOME/bin.
You can then ensure the application directory is in your PATH with
$ cs install --setup
Lastly, you can install a few scala applications in the installation directory with
$ cs install scala sbt ammonite scalafmt cs
Using applications and JVMs without installing them
The launch command accepts a --jvm option, specifying a JVM to use. Use it like
$ cs launch ammonite --jvm 14
Loading...
Welcome to the Ammonite Repl 2.1.4-12-f697522 (Scala 2.13.3 Java 14.0.1)
@
This transparently downloads and unpacks a JVM in the managed JVM directory, and starts the application with it.
The --scala option can come in handy too:
$ cs launch ammonite --scala 2.12 --jvm 14
Loading...
Welcome to the Ammonite Repl 2.1.4-11-307f3d8 (Scala 2.12.12 Java 14.0.1)
@
Alternatively to --jvm, you can just set up a JVM for the current shell
session, then call launch:
$ eval "$(cs java --env --jvm 14)"
$ cs launch ammonite
Loading...
Welcome to the Ammonite Repl 2.1.4-12-f697522 (Scala 2.13.3 Java 14.0.1)
@
Final words
cs setup, alongside cs java and cs install, makes it easier to setup
one's machine for Scala development, taking care of managing both JVMs and applications,
and works on all major OSs (Linux, macOS, Windows).
It also offers a way for JVM application developers to distribute their applications.
On top of that, it can install, or build if necessary, native applications, like GraalVM native-image launchers, or Scala Native-based ones, which are beyond the scope of this post.
Don't hesitate to ask questions on its Gitter channel, open issues on its GitHub repository, or contribute to it or ask for guidance for it.
Allow me to finish with giving a big thanks to the Scala Center without whose support most of the features described in this post would still be unimplemented! The Scala Center made the development of the Coursier CLI possible through a combination of direct employment and contracting of myself (Alexandre Archambault).
Many thanks to the numerous contributors that contributed code to coursier, but also bug reports, or simply support to its users or authors.
I'd also like to give a big thanks to Martijn Hoekstra, Jamal CHAQOURI, Przemek Pokrywka, nachinius, Ghislain Antony Vaillant, Eric Loots, and Mark T. Kennedy, who proof-read this post and suggested many improvements.
Addendum
Other cs commands
cs has other commands, such as cs complete, cs resolve, and cs fetch, that come in handy
when working with Maven / Ivy dependencies.
cs complete allows to complete Maven coordinates:
$ cs complete org.apache.pdfbox:
…
pdfbox-examples
pdfbox-lucene
pdfbox-parent
…
$ cs complete org.apache.pdfbox:pdfbox-lucene:
…
1.8.14
1.8.15
1.8.16
cs resolve lists transitive dependencies:
$ cs resolve org.apache.pdfbox:pdfbox-lucene:1.8.16
commons-logging:commons-logging:1.1.1:default
org.apache.lucene:lucene-core:2.4.1:default
org.apache.lucene:lucene-demos:2.4.1:default
org.apache.pdfbox:fontbox:1.8.16:default
org.apache.pdfbox:jempbox:1.8.16:default
org.apache.pdfbox:pdfbox:1.8.16:default
org.apache.pdfbox:pdfbox-lucene:1.8.16:default
These dependencies can optionally be printed as a tree, with the --tree or -t option:
$ cs resolve -t org.apache.pdfbox:pdfbox-lucene:1.8.16
Result:
└─ org.apache.pdfbox:pdfbox-lucene:1.8.16
├─ org.apache.lucene:lucene-core:2.4.1
├─ org.apache.lucene:lucene-demos:2.4.1
│ └─ org.apache.lucene:lucene-core:2.4.1
└─ org.apache.pdfbox:pdfbox:1.8.16
├─ commons-logging:commons-logging:1.1.1
├─ org.apache.pdfbox:fontbox:1.8.16
│ └─ commons-logging:commons-logging:1.1.1
└─ org.apache.pdfbox:jempbox:1.8.16
cs fetch fetches artifacts, JARs in most cases:
$ cs fetch org.apache.pdfbox:pdfbox-lucene:1.8.16
~/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/apache/pdfbox/pdfbox-lucene/1.8.16/pdfbox-lucene-1.8.16.jar
~/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/apache/pdfbox/pdfbox/1.8.16/pdfbox-1.8.16.jar
~/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/apache/lucene/lucene-core/2.4.1/lucene-core-2.4.1.jar
~/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/apache/lucene/lucene-demos/2.4.1/lucene-demos-2.4.1.jar
~/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/apache/pdfbox/fontbox/1.8.16/fontbox-1.8.16.jar
~/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/apache/pdfbox/jempbox/1.8.16/jempbox-1.8.16.jar
~/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/commons-logging/commons-logging/1.1.1/commons-logging-1.1.1.jar
The --classpath or -p option makes it print artifacts in a way that can be passed to java -cp:
$ cs fetch -p org.apache.pdfbox:pdfbox-lucene:1.8.16
~/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/apache/pdfbox/pdfbox-lucene/1.8.16/pdfbox-lucene-1.8.16.jar:~/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/apache/pdfbox/pdfbox/1.8.16/pdfbox-1.8.16.jar:…
Things that are not applications
The launch and bootstrap commands were originally written to launch applications from
their Maven coordinates, like
$ cs launch com.lihaoyi:::ammonite:2.0.4 -M ammonite.Main
$ cs bootstrap org.scalameta::scalafmt-cli:2.6.3 -o scalafmt
Application descriptors allow to gather the dependencies and parameters passed to these commands.
Note that you can add dependencies alongside an application. The following starts sqlline with the PostgreSQL JDBC driver, allowing to connect to a PostgreSQL database:
$ cs launch sqlline org.postgresql:postgresql:42.2.14 -- \
-u jdbc:postgresql://localhost/postgres -n postgres -p mysecretpassword
sqlline version 1.9.0
0: jdbc:postgresql://localhost/postgres> select 1;
+----------+
| ?column? |
+----------+
| 1 |
+----------+
1 row selected (0.007 seconds)
Reverting cs setup
Pass --try-revert to cs setup to revert what it installed:
$ cs setup --try-revert
Warning: the --try-revert option is experimental. Keep going only if you know what you are doing. [y/N] y
JVM system|adopt@1.8+ was not installed
JVM system|adopt@1.8+ not setup
Removed /Users/alexandre/Library/Application Support/Coursier/bin from PATH in ~/.profile, ~/.zprofile, ~/.bash_profile
Uninstalled amm
Uninstalled cs
Uninstalled coursier
Uninstalled scala
Uninstalled scalac
Uninstalled sbt
Uninstalled scalafmt
Beware that --try-revert also removes things that were manually set up, not
only what was install by a cs setup run.