An SBT plugin for fast development turnaround in Scala applications.
This is a Conduktor fork with additional features for AI-assisted development workflows.
- Start and stop your application in the background of your interactive SBT shell (forked JVM)
- Triggered restart: automatically restart when source files change (
~reStart) - Batched restart: debounced watch mode that waits for file changes to settle before restarting — ideal for tools like Claude Code that make multiple rapid changes (
reStartWatch)
Requires SBT 1.x. Add to project/plugins.sbt:
addSbtPlugin("io.conduktor" % "sbt-revolver" % "1.0.2")This requires access to Conduktor's GitHub Packages:
resolvers += "GitHub Packages" at "https://maven.pkg.github.com/conduktor/sbt-revolver"
credentials += Credentials(
"GitHub Package Registry",
"maven.pkg.github.com",
"_",
sys.env.getOrElse("GITHUB_TOKEN", "")
)sbt-revolver is an auto plugin — no additional configuration needed. In multi-module builds, disable for specific submodules with Project(...).disablePlugins(RevolverPlugin).
-
reStart <args> --- <jvmArgs>— Starts your application in a forked JVM. Optional arguments are appended toreStartArgs/reStart / javaOptions. Restarts if already running. -
reStop— Stops the application by killing the forked JVM. -
reStatus— Shows current running state.
sbt> ~reStart
Watches for source changes and automatically restarts. Press Enter to stop watching.
When using tools like Claude Code that make multiple rapid file changes, ~reStart triggers unnecessary restarts. Use reStartWatch instead:
sbt> reStartWatch # Watch current project
sbt> reStartWatch app # Watch specific project (multi-module builds)
Multi-module builds: reStartWatch watches source directories across the entire build (not just the target project), so changes in any dependency module trigger a restart.
This waits for the batch window (default: 3s) after the last file change before restarting.
Claude modifies file A → timer starts (3s)
Claude modifies file B → timer resets (3s)
Claude modifies file C → timer resets (3s)
Claude is done → 3s pass → single restart
Configure in build.sbt:
import scala.concurrent.duration._
reBatchWindow := 5.seconds // default: 3sPress q + Enter to stop.
| Setting | Type | Description |
|---|---|---|
reStartArgs |
Seq[String] |
Arguments passed to main method on every start |
reStart / mainClass |
Option[String] |
Main class (defaults to Compile / run / mainClass) |
reStart / javaOptions |
Seq[String] |
JVM options for the forked process |
reStart / baseDirectory |
File |
Working directory |
reStart / fullClasspath |
Classpath |
Classpath for running |
reStart / envVars |
Map[String, String] |
Environment variables |
reColors |
Seq[String] |
Colors for tagging output in multi-module projects |
reLogTag |
String |
Log tag prefix (default: project name) |
reBatchWindow |
FiniteDuration |
Debounce window for reStartWatch (default: 3s) |
// 2 GB memory limit
reStart / javaOptions += "-Xmx2g"
// Custom main class
reStart / mainClass := Some("com.example.Main")
// Fixed start arguments
reStartArgs := Seq("-x")
// Environment variables
reStart / envVars := Map("USER_TOKEN" -> "secret")
// Disable colors in multi-module
reColors := Revolver.noColors
// Longer batch window for slow tools
reBatchWindow := 10.secondsIn multi-module builds where you run reStartWatch app, configure the working directory so relative paths (like config files) resolve from the project root:
lazy val app = project
.settings(
// Both run and reStart should use project root as working directory
run / baseDirectory := (LocalRootProject / baseDirectory).value,
reStart / baseDirectory := (LocalRootProject / baseDirectory).value,
)Without this, the forked JVM's working directory is the subproject folder (modules/app/), causing relative paths like config/app.yml to fail.
Apache License 2.0