Installation and IDE Support

For all the examples in this documentation, there is a download link that provides a zip file containing the full example ready to use. These examples come with a ./mill script you can use to immediately begin working with the project, needing only a JVM installed globally

The best method of installing Mill is to just install a bootstrap script. This script can determine the best version to be used by a project (e.g. by reading a .mill-version or .config/mill-version file or a MILL_VERSION environment variable) and will use this exact Mill version. If the determined Mill version is not installed locally, it will be downloaded automatically.

IDE Support

Mill supports IntelliJ and VSCode, both via the standard Build Server Protocol

IntelliJ

To use Mill with IntelliJ, first ensure you have the free IntelliJ Scala Plugin installed. This is necessary as Mill build files are written in Scala, even if you are using it to build a Java project.

Once you have the plugin installed, you can use IntelliJ to open any project containing a Mill build.sc file, and IntelliJ will automatically load the Mill build. This will provide support both for your application code, as well as the code in the build.sc:

IntellijApp
IntellijBuild

If you make changes to your Mill build.sc, you can ask Intellij to load those updates by opening the "BSP" tab and clicking the "Refresh" button

IntellijRefresh

IntelliJ IDEA XML Support

Apart from using the Build Server Protocol, you can also generate IDEA project files directly with Mill. This is probably the preferred way if you work on polyglot projects and need support for other languages like Kotlin or AspectJ, which are currently not specifically configured over BSP.

To generate IntelliJ IDEA project files into .idea/, run:

./mill mill.idea.GenIdea/idea

This will generate the XML files IntelliJ uses to configure your project

.idea
.idea/scala_settings.xml
.idea/mill_modules
.idea/mill_modules/.iml
.idea/mill_modules/mill-build.iml
.idea/mill_modules/test.iml
.idea/libraries
.idea/libraries/mill_scalalib_2_13_0_11_10_jar.xml
...
.idea/workspace.xml
.idea/modules.xml
.idea/scala_compiler.xml
.idea/misc.xml

After the files are generated, you can open the folder in IntelliJ to load the project into your IDE. If you make changes to your Mill build.sc, you can update the project config those updates by running ./mill mill.idea.GenIdea/idea again.

VSCode

To use Mill with VSCode, first ensure you have the free Metals VSCode Scala language server installed. This is necessary as Mill build files are written in Scala, even if you are using it to build a Java project.

Once you have the language server installed, you can ask VSCode to open any folder containing a Mill build.sc file, and VSCode will ask you to import your Mill build. This will provide support both for your application code, as well as the code in the build.sc:

VSCodeApp
VSCodeBuild

If you make changes to your Mill build.sc, you can ask VSCode to load those updates by opening the "BSP" tab and clicking the "Refresh" button

VSCodeRefresh

Debugging IDE issues

In case things go wrong, it can be sometimes hard to find the cause. BSP is just a protocol, and as such, issues on the server side (the Mill BSP server) might not well propagated to the BSP client (your IDE).

For that reason Mill BSP server is writing a log file under .bsp/mill-bsp.stderr, where you can find various information about what’s going on. Its content should look familiar, as it contains regular Mill output accompanied by additional BSP client-server communication details.

You can increase the verbosity of that log file, when you run Mill with --debug at installation time (of the BSP discovery file).

mill --debug mill.bsp.BSP/install

BSP Gotchas: Mismatching JVM versions

A common issue for poor performance can be a mismatch of the JVMs. In such a case the Mill BSP server started by a BSP client like Metals is using a different JVM than mill is using when started from the command line. In such a scenario, every Mill invocation using the other JVM will inadvertently invalidate Mills target caches. This effectively leads to full reevaluation of all invoked Mill targets and appears as "bad performance".

To detect if this is the case,

  1. import the project in the BSP client.

  2. Wait until the BSP import process has finished.

  3. Then run mill __.compile in the terminal.

  4. Now watch the IDE, to see if the compile command invoked in the terminal has triggered compilation on the build server.

If this happens, you’re using different JVMs. Unfortunately, this is rather difficult to "defend" programmatically in Mill itself. It is an explicit design goal of Mill, that it should work in different environments. It is evident and likely unintentional that you have two conflicting local environments.

To fix this it’s required to find where this difference stems from. As a starting point,

  • Find out which JVM is used for Mill on the CLi. mill --version reports its JVM.

  • Search the .bsp/mill-bsp.stderr file for a line starting with "Updating Evaluator". It should contain all env variables (particularly JAVA_HOME) used by the BSP server.

Once you found and fixed that and the environments are the same, clean and restarting BSP should work as expected.

Bootstrap Scripts

Although the Mill example projects come with their own ./mill bootstrap script, you can also download it manually:

curl -L https://github.com/com-lihaoyi/mill/releases/download/0.11.11/0.11.11 > mill && chmod +x mill
echo 0.11.11 > .mill-version

Downloading a mill bootstrap script to the root of your project repository helps make it easier for new contributors to build your project, as they don’t have to install Mill before they can start. Anyone who wants to work with the project can simply use the ./mill script directly.

./mill --version
./mill __.compile # double underscore

In general, bootstrap scripts are the recommended way of installing Mill. Similar to ./gradlew or ./mvnw, the ./mill bootstrap script reduces the chance of errors due to the installed version of Mill being incompatible with the version expected by your build. In-project bootstrap scripts are also useful for running Mill in CI/CD, ensuring that your build server like Jenkins or Github Actions has the correct version of Mill present to build, compile or test your code.

millw

You can also use lefou/millw as a drop-in replacement for mill. This script is a bit more advanced, and supports running on all major platforms including MS Windows.

The script supports to following sources when determining the best Mill version to use:

  • MILL_VERSION environment variable

  • .mill-version file in the project directory

  • .config/mill-version file in the project directory

  • if non was defined so far, it can also check for the latest available version online

  • DEFAULT_MILL_VERSION environment variable

Using a system-wide installed millw is probably the robustest way to use Mill on any operating system. It also preserves support of rather old Mill versions next to recent ones, so that updating it or switching to millw initially should be a no-brainer.

You can also install it on Homebrew via homebrew-millw:

brew install lefou/millw/millw

Updating Mill

Typically, most Mill projects use a .mill-version file to configure what version to use. You can update the version specified in this file in order to change the version of Mill. The file path .config/mill-version is also supported. If neither is provided, the ./mill bootstrap script will use the DEFAULT_MILL_VERSION it has built in.

To choose a different Mill version on an ad-hoc basis, e.g. for experimentation, you can pass in a MILL_VERSION environment variable, e.g.

MILL_VERSION=0.5.0-3-4faefb mill __.compile

or

MILL_VERSION=0.5.0-3-4faefb ./mill __.compile

to override the Mill version manually. This takes precedence over the version specified in ./mill, .config/mill-version or .mill-version

Other installation methods

Of course, you can also use the package manager of your operating system or distribution. Please keep in mind, that all those solutions listed below are maintained outside of Mill and may not have the same features as the bootstrap scripts.

Some of the installations via package managers install a fixed version of Mill and do not support project-specific selection of the preferred Mill version. If you want to use the MILL_VERSION environment variable or need support for .mill-version or .config/mill-version files to control the actual used Mill version, please use a Bootstrap script instead.

OS X

Installation via homebrew:

brew install mill

Arch Linux

Arch Linux has an Extra package for mill:

pacman -S mill

FreeBSD

Installation via pkg(8):

pkg install mill

Gentoo Linux

emerge dev-java/mill-bin

Windows

To get started, download Mill from Github releases, and save it as mill.bat.

If you’re using Scoop you can install Mill via

scoop install mill

WSL / MSYS2 / Cycgin / Git-Bash

Mill also works on "sh" environments on Windows (e.g., MSYS2, Cygwin, Git-Bash, WSL); to get started, follow the instructions in the Manual section. Note that:

  • In some environments (such as WSL), Mill might have to be run without a server (using -i, --interactive, or --no-server.)

  • On Cygwin, run the following after downloading mill:

sed -i '0,/-cp "\$0"/{s/-cp "\$0"/-cp `cygpath -w "\$0"`/}; 0,/-cp "\$0"/{s/-cp "\$0"/-cp `cygpath -w "\$0"`/}' /usr/local/bin/mill

Docker

You can download and run a "Docker image containing OpenJDK, Scala and Mill" using

docker pull nightscape/scala-mill
docker run -it nightscape/scala-mill

Manual

To get started, download Mill and install it into your HOME ".local/bin" via the following curl/chmod command:

sh -c "curl -L https://github.com/com-lihaoyi/mill/releases/download/0.11.11/0.11.11 > ~/.local/bin/mill && chmod +x ~/.local/bin/mill"

Coursier (unsupported)

Installing mill via coursier or cs is currently not officially supported. There are various issues, especially with interactive mode.

Asdf (unsupported)

You can install and manage Mill via the Multiple Runtime Version Manager - asdf.

Support by asdf is currently possible by using the asdf-mill plugin:

Steps to install the mill plugin and Mill with asdf
---
asdf plugin add mill
asdf install mill latest
asdf global mill latest
---

Automatic Mill updates

If your project is hosted on GitHub, GitLab, or Bitbucket, you can use Scala Steward to automatically open a pull request to update your Mill version (in .mill-version or .config/mill-version file), whenever there is a newer version available.

Scala Steward can also scan your project dependencies and keep them up-to-date.

Development Releases

In case you want to try out the latest features and improvements that are currently in the main branch, unstable versions of Mill are available as binaries named #.#.#-n-hash linked to the latest tag.

The easiest way to use a development release is to use one of the Bootstrap Scripts, which support [_overriding_mill_versions] via an MILL_VERSION environment variable or a .mill-version or .config/mill-version file.