IDEs

This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production.

The reference material consulted while preparing these pages is listed in the section bibliography.

This page is written against Scala 3.10.0 (released 2026-10-12, the current Scala Next line) on JDK 26, with Metals 1.6.9 as the latest server listed in its documentation on 2026-10-15 and the IntelliJ IDEA 2026.2 documentation. The graphical tools themselves (VS Code, IntelliJ IDEA) were not run here: this section runs its examples with command-line tools, so the menus and settings below are quoted from the official documentation and are labelled accordingly. The one thing that could be run, the file that Scala CLI writes for an IDE, was run and is shown. Both IDE families support Scala 3.10 and the 3.9 LTS line; Metals supports Scala 3 versions from 3.3.4 automatically.

You do not need an IDE to write Scala: the command line tools of Scala CLI and sbt are enough for everything in this section, and Scastie runs code in a browser (see REPL, Worksheets & Scastie). But anything beyond exercises is easier with completion, go-to-definition, refactoring and a debugger. The official page "Scala IDEs" lists two main options, IntelliJ IDEA with the Scala plugin and Visual Studio Code with Metals, plus Metals in other editors. For Java developers, the equivalent comparison is on Java Getting Started.

The two families and how they differ

IntelliJ IDEA + Scala plugin Visual Studio Code (or another editor) + Metals

What it is

A full IDE from JetBrains; the Scala plugin is developed at JetBrains.

A language server (LSP) built on Scalameta; the editor is only a client.

Compiler feedback

Aimed at "a solid integrated experience, sane default settings, and tested solutions", in the words of the Scala documentation.

Aimed at people who "like to get feedback and code intelligence straight from the compiler", which lets them try experimental Scala features, according to the Scala documentation.

Build integration

Imports sbt projects, or uses its own IntelliJ build system; supports BSP for Scala CLI projects.

Builds are imported through the Build Server Protocol and the Bloop build server; sbt, Mill, Maven, Gradle, Bloop and Bazel are supported.

Typical pick

You want an integrated IDE with defaults that work out of the box.

You want compiler feedback in a lighter editor of your choice (Metals also has an online IDE page).

The summary above restates the Scala documentation’s own description of the two tools.

Visual Studio Code with Metals

Installation. Install the Metals extension from the Visual Studio Marketplace (or from the extensions view in VS Code), then open a directory that contains Scala code. The extension activates when the directory has a build.sbt or build.sc, when a Scala file (a .scala, .sbt or .sc file) is opened, or when a standard src/main/scala layout is detected. Metals needs a JDK to run its server (the minimum is 11, and the extension’s own setting defaults to 17; if none is found it downloads one with Coursier) and uses the JDK in JAVA_HOME to build the project. The project’s JDK must be at least as new as the server’s. For Scala 3.10 the project JDK must be 17 or later.

Importing the build. The first time you open a workspace Metals prompts "Import build". For sbt, Mill, Maven and Gradle it runs the build tool once to export the project to Bloop, a Scala build server with fast incremental compilation, and then compiles the open files. You do not need Bloop installed for this. If you click "Don’t show again" remove the .metals/ directory to bring the prompt back. When you change build.sbt or files under project/ Metals asks to re-import; you can trigger it any time from the command palette with "Metals: Import build". The import can take from seconds (a small cached build) to ten minutes or more (a large build that downloads dependencies for the first time); tail -f .metals/metals.log shows the progress.

Run Doctor. The command "Metals: Run Doctor" helps troubleshoot configuration problems in the workspace, and it is also how you check the build target names that a debug configuration needs (for an sbt project they are the project ids, with -test appended for test sources).

Files to keep out of git. Metals writes .metals/ (logs and indexes), .bloop/ (Bloop’s compilation data), .scala-build/ (when Scala CLI scripts are used) and project/metals.sbt (the file that adds the Bloop plugin to an sbt build). Add them to .gitignore:

.metals/
.bloop/
.scala-build/
metals.sbt

Settings you will touch. Settings such as "Java Home", "Sbt Script" (point to your own sbt script when you need environment variables, since the default embedded launcher respects .sbtopts and .jvmopts but not SBT_OPTS), "Custom Repositories" for a private artifact server and the server properties for an HTTP proxy are described in the Metals documentation under VS Code and User Configuration. Proxy settings go into a .jvmopts file, as -Dhttps.proxyHost and -Dhttps.proxyPort.

Running and debugging. Metals runs and debugs main methods and tests with the Debug Adapter Protocol (DAP), and Bloop starts the process. There are four ways to start a session:

  • the Test Explorer, VS Code’s testing view, which lists test suites by module and runs or debugs them, with per-test detection for JUnit, MUnit, ScalaTest and Weaver Test;

  • code lenses, the run | debug and test | test debug links above a main or test class (they accept no arguments);

  • a .vscode/launch.json configuration with "type": "scala" (see below);

  • Metals commands that can be bound to shortcuts: metals.run-current-file, metals.test-current-file and metals.test-current-target.

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "scala",
      "request": "launch",
      "name": "Launch Main",
      "mainClass": "hike",
      "args": [],
      "jvmOptions": []
    },
    {
      "type": "scala",
      "request": "launch",
      "name": "Launch Test",
      "testClass": "TrailSuite"
    }
  ]
}

The configuration is the documented shape with the class names of the trailhead example (the hike and TrailSuite classes of the sbt page). It was not run here, because it needs VS Code. To pass environment variables or JVM options to tests, use a .jvmopts file (-X options are filtered out of it) or a .test-jvmopts file for test-only options.

Worksheets. A worksheet is a Scala file named with the suffix .worksheet.sc that Metals evaluates when you save, showing each result as an inlay hint at the end of its line (hover to see a long value in full). Everything may be at the top level, with no wrapping object. Put the file next to your sources if it should see the project’s classes; elsewhere it sees only the standard library and its own dependencies. Dependencies come from Scala CLI directives, for example //> using dep com.lihaoyi::scalatags:0.7.0, and compiler options from //> using options. Worksheets are evaluated with mdoc, which has limitations (for example, a class that extends AnyVal cannot be defined in a worksheet). A file like this:

//> using scala 3.10.0
//> using dep com.lihaoyi::os-lib:0.11.8

val km = List(4.2, 9.5)
km.sum
os.pwd.last

is evaluated by Metals on save, with the value of each expression shown as an inlay hint. If you run the same file with scala run Trail.worksheet.sc instead, it executes without printing anything, since a script prints only what it asks to, and it reports a harmless warning about the file name, because the dot in Trail.worksheet.sc becomes part of a generated object name:

-- [E230] Syntax Warning: .scala-build/.../src_generated/main/Trail.worksheet.scala:17:7
17 |object Trail$u002Eworksheet_sc {
   |       ^^^^^^^^^^^^^^^^^^^^^^^
   |The identifier `Trail$u002Eworksheet_sc` should not contain `$`, which is reserved for internal compiler use.
   |
   | longer explanation available when compiling with `-explain`
1 warning found

This is the real output of the run. The worksheet inlay hints themselves were not run here.

Creating a project. The command "Metals: New Scala project" is the equivalent of sbt new: it lists Giter8 templates (and lets you type any organization/repo of GitHub), asks for a folder and a name, and creates the project.

Other editors with Metals

Metals is an LSP server, so it works with any LSP client. The Scala documentation names Emacs, Vim, Sublime Text and Helix next to VS Code. The Metals feature table marks most features as supported in all of them, with a few gaps per editor, and the installation is a single click everywhere except Helix, where it is manual. Each editor has its own page: Vim, Sublime Text, Emacs and Helix, and there is also a page for online IDEs. What they share:

  • the same server, the same "import build" step and the same Doctor, started in the directory that holds build.sbt;

  • the same user configuration keys (javaHome, sbtScript, scalafmtConfigPath, and so on), which each editor’s client passes as "metals" settings;

  • the same build tools: sbt, Maven, Gradle and Mill are imported through Bloop, and Bazel and Bloop projects directly.

The Build Server Protocol

Both Metals and IntelliJ talk to builds through the Build Server Protocol (BSP), the build-tool counterpart of the Language Server Protocol: the build tool runs as a server that answers "what are the modules, sources and classpaths?" and "compile this target", so an editor needs one integration for every build tool that speaks BSP, instead of one per tool. Metals imports sbt through Bloop, which is a BSP server; any tool that implements BSP can be integrated, as Metals' documentation for new build tools describes.

Scala CLI is a BSP server too. It does not rely on the editor to find it. Instead it writes a connection details file that the BSP specification calls build server discovery. Run scala setup-ide . (or just run compile, run or test; they do it first) and look at the directory:

scala setup-ide .
ls -a
Wrote configuration file for ide in: ./.bsp/scala.json
.            ..           .bsp         .scala-build Trailhead.scala
{
  "name": "scala",
  "argv": ["<scala runner>", "bsp", "..."],
  "version": "1.17.1",
  "bspVersion": "2.1.1",
  "languages": ["scala", "java"]
}

(The argv array holds the command line that the IDE starts, with the machine-specific paths replaced by placeholders.) Scala CLI 1.17.1 wrote .bsp/scala.json; its documentation still says .bsp/scala-cli.json, and IDEs read the connection file they find in the .bsp directory. The file .scala-build/ide-options-v2.json next to it stores the options (Scala version, extra arguments) that the BSP server uses; the other ide-*.json files in .scala-build keep inputs and environment variables. By default Scala CLI saves the options of the last compile, run or test, so that the IDE builds what you last built; after you run setup-ide yourself, that automatic update stops until you delete .bsp and run compile again.

For a Scala CLI project, open the directory in the IDE, not a single file; an IDE shows every file below the folder, but the build includes only the files Scala CLI was given. To add a file, add it to the Scala CLI command (scala setup-ide dir/A.scala dir/B.scala) or use //> using file, or better make the directory the project.

IntelliJ IDEA with the Scala plugin

Installation. Install IntelliJ IDEA (the Scala site recommends the Community edition unless you already use Ultimate; IntelliJ’s own documentation for the Scala plugin is part of IDEA’s help), then add the Scala plugin: open Settings (Ctrl+Alt+S), choose Plugins, open the Marketplace tab, find "Scala" and click Install. The plugin has a stable channel and, optionally, an Early Access Program and a Nightly Builds channel in Settings under Languages & Frameworks and Scala, on the Updates tab.

Creating a project. File, New, Project, choose Scala on the left. You pick a build system and a JDK:

  • IntelliJ: IDEA’s native builder, which needs no extra downloads, and a Scala SDK (create one from the long list of versions found on Ivy, Maven and Coursier servers, or point to one on disk);

  • sbt: choose an sbt version and a Scala version from the lists; IDEA generates a build.sbt with that Scala version and sbt downloads the compiler.

For a Scala 3 project the wizard offers "Use significant indentation syntax (Optional Braces)", which you can change later in Settings, Editor, Code Style, Scala. You can also open an existing project with File, Open (point to the directory containing build.sbt), import from existing sources, or check a project out from version control. IntelliJ’s documentation covers sbt support on its own page. A project that Scala CLI manages can be opened too; the Scala CLI cookbook has recipes for a simple project, for a Scala CLI project beside an sbt one, and for several Scala CLI projects as separate modules.

Running and worksheets. The Scala tutorial creates @main def hello(): Unit = println("Hello, World!"), and you run it with "Run 'hello'" from the context menu of the method. A Scala worksheet (right-click src, New, Scala Worksheet) evaluates as you type and shows results in a pane on the right:

def square(x: Int): Int = x * x
square(2)

The pane shows res0: Int = 4. (Quoted from the tutorial; not run here.) In both IDEs the worksheet is a convenience for exploring an API, not a build artifact: do not depend on its output in CI.

Debugging. Scala compiles to JVM bytecode, so the JVM debugger of the IDE applies. The steps (breakpoints, the Debug action beside Run, stepping) and the Scala-specific evaluator settings are in the JetBrains documentation; this was not run here.

Metals or IntelliJ? Both work with sbt and Scala CLI projects. A pragmatic split that follows the Scala documentation: IntelliJ when you want an integrated IDE with sane defaults; Metals when you want the compiler’s own feedback or a lighter editor. You can install both and switch per project, since they use different state directories (.idea/ for IntelliJ, .metals/ and .bloop/ for Metals).

Tips that apply to every editor

  • Pin the Scala and sbt versions in the build, so that every editor and CI see the same compiler: scalaVersion in build.sbt and sbt.version in project/build.properties, or //> using scala in Scala CLI projects.

  • Run a build from the command line first. If sbt compile fails, the IDE import will too, and the sbt output is easier to read than the import log.

  • If the editor shows errors that the command line does not, re-import the build, then use the Doctor (Metals), and as a last resort delete .bloop/, .metals/ or .idea/ and import again.

  • Keep generated directories out of version control (.metals/, .bloop/, .bsp/, .scala-build/, .idea/, target/).

  • Format with Scalafmt from the editor or with scala fmt; both read .scalafmt.conf. The Metals option scalafmtConfigPath points to a configuration file in a non-default place.

Where the books are outdated

  • Material from the Scala 2 era recommends the Eclipse-based Scala IDE or ENSIME. Neither is maintained; the current options are the ones on this page.

  • Older Metals instructions describe installing Bloop yourself. Today the VS Code extension handles the server and the build import, and the documentation says you do not need Bloop installed on your machine.

  • Tutorials may tell you to choose the IntelliJ build system and "Create" a Scala SDK; for a real project prefer sbt as the build system, so that the version lives in the build file and not in the IDE.