diff --git a/hix.cabal b/hix.cabal
--- a/hix.cabal
+++ b/hix.cabal
@@ -1,11 +1,11 @@
 cabal-version: 2.2
 
--- This file has been generated from package.yaml by hpack version 0.36.0.
+-- This file has been generated from package.yaml by hpack version 0.36.1.
 --
 -- see: https://github.com/sol/hpack
 
 name:           hix
-version:        0.7.2
+version:        0.8.0
 synopsis:       Haskell/Nix development build tools
 description:    See https://hackage.haskell.org/package/hix/docs/Hix.html
 category:       Build
@@ -13,7 +13,7 @@
 bug-reports:    https://github.com/tek/hix/issues
 author:         Torsten Schmits
 maintainer:     hackage@tryp.io
-copyright:      2023 Torsten Schmits
+copyright:      2025 Torsten Schmits
 license:        BSD-2-Clause-Patent
 license-file:   LICENSE
 build-type:     Simple
@@ -242,7 +242,7 @@
     , casing >=0.1.4 && <0.2
     , containers
     , exceptions ==0.10.*
-    , exon >=1.4 && <1.7
+    , exon >=1.4 && <1.8
     , extra ==1.7.*
     , filepattern ==0.1.*
     , generic-lens ==2.2.*
@@ -250,8 +250,8 @@
     , http-client ==0.7.*
     , http-client-tls ==0.3.*
     , http-types ==0.12.*
-    , incipit-base ==0.5.*
-    , lens >=5.1 && <5.3
+    , incipit-base >=0.5 && <0.7
+    , lens >=5.1 && <5.4
     , lens-regex-pcre ==1.1.*
     , optparse-applicative >=0.17 && <0.19
     , path ==0.9.*
@@ -314,7 +314,7 @@
   build-depends:
       base ==4.*
     , hix
-    , incipit-base ==0.5.*
+    , incipit-base >=0.5 && <0.7
   mixins:
       base hiding (Prelude)
     , incipit-base (IncipitBase as Prelude)
@@ -397,11 +397,11 @@
       Cabal
     , aeson >=2.0 && <2.3
     , base ==4.*
-    , exon >=1.4 && <1.7
+    , exon >=1.4 && <1.8
     , extra ==1.7.*
     , hedgehog >=1.1 && <1.5
     , hix
-    , incipit-base ==0.5.*
+    , incipit-base >=0.5 && <0.7
     , path ==0.9.*
     , path-io >=1.7 && <1.9
     , tasty ==1.4.*
diff --git a/lib/Hix.hs b/lib/Hix.hs
--- a/lib/Hix.hs
+++ b/lib/Hix.hs
@@ -1,5 +1,7 @@
 module Hix where
 
+import System.Exit (exitFailure)
+
 import Hix.Bootstrap (bootstrapProject)
 import qualified Hix.Console as Console
 import Hix.Console (errorMessage)
@@ -61,7 +63,12 @@
     LowerStabilizeCmd opts -> lowerStabilizeCli opts
     LowerAutoCmd opts -> lowerAutoCli opts
 
+failure :: Bool -> Error -> IO ()
+failure verbose err = do
+  printError verbose err
+  exitFailure
+
 main :: IO ()
 main = do
   Options global cmd <- parseCli
-  leftA (printError global.verbose) =<< runMWith global (runCommand cmd)
+  leftA (failure global.verbose) =<< runMWith global (runCommand cmd)
diff --git a/lib/Hix/Bootstrap.hs b/lib/Hix/Bootstrap.hs
--- a/lib/Hix/Bootstrap.hs
+++ b/lib/Hix/Bootstrap.hs
@@ -1,3 +1,5 @@
+{-# language CPP #-}
+
 module Hix.Bootstrap where
 
 import Control.Monad.Trans.Class (lift)
@@ -39,6 +41,10 @@
 import qualified Hix.Prelude
 import Hix.Prelude (Prelude, findPrelude)
 
+#if MIN_VERSION_Cabal(3,14,0)
+import Distribution.Utils.Path (makeSymbolicPath)
+#endif
+
 data CabalInfo =
   CabalInfo {
     path :: Path Rel Dir,
@@ -87,7 +93,11 @@
   Path Rel File ->
   M CabalInfo
 readCabal cwd path = do
+#if MIN_VERSION_Cabal(3,14,0)
+  info <- liftIO (readGenericPackageDescription Cabal.verbose Nothing (makeSymbolicPath (toFilePath (cwd </> path))))
+#else
   info <- liftIO (readGenericPackageDescription Cabal.verbose (toFilePath (cwd </> path)))
+#endif
   pure CabalInfo {path = dir, info}
   where
     dir = parent path
diff --git a/lib/Hix/Cabal.hs b/lib/Hix/Cabal.hs
--- a/lib/Hix/Cabal.hs
+++ b/lib/Hix/Cabal.hs
@@ -1,3 +1,5 @@
+{-# language CPP #-}
+
 module Hix.Cabal where
 
 import Control.Monad.Trans.Except (ExceptT (ExceptT), throwE)
@@ -32,6 +34,10 @@
 import Hix.Data.Error (Error (..))
 import Hix.Error (pathText, sourceError)
 
+#if MIN_VERSION_Cabal(3,14,0)
+import Distribution.Utils.Path (makeSymbolicPath)
+#endif
+
 noMatch :: Text -> Path b File -> ExceptT Error IO a
 noMatch reason source =
   throwE (NoMatch (sourceError reason source))
@@ -71,7 +77,11 @@
 parseCabal :: Path Abs File -> ExceptT Error IO GenericPackageDescription
 parseCabal path =
   ExceptT $ fmap (first (PreprocError . show)) $ tryIOError do
+#if MIN_VERSION_Cabal(3,14,0)
+    readGenericPackageDescription Cabal.verbose Nothing (makeSymbolicPath (toFilePath path))
+#else
     readGenericPackageDescription Cabal.verbose (toFilePath path)
+#endif
 
 buildInfo ::
   (a -> BuildInfo) ->
diff --git a/lib/Hix/Managed/Cabal/Init.hs b/lib/Hix/Managed/Cabal/Init.hs
--- a/lib/Hix/Managed/Cabal/Init.hs
+++ b/lib/Hix/Managed/Cabal/Init.hs
@@ -1,3 +1,5 @@
+{-# language CPP #-}
+
 module Hix.Managed.Cabal.Init where
 
 import Distribution.Client.Config (defaultCacheDir)
@@ -18,6 +20,10 @@
 import Hix.Managed.Cabal.Repo (ensureHackageIndex)
 import Hix.Monad (M, throwM, tryIOMWith)
 
+#if MIN_VERSION_Cabal(3,14,0)
+import Distribution.Simple.Setup (CommonSetupFlags (..))
+#endif
+
 data SolveFlags =
   SolveFlags {
     global :: GlobalFlags,
@@ -62,12 +68,26 @@
   where
     basic = defaultNixStyleFlags ()
 
+
+#if MIN_VERSION_Cabal(3,14,0)
     configFlags =
+      configDef {
+        configHcPath = pathFlag [relfile|ghc|],
+        configHcPkg = pathFlag [relfile|ghc-pkg|],
+        configCommonFlags = configDef.configCommonFlags {
+          setupVerbosity = toFlag conf.verbosity
+        }
+      }
+
+    configDef = defaultConfigFlags defaultProgramDb
+#else
+    configFlags =
       (defaultConfigFlags defaultProgramDb) {
         configHcPath = pathFlag [relfile|ghc|],
         configHcPkg = pathFlag [relfile|ghc-pkg|],
         configVerbosity = toFlag conf.verbosity
       }
+#endif
 
     pathFlag exe = maybeToFlag (ghcPath exe <$> conf.ghc)
 
diff --git a/lib/Hix/Managed/Cabal/Mock.hs b/lib/Hix/Managed/Cabal/Mock.hs
--- a/lib/Hix/Managed/Cabal/Mock.hs
+++ b/lib/Hix/Managed/Cabal/Mock.hs
@@ -1,12 +1,12 @@
+{-# language CPP #-}
+
 module Hix.Managed.Cabal.Mock where
 
 import Distribution.Simple (buildCompilerId, unknownCompilerInfo)
 import Distribution.Simple.Compiler (AbiTag (NoAbiTag))
-import Distribution.Solver.Types.PkgConfigDb (PkgConfigDb (NoPkgConfigDb))
+import Distribution.Solver.Types.PkgConfigDb (PkgConfigDb (..))
 import Distribution.System (Arch (X86_64), OS (Linux), Platform (Platform))
 
-import Hix.Managed.Data.ManagedPackage (ManagedPackage)
-import Hix.Managed.Data.Packages (Packages)
 import qualified Hix.Managed.Cabal.Data.Packages
 import Hix.Managed.Cabal.Data.Packages (GhcPackages (GhcPackages))
 import qualified Hix.Managed.Cabal.Data.SolveResources
@@ -15,6 +15,8 @@
 import Hix.Managed.Cabal.Mock.InstalledPackage (mockInstalledPackageIndex)
 import qualified Hix.Managed.Cabal.Mock.SourcePackage as SourcePackage
 import Hix.Managed.Cabal.Mock.SourcePackage (mockSourcePackageDb)
+import Hix.Managed.Data.ManagedPackage (ManagedPackage)
+import Hix.Managed.Data.Packages (Packages)
 
 mockSolveResources ::
   Packages ManagedPackage ->
@@ -26,7 +28,11 @@
     flags = emptySolveFlags,
     platform = Platform X86_64 Linux,
     compiler = unknownCompilerInfo buildCompilerId NoAbiTag,
+#if MIN_VERSION_Cabal(3,14,0)
+    pkgConfigDb = PkgConfigDb mempty,
+#else
     pkgConfigDb = NoPkgConfigDb,
+#endif
     installedPkgIndex = mockInstalledPackageIndex installed,
     sourcePkgDb = SourcePackage.dbWithManaged packages (mockSourcePackageDb available),
     solverParams = id
diff --git a/lib/Hix/Managed/Cabal/Repo.hs b/lib/Hix/Managed/Cabal/Repo.hs
--- a/lib/Hix/Managed/Cabal/Repo.hs
+++ b/lib/Hix/Managed/Cabal/Repo.hs
@@ -1,3 +1,5 @@
+{-# language CPP #-}
+
 module Hix.Managed.Cabal.Repo where
 
 import Data.Time (
@@ -35,6 +37,10 @@
 import Hix.Monad (M, catchIOM, eitherFatalShow, noteFatal, tryIOM, tryIOMWith, withLower)
 import Hix.Pretty (showP)
 
+#if MIN_VERSION_Cabal(3,14,0)
+import Distribution.Client.IndexUtils (Index (RepoIndex))
+#endif
+
 withRepoContextM ::
   SolveConfig ->
   GlobalFlags ->
@@ -119,7 +125,11 @@
   Repo ->
   M (Maybe HackageIndexState)
 currentIndexState verbosity ctx repo =
+#if MIN_VERSION_Cabal(3,14,0)
+  catchIOM (Just . HackageIndexState <$> currentIndexTimestamp verbosity (RepoIndex ctx repo)) (const (pure Nothing))
+#else
   catchIOM (Just . HackageIndexState <$> currentIndexTimestamp verbosity ctx repo) (const (pure Nothing))
+#endif
 
 indexProblem ::
   SolveConfig ->
diff --git a/lib/Hix/Managed/Cabal/Resources.hs b/lib/Hix/Managed/Cabal/Resources.hs
--- a/lib/Hix/Managed/Cabal/Resources.hs
+++ b/lib/Hix/Managed/Cabal/Resources.hs
@@ -1,10 +1,12 @@
+{-# language CPP #-}
+
 module Hix.Managed.Cabal.Resources where
 
 import Control.Monad.Trans.Reader (asks)
 import Distribution.Client.IndexUtils (getInstalledPackages, getSourcePackages)
 import qualified Distribution.Client.NixStyleOptions
 import Distribution.Client.Setup (configCompilerAux', withRepoContext)
-import Distribution.Simple (PackageDB (GlobalPackageDB), PackageDBStack, compilerInfo)
+import Distribution.Simple (pattern GlobalPackageDB, compilerInfo)
 import Distribution.Solver.Types.PkgConfigDb (readPkgConfigDb)
 import Distribution.Verbosity (lessVerbose, silent, verbose)
 
@@ -22,7 +24,18 @@
 import Hix.Managed.Data.Packages (Packages)
 import Hix.Monad (tryIOM)
 
+#if MIN_VERSION_Cabal(3,14,0)
+import Distribution.Simple (PackageDBStackCWD)
+import Distribution.Solver.Types.PkgConfigDb (PkgConfigDb (..))
+#else
+import Distribution.Simple (PackageDBStack)
+#endif
+
+#if MIN_VERSION_Cabal(3,14,0)
+packageDbs :: PackageDBStackCWD
+#else
 packageDbs :: PackageDBStack
+#endif
 packageDbs = [GlobalPackageDB]
 
 -- | This adds the 'ManagedPackage's to the source package DB, which is the set of available package IDs.
@@ -54,6 +67,9 @@
       installedPkgIndex = installedPkgIndex,
       sourcePkgDb = SourcePackage.dbWithManaged packages sourcePkgDb,
       solverParams = id,
+#if MIN_VERSION_Cabal(3,14,0)
+      pkgConfigDb = fromMaybe (PkgConfigDb []) pkgConfigDb,
+#endif
       ..
     }
 
diff --git a/lib/Hix/Managed/Cabal/Solve.hs b/lib/Hix/Managed/Cabal/Solve.hs
--- a/lib/Hix/Managed/Cabal/Solve.hs
+++ b/lib/Hix/Managed/Cabal/Solve.hs
@@ -1,3 +1,5 @@
+{-# language CPP #-}
+
 module Hix.Managed.Cabal.Solve where
 
 import Distribution.Client.Dependency (
@@ -10,7 +12,6 @@
   setAllowBootLibInstalls,
   standardInstallPolicy,
   )
-import Distribution.Client.Dependency.Types (Solver (Modular))
 import Distribution.Client.SolverInstallPlan (SolverInstallPlan)
 import Distribution.Client.Types (UnresolvedSourcePackage)
 import Distribution.Simple.Utils (debugNoWrap)
@@ -31,6 +32,10 @@
 import Hix.Managed.Cabal.Targets (solveTargets)
 import Hix.Monad (M, tryIOMAs)
 
+#if ! MIN_VERSION_Cabal(3,14,0)
+import Distribution.Client.Dependency.Types (Solver (Modular))
+#endif
+
 newtype Unresolvable =
   Unresolvable Text
   deriving stock (Eq, Show, Generic)
@@ -48,7 +53,11 @@
   IO (Either String SolverInstallPlan)
 solveSpecifiers res mapParams pkgSpecifiers prefs =
   foldProgress (logMsg res.conf.verbosity) (pure . Left) (pure . Right) $
+#if MIN_VERSION_Cabal(3,14,0)
+  resolveDependencies res.platform res.compiler (Just res.pkgConfigDb) params
+#else
   resolveDependencies res.platform res.compiler res.pkgConfigDb Modular params
+#endif
   where
     params =
       mapParams $
diff --git a/lib/Hix/Options.hs b/lib/Hix/Options.hs
--- a/lib/Hix/Options.hs
+++ b/lib/Hix/Options.hs
@@ -5,6 +5,7 @@
   CommandFields,
   Mod,
   Parser,
+  ReadM,
   auto,
   bashCompleter,
   command,
@@ -31,7 +32,7 @@
   switch,
   value,
   )
-import Path (Abs, Dir, File, Path, parseRelDir, parseSomeDir)
+import Path (Abs, Dir, File, Path, SomeBase, parseRelDir, parseSomeDir)
 import Path.IO (getCurrentDir)
 import Prelude hiding (Mod, mod)
 
@@ -82,21 +83,33 @@
   JsonConfig,
   absDirOption,
   absFileOption,
+  absFileOrCwdOption,
   buildHandlersOption,
   indexStateOption,
   jsonOption,
   outputFormatOption,
   outputTargetOption,
   relFileOption,
+  someFileOption,
   )
 
 fileParser ::
+  ReadM a ->
   String ->
   String ->
-  Parser (Path Abs File)
-fileParser longName helpText =
-  option absFileOption (long longName <> completer (bashCompleter "file") <> help helpText)
+  Parser a
+fileParser readOption longName helpText =
+  option readOption (long longName <> completer (bashCompleter "file") <> help helpText)
 
+absFileParser :: String -> String -> Parser (Path Abs File)
+absFileParser = fileParser absFileOption
+
+absFileOrCwdParser :: Path Abs Dir -> String -> String -> Parser (Path Abs File)
+absFileOrCwdParser cwd = fileParser (absFileOrCwdOption cwd)
+
+someFileParser :: String -> String -> Parser (SomeBase File)
+someFileParser = fileParser someFileOption
+
 rootParser :: Parser (Maybe (Path Abs Dir))
 rootParser =
   optional (option absDirOption (long "root" <> help "The root directory of the project"))
@@ -106,19 +119,21 @@
 jsonConfigParser =
   option jsonOption (long "config" <> help "The Hix-generated config, file or text")
 
-preprocParser :: Parser PreprocOptions
-preprocParser =
+preprocParser ::
+  Path Abs Dir ->
+  Parser PreprocOptions
+preprocParser cwd =
   PreprocOptions
   <$>
   (fmap Right <$> optional jsonConfigParser)
   <*>
   rootParser
   <*>
-  fileParser "source" "The original source file"
+  absFileOrCwdParser cwd "source" "The original source file"
   <*>
-  fileParser "in" "The prepared input file"
+  absFileOrCwdParser cwd "in" "The prepared input file"
   <*>
-  fileParser "out" "The path to the output file"
+  absFileOrCwdParser cwd "out" "The path to the output file"
 
 packageSpecParser :: Parser (Maybe PackageSpec)
 packageSpecParser = do
@@ -140,15 +155,19 @@
   <*>
   componentSpecParser
 
-componentForFileParser :: Parser TargetSpec
-componentForFileParser =
+componentForFileParser ::
+  Path Abs Dir ->
+  Parser TargetSpec
+componentForFileParser cwd =
   TargetForFile
   <$>
-  option absFileOption (long "file" <> short 'f' <> help "The absolute file path of the test module")
+  option (absFileOrCwdOption cwd) (long "file" <> short 'f' <> help "The absolute file path of the test module")
 
-targetSpecParser :: Parser TargetSpec
-targetSpecParser =
-  componentForFileParser
+targetSpecParser ::
+  Path Abs Dir ->
+  Parser TargetSpec
+targetSpecParser cwd =
+  componentForFileParser cwd
   <|>
   TargetForComponent <$> componentCoordsParser
 
@@ -194,30 +213,36 @@
 extraGhcidParser =
   optional (strOption (long "ghcid-options" <> help "Additional command line options to pass to ghcid"))
 
-envParser :: Parser EnvRunnerCommandOptions
-envParser = do
+envParser ::
+  Path Abs Dir ->
+  Parser EnvRunnerCommandOptions
+envParser cwd = do
   options <- do
     config <- Right <$> jsonConfigParser
     root <- rootParser
-    component <- optional targetSpecParser
+    component <- optional (targetSpecParser cwd)
     pure EnvRunnerOptions {..}
   test <- testOptionsParser
   extraGhci <- extraGhciParser
   extraGhcid <- extraGhcidParser
   pure EnvRunnerCommandOptions {..}
 
-ghciParser :: Parser GhciOptions
-ghciParser = do
+ghciParser ::
+  Path Abs Dir ->
+  Parser GhciOptions
+ghciParser cwd = do
   config <- Right <$> jsonConfigParser
   root <- rootParser
-  component <- targetSpecParser
+  component <- targetSpecParser cwd
   test <- testOptionsParser
   extra <- extraGhciParser
   pure GhciOptions {..}
 
-ghcidParser :: Parser GhcidOptions
-ghcidParser = do
-  ghci <- ghciParser
+ghcidParser ::
+  Path Abs Dir ->
+  Parser GhcidOptions
+ghcidParser cwd = do
+  ghci <- ghciParser cwd
   extra <- extraGhcidParser
   pure GhcidOptions {..}
 
@@ -321,15 +346,17 @@
 managedGithubPrParser =
   option absFileOption (long "file" <> help "The JSON file written by a managed deps app")
 
-commands :: Mod CommandFields Command
-commands =
-  command "preproc" (Preproc <$> info preprocParser (progDesc "Preprocess a source file for use with ghcid"))
+commands ::
+  Path Abs Dir ->
+  Mod CommandFields Command
+commands cwd =
+  command "preproc" (Preproc <$> info (preprocParser cwd) (progDesc "Preprocess a source file for use with ghcid"))
   <>
-  command "env" (EnvRunner <$> info envParser (progDesc "Print the env runner for a component or a named env"))
+  command "env" (EnvRunner <$> info (envParser cwd) (progDesc "Print the env runner for a component or a named env"))
   <>
-  command "ghci-cmd" (GhciCmd <$> info ghciParser (progDesc "Print a ghci cmdline to load a module in a Hix env"))
+  command "ghci-cmd" (GhciCmd <$> info (ghciParser cwd) (progDesc "Print a ghci cmdline to load a module in a Hix env"))
   <>
-  command "ghcid-cmd" (GhcidCmd <$> info ghcidParser (progDesc "Print a ghcid cmdline to run a function in a Hix env"))
+  command "ghcid-cmd" (GhcidCmd <$> info (ghcidParser cwd) (progDesc "Print a ghcid cmdline to run a function in a Hix env"))
   <>
   command "new" (NewCmd <$> info newParser (progDesc "Create a new Hix project in the current directory"))
   <>
@@ -360,7 +387,7 @@
   Path Abs Dir ->
   Parser Options
 appParser cwd =
-  Options <$> globalParser cwd <*> hsubparser commands
+  Options <$> globalParser cwd <*> hsubparser (commands cwd)
 
 parseCli ::
   IO Options
diff --git a/lib/Hix/Optparse.hs b/lib/Hix/Optparse.hs
--- a/lib/Hix/Optparse.hs
+++ b/lib/Hix/Optparse.hs
@@ -5,7 +5,21 @@
 import Distribution.Parsec (eitherParsec)
 import Exon (exon)
 import Options.Applicative (ReadM, eitherReader)
-import Path (Abs, Dir, File, Path, Rel, parseAbsDir, parseAbsFile, parseRelDir, parseRelFile, toFilePath)
+import Path (
+  Abs,
+  Dir,
+  File,
+  Path,
+  Rel,
+  SomeBase (..),
+  parseAbsDir,
+  parseAbsFile,
+  parseRelDir,
+  parseRelFile,
+  parseSomeFile,
+  toFilePath,
+  (</>),
+  )
 import qualified Text.Show as Show
 
 import Hix.Data.OutputFormat (OutputFormat (..))
@@ -21,13 +35,32 @@
   eitherReader \ raw ->
     first (const [exon|not a valid #{desc} path: #{raw}|]) (parse raw)
 
+absPathOrCwdOption ::
+  String ->
+  (String -> Either e (SomeBase t)) ->
+  Path Abs Dir ->
+  ReadM (Path Abs t)
+absPathOrCwdOption desc parse cwd =
+  eitherReader \ raw ->
+    first (const [exon|not a valid #{desc} path: #{raw}|]) (parse raw) <&> \case
+      Abs p -> p
+      Rel p -> cwd </> p
+
 -- | An absolute file path option for @optparse-applicative@.
 absFileOption :: ReadM (Path Abs File)
 absFileOption = pathOption "absolute file" parseAbsFile
 
+-- | An absolute file path option for @optparse-applicative@.
+absFileOrCwdOption :: Path Abs Dir -> ReadM (Path Abs File)
+absFileOrCwdOption = absPathOrCwdOption "absolute or relative file" parseSomeFile
+
 -- | A relative file path option for @optparse-applicative@.
 relFileOption :: ReadM (Path Rel File)
 relFileOption = pathOption "relative file" parseRelFile
+
+-- | A file path option for @optparse-applicative@.
+someFileOption :: ReadM (SomeBase File)
+someFileOption = pathOption "some file" parseSomeFile
 
 -- | A relative dir path option for @optparse-applicative@.
 absDirOption :: ReadM (Path Abs Dir)
diff --git a/test/Hix/Test/GhciTest.hs b/test/Hix/Test/GhciTest.hs
--- a/test/Hix/Test/GhciTest.hs
+++ b/test/Hix/Test/GhciTest.hs
@@ -32,7 +32,8 @@
 import Hix.Env (envRunner)
 import Hix.Ghci (assemble, ghciCmdlineFromOptions, ghcidCmdlineFromOptions)
 import Hix.Monad (runM)
-import Hix.Test.Utils (UnitTest)
+import Hix.Test.Utils (UnitTest, unitTest)
+import Test.Tasty (TestTree, testGroup)
 
 root :: Path Abs Dir
 root =
@@ -213,3 +214,12 @@
 test_moduleName = do
   conf <- evalEither =<< liftIO (runM root (assemble options.ghci { component = spec4 }))
   target_moduleName === conf.script
+
+test_ghci :: TestTree
+test_ghci =
+  testGroup "ghci" [
+    unitTest "run ghcid" test_ghcid,
+    unitTest "main package" test_mainPackage,
+    unitTest "component env" test_componentEnv,
+    unitTest "extract module name from path" test_moduleName
+  ]
diff --git a/test/Main.hs b/test/Main.hs
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -4,7 +4,7 @@
 import Hix.Test.BootstrapTest (test_bootstrap)
 import Hix.Test.BoundsTest (test_bounds)
 import Hix.Test.CabalTest (test_cabal)
-import Hix.Test.GhciTest (test_componentEnv, test_ghcid, test_moduleName)
+import Hix.Test.GhciTest (test_ghci)
 import Hix.Test.ManagedTest (test_managed)
 import Hix.Test.NewTest (test_new)
 import Hix.Test.PreprocTest (
@@ -32,9 +32,7 @@
       unitTest "self exporting module, separate line" test_preprocSelfExport2,
       unitTest "self exporting module, separate line" test_preprocNoPrelude,
       unitTest "modules starting with 'Prelude'" test_preprocPreludePrefix,
-      unitTest "run ghcid" test_ghcid,
-      unitTest "component env" test_componentEnv,
-      unitTest "extract module name from path" test_moduleName,
+      test_ghci,
       unitTest "generate a project" test_new,
       unitTest "bootstrap a project" test_bootstrap
     ],
