Installation and IDE Support

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.

Bootstrap Scripts

There are currently two bootstrap script available:

Using millw is recommended. We plan to merge both script in the future.

In general, bootstrap scripts are the recommended way of installing Mill, because they reduce the chance of errors due to the installed version of Mill being incompatible with the version expected by your build.

All bootstrap scripts can be installed globally and/or per project.

Global installation

After installing the script in a global or user-wide location, you can use it everywhere. If it detects project-specific configuration of the Mill version, it will download and use this exact version.

Project-specific installation

You can also add the script to your project as mill. This makes 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-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.

Mill’s in-repo Bootstrap Script (Linux/OS-X Only)

You can find this script in the root of the Mill repository, or on each release page. To get the latest version run the following command:

curl -L > mill && chmod +x mill

The mill command will automatically use the version specified by the bootstrap script, even if you installed it via other means. The ./mill file has a version number embedded within it, which you can update simply by editing the script.


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

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.


Installation via homebrew:

brew install mill

Arch Linux

Arch Linux has an Extra package for mill:

pacman -S mill


Installation via pkg(8):

pkg install mill

Gentoo Linux

emerge dev-java/mill-bin


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


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


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

sh -c "curl -L > ~/.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.

IDE Support

To support various IDEs and Language Servers, Mill supports the Build Server Protocol in version 2.2.0 and has a built-in BSP server.

In addition to BSP, Mill also supports IntelliJ IDEA project configuration generation directly.

Build Server Protocol (BSP)

The Build Server Protocol has the concept of BSP server discovery, which means: A BSP client can connect to any BSP server, as long as there is a connection file under the .bsp/ directory.

To install a BSP connection file .bsp/mill-bsp.json for Mill, run:

mill mill.bsp.BSP/install

Working known clients of the BSP server are IntelliJ IDEA and Metals.

You can fine control some BSP server options by specifying command options:



--jobs n

Use n threads in parallel to run tasks. A value of 0 means to use as many threads as the system has cpu cores.

Using Metals

When using Metals by default Bloop will be used as your build server unless you explicitly choose Mill. When in a Mill workspace use the "Switch Build Server" command from Metals which will allow you to switch to using Mill as your build server. If no .bsp/mill-bsp.json file exists, Metals will automatically create it for you and then connect to Mill.

Updating older setups

In the past, we provided SemanticDB support via mill.scalalib.bsp.ScalaMetalsSupport trait, which had to be mixed-in to your Scala modules. This is no longer needed and deprecated. You should remove these mix-ins. ScalaMetalsSupport trait is now deprecated and will be removed in the future.

If things go wrong

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.

Using Bloop (standalone BSP server)

If you wish to use Bloop as your build server (it is the default metals BSP implementation) with metals / vscode, consider using the mill bloop plugin.

This is preferred to the instructions (currently) on the bloop website.

Please be aware, that the Bloop contrib plugin is maintained by the community and is probably not on a par with the built-in BSP server.

IntelliJ IDEA Support

IntelliJ IDEA also supports the BSP protocol. To use this support, just follow the directions in Build Server Protocol (BSP).

Additionally, you can 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

Updating Mill

If you have installed Mill via the recommended Bootstrap Script method, you don’t need to install multiple version of Mill explicitly.

Follow the next Overriding Mill Versions section for details.

Overriding Mill Versions

Apart from downloading and installing new versions of Mill globally, there are a few ways of selecting/updating your Mill version. This will only work, if you have choosen one of the Boostrap script methods:

  • Create a .mill-version or .config/mill-version file to specify the version of Mill you wish to use:

echo "0.5.0" > .mill-version

.mill-version takes precedence over .config/mill-version or the version of Mill specified in the ./mill script.

  • Pass in a MILL_VERSION environment variable, e.g.

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


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

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.