sbt-typelevel configures sbt for developing, testing, cross-building, publishing, and documenting your Scala library on GitHub, with a focus on semantic versioning and binary compatibility. It is a collection of plugins that work well individually and even better together.



You can find an approximate list of sbt-typelevel adopters here, which includes all active Typelevel and http4s projects.

Quick start

sbt-typelevel Scala version support Discord

Giter8 Template

We provide a Giter8 template for quickly starting projects with familiar workflows and best practices.

sbt new typelevel/typelevel.g8

This will guide you through the basic setup to create a new project with sbt-typelevel and sbt-typelevel-site. Check out the typelevel.g8 project for more details.


Pick either the sbt-typelevel (recommended) or sbt-typelevel-ci-release plugin.


// Full service, batteries-included, let's go!
addSbtPlugin("org.typelevel" % "sbt-typelevel" % "0.6.7")

// Set me up for CI release, but don't touch my scalacOptions!
addSbtPlugin("org.typelevel" % "sbt-typelevel-ci-release" % "0.6.7")

// Optional. Make me a website!
addSbtPlugin("org.typelevel" % "sbt-typelevel-site" % "0.6.7")

sbt-typelevel-ci-release includes all the core features mentioned above.

sbt-typelevel extends sbt-typelevel-ci-release with:

  1. sbt-typelevel-settings: Good (and/or opinionated 😉) defaults for scalacOptions and friends. Note that you can also manually add this plugin to a project using sbt-typelevel-ci-release.
  2. Automated scalafmt and copyright header checks in CI.
  3. A prePR command and other nice-to-haves.

Configure Your Build


ThisBuild / tlBaseVersion := "0.4" // your current series x.y

ThisBuild / organization := "org.typelevel"
ThisBuild / organizationName := "Typelevel"
ThisBuild / startYear := Some(2024)
ThisBuild / licenses := Seq(License.Apache2)
ThisBuild / developers ++= List(
  // your GitHub handle and name
  tlGitHubDev("armanbilge", "Arman Bilge")

// false by default, set to true to publish to
ThisBuild / tlSonatypeUseLegacyHost := false

val Scala3 = "3.3.0"
ThisBuild / crossScalaVersions := Seq("2.13.11", Scala3)
ThisBuild / scalaVersion := Scala3 // the default Scala

lazy val root = tlCrossRootProject.aggregate(core, heffalump, tests)

lazy val core = crossProject(JVMPlatform, JSPlatform)
    name := "woozle-core",
    description := "Core data types and typeclasses",
    libraryDependencies += "org.typelevel" %%% "cats-core" % "2.9.0"

lazy val heffalump = project
    name := "woozle-heffalump",
    description := "Integration module with heffalump (JVM only)",
    libraryDependencies += "org.100aker" %% "heffalump-core" % "0.8.21"

lazy val tests = crossProject(JVMPlatform, JSPlatform)
    name := "woozle-tests",
    libraryDependencies += "org.scalacheck" %%% "scalacheck" % "1.17.0" % Test

Configure GitHub Actions

Run githubWorkflowGenerate in sbt to automatically generate the GitHub Actions workflows. This will create a CI matrix parallelized on Scala version and target platform (JVM, JS, etc.) and includes steps for running tests and checking binary compatibility. It will also setup a job for publishing tagged releases e.g. v0.4.5 and snapshots to Sonatype/Maven.

Finally, on GitHub set the following secrets on your repository:

Please see the Secrets page for more information and detailed instructions.