diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,9 @@
 # ChangeLog hie-bios
 
+## 2026-04-15 - 0.19.0
+
+* Pass --builddir to avoid clobbering dist-newstyle ([#503](https://github.com/haskell/hie-bios/pull/503))
+
 ## 2026-02-06 - 0.18.0
 
 * Adapt to OsPath change ([#493](https://github.com/haskell/hie-bios/pull/493))
diff --git a/hie-bios.cabal b/hie-bios.cabal
--- a/hie-bios.cabal
+++ b/hie-bios.cabal
@@ -1,8 +1,8 @@
 Cabal-Version:          2.2
 Name:                   hie-bios
-Version:                0.18.0
-Author:                 Matthew Pickering <matthewtpickering@gmail.com>
-Maintainer:             Matthew Pickering <matthewtpickering@gmail.com>
+Version:                0.19.0
+Author:                 Matthew Pickering <matthewtpickering@gmail.com>, Hannes Siebenhandl <fendor.haskell@gmail.com>
+Maintainer:             Hannes Siebenhandl <fendor.haskell@gmail.com>
 License:                BSD-3-Clause
 License-File:           LICENSE
 Homepage:               https://github.com/haskell/hie-bios
diff --git a/src/HIE/Bios/Cradle/Cabal.hs b/src/HIE/Bios/Cradle/Cabal.hs
--- a/src/HIE/Bios/Cradle/Cabal.hs
+++ b/src/HIE/Bios/Cradle/Cabal.hs
@@ -11,9 +11,11 @@
   withGhcWrapperTool,
   -- * Argument processing
   processCabalWrapperArgs,
-  -- * Exposed for tests
+  -- * Internals (exposed for tests)
   isCabalMultipleCompSupported,
-  )where
+  cabalBuildDir,
+  )
+  where
 
 import Data.Char (isSpace)
 import System.Exit
@@ -296,14 +298,21 @@
 
 cabalLoadFilesWithRepl :: LogAction IO (WithSeverity Log) -> CradleProjectConfig -> FilePath -> [String] -> CradleLoadResultT IO CreateProcess
 cabalLoadFilesWithRepl l projectFile workDir args = do
-  let cabalCommand = "v2-repl"
-
+  buildDir <- liftIO $ cabalBuildDir workDir
   newEnvironment <- liftIO Process.getCleanEnvironment
   wrapper_fp <- liftIO $ withReplWrapperTool l (proc "ghc") workDir
-  pure (proc "cabal" ([cabalCommand, "--keep-temp-files", "--with-repl", wrapper_fp] <> projectFileProcessArgs projectFile <> args))
-    { env = Just newEnvironment
-    , cwd = Just workDir
-    }
+  let
+    cabalCommand = "v2-repl"
+    cabalArgs =
+      -- Don't clobber the user's 'dist-newstyle': pass --builddir (#501)
+        [ "--builddir=" <> buildDir
+        , cabalCommand, "--keep-temp-files", "--with-repl", wrapper_fp
+        ] <> projectFileProcessArgs projectFile <> args
+  pure $
+    (proc "cabal" cabalArgs)
+      { env = Just newEnvironment
+      , cwd = Just workDir
+      }
 
 -- | @'cabalCradleDependencies' projectFile rootDir componentDir@.
 -- Compute the dependencies of the cabal cradle based
@@ -617,8 +626,10 @@
   isCabalPathSupported vs >>= \case
     False -> pure Nothing
     True -> do
+      buildDir <- liftIO $ cabalBuildDir workDir
       let
-        args = ["path", "--output-format=json"] <> projectFileProcessArgs projectFile
+        args = [ "--builddir=" <> buildDir, "path", "--output-format=json" ]
+            <> projectFileProcessArgs projectFile
         bs = BS.fromStrict . T.encodeUtf8 . T.pack
         parse_compiler_path = Aeson.parseEither ((.: "compiler") >=>  (.: "path")) <=< Aeson.eitherDecode
 
diff --git a/tests/BiosTests.hs b/tests/BiosTests.hs
--- a/tests/BiosTests.hs
+++ b/tests/BiosTests.hs
@@ -11,10 +11,12 @@
 import Test.Tasty
 import Test.Tasty.HUnit
 import Test.Tasty.ExpectedFailure
-import qualified Test.Tasty.Options as Tasty
 import qualified Test.Tasty.Ingredients as Tasty
+import qualified Test.Tasty.Options     as Tasty
+import qualified Test.Tasty.Runners     as Tasty
 import HIE.Bios
 import HIE.Bios.Cradle
+import HIE.Bios.Cradle.Cabal (cabalBuildDir)
 import Control.Monad (forM_)
 import Control.Monad.Extra (unlessM)
 import Control.Monad.IO.Class
@@ -65,6 +67,10 @@
   extraGhcDep <- checkToolIsAvailable extraGhc
 
   defaultMainWithIngredients (ignoreToolTests:verboseLogging:defaultIngredients) $
+    -- Run tests sequentially on Windows, to avoid issues with locking of the
+    -- package database, e.g. errors of the form:
+    --   package.db/package.cache.lock: openBinaryFile: resource busy (file is locked)
+    (if isWindows then localOption (Tasty.NumThreads 1) else id) $
     testGroup "Bios-tests"
       [ testGroup "Find cradle" findCradleTests
       , testGroup "Symlink" symbolicLinkTests
@@ -186,6 +192,20 @@
           return ()
   , biosTestCase "simple-cabal" $ runTestEnv "./simple-cabal" $ do
       testDirectoryM isCabalCradle "B.hs"
+  , biosTestCase "build-dir" $ runTestEnv "./simple-cabal" $ do
+      initCradle "B.hs"
+      assertCradle isCabalCradle
+      root <- askRoot
+      buildDir <- liftIO $ cabalBuildDir root
+      -- use --multi-repl, as that was the codepath with the bug
+      loadFileGhcMultiStyle "B.hs" []
+      liftIO $ do
+        -- Check we aren't trampling over dist-newstyle
+        distNewstyleExists <- doesDirectoryExist (root </> "dist-newstyle")
+        assertBool "dist-newstyle was created" (not distNewstyleExists)
+        -- Check we are using the correct build directory
+        buildDirExists <- doesDirectoryExist buildDir
+        assertBool "build dir does not exist" buildDirExists
   , biosTestCase "nested-cabal" $ runTestEnv "./nested-cabal" $ do
       cabalAttemptLoad "sub-comp/Lib.hs"
       assertComponentOptions $ \opts -> do
