diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,6 +1,64 @@
 # Changelog
 
 
+## v2.7.1
+
+**Changes since v2.5.1.1:**
+
+Behavior changes:
+
+* `stack repl` now always warns about GHCi problems with loading multiple
+  packages. It also sets now proper working directory when invoked with
+  one package. See
+  [#5421](https://github.com/commercialhaskell/stack/issues/5421)
+
+* `custom-setup` dependencies are now properly initialized for `stack dist`.
+  This makes `explicit-setup-deps` no longer required and that option was
+  removed. See
+  [#4006](https://github.com/commercialhaskell/stack/issues/4006)
+
+Other enhancements:
+
+* Nix integration now passes `ghcVersion` (in addition to existing `ghc`) to
+  `shell-file` as an identifier that can be looked up in a compiler attribute set.
+
+* Nix integration now allows Nix integration if the user is ready in nix-shell.
+  This gets rid of "In Nix shell but reExecL is False" error.
+
+* `stack list` is a new command to list package versions in a snapshot.
+  See [#5431](https://github.com/commercialhaskell/stack/pull/5431)
+
+* Consider GHC 9.0 a tested compiler and remove warnings.
+
+* `custom-preprocessor-extensions` is a new configuration option for allowing
+  stack to be aware of any custom preprocessors you have added to `Setup.hs`.
+  See [#3491](https://github.com/commercialhaskell/stack/issues/3491)
+
+* Added `--candidate` flag to `upload` command to upload a package candidate
+  rather than publishing the package.
+
+* Error output using `--no-interleaved-output` no longer prepends indentating
+  whitespace. This allows emacs compilation-mode and vim quickfix to locate
+  and track errors. See
+  [#5523](https://github.com/commercialhaskell/stack/pull/5523)
+
+Bug fixes:
+
+* `stack new` now suppports branches other than `master` as default for
+  GitHub repositories. See
+  [#5422](https://github.com/commercialhaskell/stack/issues/5422)
+
+* Ignore all errors from `hi-file-parser`. See
+  [#5445](https://github.com/commercialhaskell/stack/issues/5445) and
+  [#5486](https://github.com/commercialhaskell/stack/issues/5486).
+
+* Support basic auth in package-indices. See
+  [#5509](https://github.com/commercialhaskell/stack/issues/5509).
+
+* Add support for parsing `.hi`. files from GHC 8.10 and 9.0. See
+  [hi-file-parser#2](https://github.com/commercialhaskell/hi-file-parser/pull/2).
+
+
 ## v2.5.1.1
 
 Hackage-only release:
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2015-2020, Stack contributors
+Copyright (c) 2015-2021, Stack contributors
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/doc/ChangeLog.md b/doc/ChangeLog.md
--- a/doc/ChangeLog.md
+++ b/doc/ChangeLog.md
@@ -1,6 +1,64 @@
 # Changelog
 
 
+## v2.7.1
+
+**Changes since v2.5.1.1:**
+
+Behavior changes:
+
+* `stack repl` now always warns about GHCi problems with loading multiple
+  packages. It also sets now proper working directory when invoked with
+  one package. See
+  [#5421](https://github.com/commercialhaskell/stack/issues/5421)
+
+* `custom-setup` dependencies are now properly initialized for `stack dist`.
+  This makes `explicit-setup-deps` no longer required and that option was
+  removed. See
+  [#4006](https://github.com/commercialhaskell/stack/issues/4006)
+
+Other enhancements:
+
+* Nix integration now passes `ghcVersion` (in addition to existing `ghc`) to
+  `shell-file` as an identifier that can be looked up in a compiler attribute set.
+
+* Nix integration now allows Nix integration if the user is ready in nix-shell.
+  This gets rid of "In Nix shell but reExecL is False" error.
+
+* `stack list` is a new command to list package versions in a snapshot.
+  See [#5431](https://github.com/commercialhaskell/stack/pull/5431)
+
+* Consider GHC 9.0 a tested compiler and remove warnings.
+
+* `custom-preprocessor-extensions` is a new configuration option for allowing
+  stack to be aware of any custom preprocessors you have added to `Setup.hs`.
+  See [#3491](https://github.com/commercialhaskell/stack/issues/3491)
+
+* Added `--candidate` flag to `upload` command to upload a package candidate
+  rather than publishing the package.
+
+* Error output using `--no-interleaved-output` no longer prepends indentating
+  whitespace. This allows emacs compilation-mode and vim quickfix to locate
+  and track errors. See
+  [#5523](https://github.com/commercialhaskell/stack/pull/5523)
+
+Bug fixes:
+
+* `stack new` now suppports branches other than `master` as default for
+  GitHub repositories. See
+  [#5422](https://github.com/commercialhaskell/stack/issues/5422)
+
+* Ignore all errors from `hi-file-parser`. See
+  [#5445](https://github.com/commercialhaskell/stack/issues/5445) and
+  [#5486](https://github.com/commercialhaskell/stack/issues/5486).
+
+* Support basic auth in package-indices. See
+  [#5509](https://github.com/commercialhaskell/stack/issues/5509).
+
+* Add support for parsing `.hi`. files from GHC 8.10 and 9.0. See
+  [hi-file-parser#2](https://github.com/commercialhaskell/hi-file-parser/pull/2).
+
+
 ## v2.5.1.1
 
 Hackage-only release:
diff --git a/doc/GUIDE.md b/doc/GUIDE.md
--- a/doc/GUIDE.md
+++ b/doc/GUIDE.md
@@ -450,7 +450,7 @@
 also known as *snapshots*. We mentioned the LTS resolvers, and you can get quite a bit of
 information about it at [https://www.stackage.org/lts](https://www.stackage.org/lts), including:
 
-* The appropriate resolver value (`resolver: lts-16.15`, as is currently the latest LTS)
+* The appropriate resolver value (`resolver: lts-17.9`, as is currently the latest LTS)
 * The GHC version used
 * A full list of all packages available in this snapshot
 * The ability to perform a Hoogle search on the packages in this snapshot
@@ -467,7 +467,7 @@
 
 ## Resolvers and changing your compiler version
 
-Let's explore package sets a bit further. Instead of lts-16.15, let's change our
+Let's explore package sets a bit further. Instead of lts-17.9, let's change our
 `stack.yaml` file to use [the latest nightly](https://www.stackage.org/nightly). Right now,
 this is currently 2020-03-24 - please see the resolve from the link above to get the latest.
 
@@ -483,8 +483,8 @@
 Continuous Integration (CI) setting, like on Travis. For example:
 
 ```
-michael@d30748af6d3d:~/helloworld$ stack --resolver lts-16.15 build
-Downloaded lts-16.15 build plan.
+michael@d30748af6d3d:~/helloworld$ stack --resolver lts-17.9 build
+Downloaded lts-17.9 build plan.
 # build output ...
 ```
 
@@ -1143,7 +1143,7 @@
 ```
 michael@d30748af6d3d:~$ stack exec --package stm -- echo I installed the stm package via --package stm
 Run from outside a project, using implicit global project config
-Using latest snapshot resolver: lts-16.15
+Using latest snapshot resolver: lts-17.9
 Writing global (non-project-specific) config file to: /home/michael/.stack/global/stack.yaml
 Note: You can change the snapshot via the resolver field there.
 I installed the stm package via --package stm
@@ -1226,6 +1226,19 @@
 If you're on Windows: you can run `stack turtle.hs` instead of `./turtle.hs`.
 The shebang line is not required in that case.
 
+### Just-in-time compilation
+
+You can add the `--compile` flag to make stack compile the script,
+and then run the compiled executable. Compilation is done quickly, 
+without optimization. To compile with optimization, use the `--optimize` flag 
+instead. Compilation is done only if needed; if the executable already exists,
+and is newer than the script, stack just runs the executable directly.
+
+This feature can be good for speed (your script runs faster) and also
+for durability (the executable remains runnable even if the script is
+disturbed, eg due to changes in your installed ghc/snapshots, changes
+to source files during git bisect, etc.)
+
 ### Using multiple packages
 
 You can also specify multiple packages, either with multiple `--package`
@@ -1650,6 +1663,7 @@
   per
   [our blog post](https://www.fpcomplete.com/blog/2016/05/stack-security-gnupg-keys).
     * `--no-signature` disables signing of packages
+    * `--candidate` upload a [package candidate](http://hackage.haskell.org/upload#candidates)
     * `username` and `password` can be read by environment
 
     ```bash
@@ -1666,6 +1680,9 @@
   (`-l`) and nightly (`-n`) snapshots.
 * `stack ls dependencies` lists all of the packages and versions used for a
   project
+* `stack list [PACKAGE]...` list the version of the specified package(s) in a
+  snapshot, or without an argument list all the snapshot's package versions.
+  If no resolver is specified the latest package version from Hackage is given.
 * `stack sig` subcommand can help you with GPG signing & verification
     * `sign` will sign an sdist tarball and submit the signature to
       sig.commercialhaskell.org for storage in the sig-archive git repo.
diff --git a/doc/faq.md b/doc/faq.md
--- a/doc/faq.md
+++ b/doc/faq.md
@@ -74,9 +74,9 @@
 
 ## I need to use a package (or version of a package) that is not available on hackage, what should I do?
 
-Add it to the 
-[`extra-deps`](yaml_configuration.md#extra-deps) list in your project's 
-`stack.yaml`, specifying the package's source code location relative to the 
+Add it to the
+[`extra-deps`](yaml_configuration.md#extra-deps) list in your project's
+`stack.yaml`, specifying the package's source code location relative to the
 directory where your `stack.yaml` file lives, e.g.
 
 ```yaml
@@ -89,9 +89,9 @@
 - patched/diagrams
 ```
 
-The above example specifies that the `proprietary-dep` package is found in the 
-project's `third-party` folder, that the `conduit` package is found in the 
-project's `github-version-of` folder, and that the `diagrams` package is found 
+The above example specifies that the `proprietary-dep` package is found in the
+project's `third-party` folder, that the `conduit` package is found in the
+project's `github-version-of` folder, and that the `diagrams` package is found
 in the project's `patched` folder. This autodetects changes and reinstalls the
 package.
 
@@ -171,10 +171,22 @@
 ```
 
 To ensure that Stack picks up changes to this file for rebuilds, add
+the following lines to your stack.yaml file:
+
+```yaml
+    custom-preprocessor-extensions:
+    - erb
+
+    require-stack-version: ">= 2.6.0"
+```
+
+And for backwards compatability with older versions of stack, also add
 the following line to your .cabal file:
 
     extra-source-files:   B.erb
 
+You could also use the [`--custom-preprocessor-extensions` flag](yaml_configuration.md#custom-preprocessor-extensions)
+
 ## I already have GHC installed, can I still use stack?
 
 Yes. In its default configuration, stack will simply ignore any system GHC
@@ -578,7 +590,7 @@
 Supported versions: ghc-7.10.3, ghc-8.0.1, ghc-8.0.2, ghc-8.2.1, ghc-8.2.2
 ```
 
-Most Linux distributions have standardized on providing libtinfo.so.6 (either directly or as a symlink to libncursesw.so.6). As such, there aren't GHC 8.6.* bindists that link to libncursesw.so.6 available. 
+Most Linux distributions have standardized on providing libtinfo.so.6 (either directly or as a symlink to libncursesw.so.6). As such, there aren't GHC 8.6.* bindists that link to libncursesw.so.6 available.
 
 So creating a symlink to libncursesw.so.6 as libtinfo.so.6 can prevent this error (root privileges might be required).
 ```
diff --git a/doc/yaml_configuration.md b/doc/yaml_configuration.md
--- a/doc/yaml_configuration.md
+++ b/doc/yaml_configuration.md
@@ -274,6 +274,17 @@
 needed. The user can delete this message if the generated configuration is
 acceptable.
 
+### custom-preprocessor-extensions
+
+In order for stack to be aware of any custom preprocessors you are using, add their extensions here
+
+```yaml
+custom-preprocessor-extensions:
+- erb
+```
+
+TODO: Add a simple example of how to use custom preprocessors.
+
 ## Non-project-specific config
 
 Non-project config options may go in the global config (`/etc/stack/config.yaml`) or the user config (`~/.stack/config.yaml`).
@@ -781,31 +792,6 @@
 modify-code-page: false
 ```
 
-### explicit-setup-deps
-
-(Since 0.1.6)
-
-Decide whether a custom `Setup.hs` script should be run with an explicit list of
-dependencies, based on the dependencies of the package itself. It associates the
-name of a local package with a boolean. When it's `true`, the `Setup.hs` script
-is built with an explicit list of packages. When it's `false` (default), the
-`Setup.hs` script is built without access to the local DB, but can access any
-package in the snapshot / global DB.
-
-Note that in the future, this will be unnecessary, once Cabal provides full
-support for explicit Setup.hs dependencies.
-
-```yaml
-explicit-setup-deps:
-    "*": true # change the default
-    entropy: false # override the new default for one package
-```
-
-NOTE: since 1.4.0, Stack has support for Cabal's `custom-setup` block
-(introduced in Cabal 1.24). If a `custom-setup` block is provided in a `.cabal`
-file, it will override the setting of `explicit-setup-deps`, and instead rely
-on the stated dependencies.
-
 ### allow-newer
 
 (Since 0.1.7)
@@ -951,7 +937,7 @@
     author-name: Your Name
     author-email: youremail@example.com
     category: Your Projects Category
-    copyright: 'Copyright (c) 2020 Your Name'
+    copyright: 'Copyright (c) 2021 Your Name'
     github-username: yourusername
 ```
 
diff --git a/src/Network/HTTP/StackClient.hs b/src/Network/HTTP/StackClient.hs
--- a/src/Network/HTTP/StackClient.hs
+++ b/src/Network/HTTP/StackClient.hs
@@ -11,6 +11,7 @@
   , httpNoBody
   , httpSink
   , withResponse
+  , setRequestCheckStatus
   , setRequestMethod
   , setRequestHeader
   , addRequestHeader
@@ -66,7 +67,7 @@
 import qualified Data.Text as T
 import           Data.Time.Clock (NominalDiffTime, diffUTCTime, getCurrentTime)
 import           Network.HTTP.Client (Request, RequestBody(..), Response, parseRequest, getUri, path, checkResponse, parseUrlThrow)
-import           Network.HTTP.Simple (setRequestMethod, setRequestBody, setRequestHeader, addRequestHeader, HttpException(..), getResponseBody, getResponseStatusCode, getResponseHeaders)
+import           Network.HTTP.Simple (setRequestCheckStatus, setRequestMethod, setRequestBody, setRequestHeader, addRequestHeader, HttpException(..), getResponseBody, getResponseStatusCode, getResponseHeaders)
 import           Network.HTTP.Types (hAccept, hContentLength, hContentMD5, methodPut)
 import           Network.HTTP.Conduit (requestHeaders)
 import           Network.HTTP.Client.TLS (getGlobalManager, applyDigestAuth, displayDigestAuthException)
diff --git a/src/Stack/Build.hs b/src/Stack/Build.hs
--- a/src/Stack/Build.hs
+++ b/src/Stack/Build.hs
@@ -9,6 +9,7 @@
 
 module Stack.Build
   (build
+  ,buildLocalTargets
   ,loadPackage
   ,mkBaseConfigOpts
   ,queryBuildInfo
@@ -39,6 +40,7 @@
 import           Stack.Build.Installed
 import           Stack.Build.Source
 import           Stack.Package
+import           Stack.Setup (withNewLocalBuildTargets)
 import           Stack.Types.Build
 import           Stack.Types.Config
 import           Stack.Types.NamedComponent
@@ -116,6 +118,10 @@
                          installedMap
                          (smtTargets $ smTargets sourceMap)
                          plan
+
+buildLocalTargets :: HasEnvConfig env => NonEmpty Text -> RIO env (Either SomeException ())
+buildLocalTargets targets =
+  tryAny $ withNewLocalBuildTargets (NE.toList targets) $ build Nothing
 
 justLocals :: Plan -> [PackageIdentifier]
 justLocals =
diff --git a/src/Stack/Build/Execute.hs b/src/Stack/Build/Execute.hs
--- a/src/Stack/Build/Execute.hs
+++ b/src/Stack/Build/Execute.hs
@@ -1024,10 +1024,8 @@
                   => ActionContext
                   -> ExecuteEnv
                   -> Task
-                  -> Maybe (Map PackageIdentifier GhcPkgId)
-                  -- ^ All dependencies' package ids to provide to Setup.hs. If
-                  -- Nothing, just provide global and snapshot package
-                  -- databases.
+                  -> Map PackageIdentifier GhcPkgId
+                  -- ^ All dependencies' package ids to provide to Setup.hs.
                   -> Maybe String
                   -> (  Package                                -- Package info
                      -> Path Abs File                          -- Cabal file path
@@ -1040,7 +1038,7 @@
                      -> OutputType
                      -> RIO env a)
                   -> RIO env a
-withSingleContext ActionContext {..} ee@ExecuteEnv {..} task@Task {..} mdeps msuffix inner0 =
+withSingleContext ActionContext {..} ee@ExecuteEnv {..} task@Task {..} allDeps msuffix inner0 =
     withPackage $ \package cabalfp pkgDir ->
     withOutputType pkgDir package $ \outputType ->
     withCabal package pkgDir outputType $ \cabal ->
@@ -1180,24 +1178,18 @@
 
                 getPackageArgs :: Path Abs Dir -> RIO env [String]
                 getPackageArgs setupDir =
-                    case (packageSetupDeps package, mdeps) of
+                    case packageSetupDeps package of
                         -- The package is using the Cabal custom-setup
                         -- configuration introduced in Cabal 1.24. In
                         -- this case, the package is providing an
                         -- explicit list of dependencies, and we
                         -- should simply use all of them.
-                        (Just customSetupDeps, _) -> do
+                        Just customSetupDeps -> do
                             unless (Map.member (mkPackageName "Cabal") customSetupDeps) $
                                 prettyWarnL
                                     [ fromString $ packageNameString $ packageName package
                                     , "has a setup-depends field, but it does not mention a Cabal dependency. This is likely to cause build errors."
                                     ]
-                            allDeps <-
-                                case mdeps of
-                                    Just x -> return x
-                                    Nothing -> do
-                                        prettyWarnS "In getPackageArgs: custom-setup in use, but no dependency map present"
-                                        return Map.empty
                             matchedDeps <- forM (Map.toList customSetupDeps) $ \(name, range) -> do
                                 let matches (PackageIdentifier name' version) =
                                         name == name' &&
@@ -1218,21 +1210,6 @@
                             writeBinaryFileAtomic cppMacrosFile (encodeUtf8Builder (T.pack (C.generatePackageVersionMacros macroDeps)))
                             return (packageDBArgs ++ depsArgs ++ cppArgs)
 
-                        -- This branch is taken when
-                        -- 'explicit-setup-deps' is requested in your
-                        -- stack.yaml file.
-                        (Nothing, Just deps) | explicitSetupDeps (packageName package) config -> do
-                            warnCustomNoDeps
-                            -- Stack always builds with the global Cabal for various
-                            -- reproducibility issues.
-                            let depsMinusCabal
-                                 = map ghcPkgIdString
-                                 $ Set.toList
-                                 $ addGlobalPackages deps (Map.elems eeGlobalDumpPkgs)
-                            return (
-                                packageDBArgs ++
-                                cabalPackageArg ++
-                                map ("-package-id=" ++) depsMinusCabal)
                         -- This branch is usually taken for builds, and
                         -- is always taken for `stack sdist`.
                         --
@@ -1250,7 +1227,7 @@
                         -- Currently, this branch is only taken via `stack
                         -- sdist` or when explicitly requested in the
                         -- stack.yaml file.
-                        (Nothing, _) -> do
+                        Nothing -> do
                             warnCustomNoDeps
                             return $ cabalPackageArg ++
                                     -- NOTE: This is different from
@@ -1542,7 +1519,7 @@
       where
         bindir = bcoSnapInstallRoot eeBaseConfigOpts </> bindirSuffix
 
-    realConfigAndBuild cache mcurator allDepsMap = withSingleContext ac ee task (Just allDepsMap) Nothing
+    realConfigAndBuild cache mcurator allDepsMap = withSingleContext ac ee task allDepsMap Nothing
         $ \package cabalfp pkgDir cabal0 announce _outputType -> do
             let cabal = cabal0 CloseOnException
             executableBuildStatuses <- getExecutableBuildStatuses package pkgDir
@@ -1859,7 +1836,7 @@
     mcurator <- view $ buildConfigL.to bcCurator
     let pname = pkgName $ taskProvides task
         expectFailure = expectTestFailure pname mcurator
-    withSingleContext ac ee task (Just allDepsMap) (Just "test") $ \package _cabalfp pkgDir _cabal announce outputType -> do
+    withSingleContext ac ee task allDepsMap (Just "test") $ \package _cabalfp pkgDir _cabal announce outputType -> do
         config <- view configL
         let needHpc = toCoverage topts
 
@@ -2087,7 +2064,7 @@
             -> RIO env ()
 singleBench beopts benchesToRun ac ee task installedMap = do
     (allDepsMap, _cache) <- getConfigCache ee task installedMap False True
-    withSingleContext ac ee task (Just allDepsMap) (Just "bench") $ \_package _cabalfp _pkgDir cabal announce _outputType -> do
+    withSingleContext ac ee task allDepsMap (Just "bench") $ \_package _cabalfp _pkgDir cabal announce _outputType -> do
         let args = map T.unpack benchesToRun <> maybe []
                          ((:[]) . ("--benchmark-options=" <>))
                          (beoAdditionalArgs beopts)
@@ -2285,81 +2262,6 @@
     case taskType task of
         TTLocalMutable lp -> lpComponents lp -- FIXME probably just want lpWanted
         TTRemotePackage{} -> Set.empty
-
--- | Take the given list of package dependencies and the contents of the global
--- package database, and construct a set of installed package IDs that:
---
--- * Excludes the Cabal library (it's added later)
---
--- * Includes all packages depended on by this package
---
--- * Includes all global packages, unless: (1) it's hidden, (2) it's shadowed
---   by a depended-on package, or (3) one of its dependencies is not met.
---
--- See:
---
--- * https://github.com/commercialhaskell/stack/issues/941
---
--- * https://github.com/commercialhaskell/stack/issues/944
---
--- * https://github.com/commercialhaskell/stack/issues/949
-addGlobalPackages :: Map PackageIdentifier GhcPkgId -- ^ dependencies of the package
-                  -> [DumpPackage] -- ^ global packages
-                  -> Set GhcPkgId
-addGlobalPackages deps globals0 =
-    res
-  where
-    -- Initial set of packages: the installed IDs of all dependencies
-    res0 = Map.elems $ Map.filterWithKey (\ident _ -> not $ isCabal ident) deps
-
-    -- First check on globals: it's not shadowed by a dep, it's not Cabal, and
-    -- it's exposed
-    goodGlobal1 dp = not (isDep dp)
-                  && not (isCabal $ dpPackageIdent dp)
-                  && dpIsExposed dp
-    globals1 = filter goodGlobal1 globals0
-
-    -- Create a Map of unique package names in the global database
-    globals2 = Map.fromListWith chooseBest
-             $ map (pkgName . dpPackageIdent &&& id) globals1
-
-    -- Final result: add in globals that have their dependencies met
-    res = loop id (Map.elems globals2) $ Set.fromList res0
-
-    ----------------------------------
-    -- Some auxiliary helper functions
-    ----------------------------------
-
-    -- Is the given package identifier for any version of Cabal
-    isCabal (PackageIdentifier name _) = name == mkPackageName "Cabal"
-
-    -- Is the given package name provided by the package dependencies?
-    isDep dp = pkgName (dpPackageIdent dp) `Set.member` depNames
-    depNames = Set.map pkgName $ Map.keysSet deps
-
-    -- Choose the best of two competing global packages (the newest version)
-    chooseBest dp1 dp2
-        | getVer dp1 < getVer dp2 = dp2
-        | otherwise               = dp1
-      where
-        getVer = pkgVersion . dpPackageIdent
-
-    -- Are all dependencies of the given package met by the given Set of
-    -- installed packages
-    depsMet dp gids = all (`Set.member` gids) (dpDepends dp)
-
-    -- Find all globals that have all of their dependencies met
-    loop front (dp:dps) gids
-        -- This package has its deps met. Add it to the list of dependencies
-        -- and then traverse the list from the beginning (this package may have
-        -- been a dependency of an earlier one).
-        | depsMet dp gids = loop id (front dps) (Set.insert (dpGhcPkgId dp) gids)
-        -- Deps are not met, keep going
-        | otherwise = loop (front . (dp:)) dps gids
-    -- None of the packages we checked can be added, therefore drop them all
-    -- and return our results
-    loop _ [] gids = gids
-
 
 expectTestFailure :: PackageName -> Maybe Curator -> Bool
 expectTestFailure pname mcurator =
diff --git a/src/Stack/Config.hs b/src/Stack/Config.hs
--- a/src/Stack/Config.hs
+++ b/src/Stack/Config.hs
@@ -51,7 +51,6 @@
 import qualified Distribution.Text
 import           Distribution.Version (simplifyVersionRange, mkVersion')
 import           GHC.Conc (getNumProcessors)
-import           Lens.Micro ((.~))
 import           Network.HTTP.StackClient (httpJSON, parseUrlThrow, getResponseBody)
 import           Options.Applicative (Parser, help, long, metavar, strOption)
 import           Path
@@ -230,6 +229,7 @@
 
          configExtraIncludeDirs = configMonoidExtraIncludeDirs
          configExtraLibDirs = configMonoidExtraLibDirs
+         configCustomPreprocessorExts = configMonoidCustomPreprocessorExts
          configOverrideGccPath = getFirst configMonoidOverrideGccPath
 
          -- Only place in the codebase where platform is hard-coded. In theory
@@ -329,7 +329,6 @@
          configSetupInfoInline = configMonoidSetupInfoInline
          configPvpBounds = fromFirst (PvpBounds PvpBoundsNone False) configMonoidPvpBounds
          configModifyCodePage = fromFirstTrue configMonoidModifyCodePage
-         configExplicitSetupDeps = configMonoidExplicitSetupDeps
          configRebuildGhcOptions = fromFirstFalse configMonoidRebuildGhcOptions
          configApplyGhcOptions = fromFirst AGOLocals configMonoidApplyGhcOptions
          configAllowNewer = fromFirst False configMonoidAllowNewer
diff --git a/src/Stack/Config/Nix.hs b/src/Stack/Config/Nix.hs
--- a/src/Stack/Config/Nix.hs
+++ b/src/Stack/Config/Nix.hs
@@ -5,6 +5,7 @@
 module Stack.Config.Nix
        (nixOptsFromMonoid
        ,nixCompiler
+       ,nixCompilerVersion
        ,StackNixException(..)
        ) where
 
@@ -73,6 +74,16 @@
               <> T.pack (versionString version) <> "\"\
               \else haskell.compiler.${builtins.head compilers})"
             _ -> "haskell.compiler.ghc" <> T.concat (x : y : minor)
+        _ -> Left $ stringException "GHC major version not specified"
+    WCGhcjs{} -> Left $ stringException "Only GHC is supported by stack --nix"
+    WCGhcGit{} -> Left $ stringException "Only GHC is supported by stack --nix"
+
+nixCompilerVersion :: WantedCompiler -> Either StringException T.Text
+nixCompilerVersion compilerVersion =
+  case compilerVersion of
+    WCGhc version ->
+      case T.split (== '.') (fromString $ versionString version) of
+        x : y : minor -> Right $ "ghc" <> T.concat (x : y : minor)
         _ -> Left $ stringException "GHC major version not specified"
     WCGhcjs{} -> Left $ stringException "Only GHC is supported by stack --nix"
     WCGhcGit{} -> Left $ stringException "Only GHC is supported by stack --nix"
diff --git a/src/Stack/Constants.hs b/src/Stack/Constants.hs
--- a/src/Stack/Constants.hs
+++ b/src/Stack/Constants.hs
@@ -9,7 +9,7 @@
     (buildPlanDir
     ,buildPlanCacheDir
     ,haskellFileExts
-    ,haskellPreprocessorExts
+    ,haskellDefaultPreprocessorExts
     ,stackDotYaml
     ,stackWorkEnvVar
     ,stackRootEnvVar
@@ -142,8 +142,8 @@
 haskellFileExts = ["hs", "hsc", "lhs"]
 
 -- | Extensions for modules that are preprocessed by common preprocessors.
-haskellPreprocessorExts :: [Text]
-haskellPreprocessorExts = ["gc", "chs", "hsc", "x", "y", "ly", "cpphs"]
+haskellDefaultPreprocessorExts :: [Text]
+haskellDefaultPreprocessorExts = ["gc", "chs", "hsc", "x", "y", "ly", "cpphs"]
 
 -- | Name of the 'stack' program, uppercased
 stackProgNameUpper :: String
diff --git a/src/Stack/Docker.hs b/src/Stack/Docker.hs
--- a/src/Stack/Docker.hs
+++ b/src/Stack/Docker.hs
@@ -450,7 +450,7 @@
 -- a container, such as switching the UID/GID to the "outside-Docker" user's.
 entrypoint :: (HasProcessContext env, HasLogFunc env)
            => Config -> DockerEntrypoint -> RIO env ()
-entrypoint config@Config{..} DockerEntrypoint{..} =
+entrypoint config@Config{} DockerEntrypoint{..} =
   modifyMVar_ entrypointMVar $ \alreadyRan -> do
     -- Only run the entrypoint once
     unless alreadyRan $ do
diff --git a/src/Stack/Ghci.hs b/src/Stack/Ghci.hs
--- a/src/Stack/Ghci.hs
+++ b/src/Stack/Ghci.hs
@@ -21,6 +21,7 @@
 import qualified Data.ByteString.Char8 as S8
 import qualified Data.ByteString.Lazy as LBS
 import           Data.List
+import qualified Data.List.NonEmpty as NE
 import qualified Data.Map.Strict as M
 import qualified Data.Set as S
 import qualified Data.Text as T
@@ -32,7 +33,7 @@
 import           Path.IO hiding (withSystemTempDir)
 import qualified RIO
 import           RIO.PrettyPrint
-import           RIO.Process (HasProcessContext, exec, proc, readProcess_)
+import           RIO.Process (HasProcessContext, exec, proc, readProcess_, withWorkingDir)
 import           Stack.Build
 import           Stack.Build.Installed
 import           Stack.Build.Source
@@ -41,7 +42,6 @@
 import           Stack.Constants.Config
 import           Stack.Ghci.Script
 import           Stack.Package
-import           Stack.Setup (withNewLocalBuildTargets)
 import           Stack.Types.Build
 import           Stack.Types.Config
 import           Stack.Types.NamedComponent
@@ -346,14 +346,17 @@
     let targets = localTargets ++ map T.pack ghciAdditionalPackages
     -- If necessary, do the build, for local packagee targets, only do
     -- 'initialBuildSteps'.
-    when (not ghciNoBuild && not (null targets)) $ do
-        -- only new local targets could appear here
-        eres <- tryAny $ withNewLocalBuildTargets targets $ build Nothing
+    case NE.nonEmpty targets of
+      -- only new local targets could appear here
+      Just nonEmptyTargets | not ghciNoBuild -> do
+        eres <- buildLocalTargets nonEmptyTargets
         case eres of
             Right () -> return ()
             Left err -> do
                 prettyError $ fromString (show err)
                 prettyWarn "Build failed, but trying to launch GHCi anyway"
+      _ ->
+        return ()
 
 checkAdditionalPackages :: MonadThrow m => [String] -> m [PackageName]
 checkAdditionalPackages pkgs = forM pkgs $ \name -> do
@@ -412,7 +415,7 @@
     compilerExeName <- view $ compilerPathsL.to cpCompiler.to toFilePath
     let execGhci extras = do
             menv <- liftIO $ configProcessContextSettings config defaultEnvSettings
-            withProcessContext menv $ exec
+            withPackageWorkingDir $ withProcessContext menv $ exec
                  (fromMaybe compilerExeName ghciGhcCommand)
                  (("--interactive" : ) $
                  -- This initial "-i" resets the include directories to
@@ -420,6 +423,10 @@
                  -- is included.
                   (if null pkgs then id else ("-i" : )) $
                   odir <> pkgopts <> extras <> ghciGhcOptions <> ghciArgs)
+        withPackageWorkingDir =
+            case pkgs of
+              [pkg] -> withWorkingDir (toFilePath $ ghciPkgDir pkg)
+              _ -> id
         -- TODO: Consider optimizing this check. Perhaps if no
         -- "with-ghc" is specified, assume that it is not using intero.
         checkIsIntero =
@@ -747,48 +754,63 @@
 
 checkForIssues :: HasLogFunc env => [GhciPkgInfo] -> RIO env ()
 checkForIssues pkgs = do
-    unless (null issues) $ borderedWarning $ do
-        logWarn "Warning: There are cabal settings for this project which may prevent GHCi from loading your code properly."
-        logWarn "In some cases it can also load some projects which would otherwise fail to build."
-        logWarn ""
-        mapM_ (logWarn . RIO.display) $ intercalate [""] issues
-        logWarn ""
-        logWarn "To resolve, remove the flag(s) from the cabal file(s) and instead put them at the top of the haskell files."
-        logWarn ""
+    when (length pkgs > 1) $ borderedWarning $ do
+        -- Cabal flag issues could arise only when there are at least 2 packages
+        unless (null cabalFlagIssues) $ borderedWarning $ do
+            logWarn "Warning: There are cabal flags for this project which may prevent GHCi from loading your code properly."
+            logWarn "In some cases it can also load some projects which would otherwise fail to build."
+            logWarn ""
+            mapM_ (logWarn . RIO.display) $ intercalate [""] cabalFlagIssues
+            logWarn ""
+            logWarn "To resolve, remove the flag(s) from the cabal file(s) and instead put them at the top of the haskell files."
+            logWarn ""
         logWarn "It isn't yet possible to load multiple packages into GHCi in all cases - see"
         logWarn "https://ghc.haskell.org/trac/ghc/ticket/10827"
   where
-    issues = concat
-        [ mixedFlag "-XNoImplicitPrelude"
-          [ "-XNoImplicitPrelude will be used, but GHCi will likely fail to build things which depend on the implicit prelude." ]
-        , mixedFlag "-XCPP"
-          [ "-XCPP will be used, but it can cause issues with multiline strings."
-          , "See https://downloads.haskell.org/~ghc/7.10.2/docs/html/users_guide/options-phases.html#cpp-string-gaps"
-          ]
-        , mixedFlag "-XNoTraditionalRecordSyntax"
-          [ "-XNoTraditionalRecordSyntax will be used, but it break modules which use record syntax." ]
-        , mixedFlag "-XTemplateHaskell"
-          [ "-XTemplateHaskell will be used, but it may cause compilation issues due to different parsing of '$' when there's no space after it." ]
-        , mixedFlag "-XQuasiQuotes"
-          [ "-XQuasiQuotes will be used, but it may cause parse failures due to a different meaning for list comprehension syntax like [x| ... ]" ]
-        , mixedFlag "-XSafe"
-          [ "-XSafe will be used, but it will fail to compile unsafe modules." ]
-        , mixedFlag "-XArrows"
-          [ "-XArrows will be used, but it will cause non-arrow usages of proc, (-<), (-<<) to fail" ]
-        , mixedFlag "-XOverloadedStrings"
-          [ "-XOverloadedStrings will be used, but it can cause type ambiguity in code not usually compiled with it." ]
-        , mixedFlag "-XOverloadedLists"
-          [ "-XOverloadedLists will be used, but it can cause type ambiguity in code not usually compiled with it." ]
-        , mixedFlag "-XMonoLocalBinds"
-          [ "-XMonoLocalBinds will be used, but it can cause type errors in code which expects generalized local bindings." ]
-        , mixedFlag "-XTypeFamilies"
-          [ "-XTypeFamilies will be used, but it implies -XMonoLocalBinds, and so can cause type errors in code which expects generalized local bindings." ]
-        , mixedFlag "-XGADTs"
-          [ "-XGADTs will be used, but it implies -XMonoLocalBinds, and so can cause type errors in code which expects generalized local bindings." ]
-        , mixedFlag "-XNewQualifiedOperators"
-          [ "-XNewQualifiedOperators will be used, but this will break usages of the old qualified operator syntax." ]
+    cabalFlagIssues = concatMap mixedFlag
+        [ ( "-XNoImplicitPrelude"
+          , [ "-XNoImplicitPrelude will be used, but GHCi will likely fail to build things which depend on the implicit prelude."]
+          )
+        , ( "-XCPP"
+          , [ "-XCPP will be used, but it can cause issues with multiline strings."
+            , "See https://downloads.haskell.org/~ghc/7.10.2/docs/html/users_guide/options-phases.html#cpp-string-gaps"
+            ]
+          )
+        , ( "-XNoTraditionalRecordSyntax"
+          , [ "-XNoTraditionalRecordSyntax will be used, but it break modules which use record syntax." ]
+          )
+        , ( "-XTemplateHaskell"
+          , [ "-XTemplateHaskell will be used, but it may cause compilation issues due to different parsing of '$' when there's no space after it." ]
+          )
+        , ( "-XQuasiQuotes"
+          , [ "-XQuasiQuotes will be used, but it may cause parse failures due to a different meaning for list comprehension syntax like [x| ... ]" ]
+          )
+        , ( "-XSafe"
+          , [ "-XSafe will be used, but it will fail to compile unsafe modules." ]
+          )
+        , ( "-XArrows"
+          , [ "-XArrows will be used, but it will cause non-arrow usages of proc, (-<), (-<<) to fail" ]
+          )
+        , ( "-XOverloadedStrings"
+          , [ "-XOverloadedStrings will be used, but it can cause type ambiguity in code not usually compiled with it." ]
+          )
+        , ( "-XOverloadedLists"
+          , [ "-XOverloadedLists will be used, but it can cause type ambiguity in code not usually compiled with it." ]
+          )
+        , ( "-XMonoLocalBinds"
+          , [ "-XMonoLocalBinds will be used, but it can cause type errors in code which expects generalized local bindings." ]
+          )
+        , ( "-XTypeFamilies"
+          , [ "-XTypeFamilies will be used, but it implies -XMonoLocalBinds, and so can cause type errors in code which expects generalized local bindings." ]
+          )
+        , ( "-XGADTs"
+          , [ "-XGADTs will be used, but it implies -XMonoLocalBinds, and so can cause type errors in code which expects generalized local bindings." ]
+          )
+        , ( "-XNewQualifiedOperators"
+          , [ "-XNewQualifiedOperators will be used, but this will break usages of the old qualified operator syntax." ]
+          )
         ]
-    mixedFlag flag msgs =
+    mixedFlag (flag, msgs) =
         let x = partitionComps (== flag) in
         [ msgs ++ showWhich x | mixedSettings x ]
     mixedSettings (xs, ys) = xs /= [] && ys /= []
diff --git a/src/Stack/List.hs b/src/Stack/List.hs
new file mode 100644
--- /dev/null
+++ b/src/Stack/List.hs
@@ -0,0 +1,76 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+module Stack.List
+  ( listPackages
+  ) where
+
+import Stack.Prelude
+import qualified RIO.Map as Map
+import RIO.List (intercalate)
+import RIO.Process (HasProcessContext)
+
+newtype ListException
+  = CouldNotParsePackageSelectors [String]
+    deriving Typeable
+instance Exception ListException
+instance Show ListException where
+    show (CouldNotParsePackageSelectors strs) = unlines $ map ("- " ++) strs
+
+-- | Intended to work for the command line command.
+listPackages
+  :: forall env. (HasPantryConfig env, HasLogFunc env, HasProcessContext env)
+  => Maybe RawSnapshot -- ^ when looking up by name, take from this build plan
+  -> [String] -- ^ names or identifiers
+  -> RIO env ()
+listPackages mSnapshot input = do
+    let (errs1, names) = case mSnapshot of
+                   Just snapshot | null input ->
+                                     ([], Map.keys (rsPackages snapshot))
+                   _ -> partitionEithers $ map parse input
+    (errs2, locs) <- partitionEithers <$> traverse toLoc names
+    case errs1 ++ errs2 of
+      [] -> pure ()
+      errs -> throwM $ CouldNotParsePackageSelectors errs
+    mapM_ (logInfo . fromString . packageIdentifierString) locs
+  where
+    toLoc | Just snapshot <- mSnapshot = toLocSnapshot snapshot
+          | otherwise = toLocNoSnapshot
+
+    toLocNoSnapshot :: PackageName -> RIO env (Either String PackageIdentifier)
+    toLocNoSnapshot name = do
+      mloc1 <- getLatestHackageLocation YesRequireHackageIndex name UsePreferredVersions
+      mloc <-
+        case mloc1 of
+          Just _ -> pure mloc1
+          Nothing -> do
+            updated <- updateHackageIndex $ Just $ "Could not find package " <> fromString (packageNameString name) <> ", updating"
+            case updated of
+              UpdateOccurred -> getLatestHackageLocation YesRequireHackageIndex name UsePreferredVersions
+              NoUpdateOccurred -> pure Nothing
+      case mloc of
+        Nothing -> do
+          candidates <- getHackageTypoCorrections name
+          pure $ Left $ concat
+            [ "Could not find package "
+            , packageNameString name
+            , " on Hackage"
+            , if null candidates
+                then ""
+                else ". Perhaps you meant: " ++ intercalate ", " (map packageNameString candidates)
+            ]
+        Just loc -> pure $ Right (packageLocationIdent loc)
+
+    toLocSnapshot :: RawSnapshot -> PackageName -> RIO env (Either String PackageIdentifier)
+    toLocSnapshot snapshot name =
+        case Map.lookup name (rsPackages snapshot) of
+          Nothing ->
+            pure $ Left $ "Package does not appear in snapshot: " ++ packageNameString name
+          Just sp -> do
+            loc <- cplComplete <$> completePackageLocation (rspLocation sp)
+            pure $ Right (packageLocationIdent loc)
+
+    parse s =
+        case parsePackageName s of
+            Just x -> Right x
+            Nothing -> Left $ "Could not parse as package name or identifier: " ++ s
diff --git a/src/Stack/New.hs b/src/Stack/New.hs
--- a/src/Stack/New.hs
+++ b/src/Stack/New.hs
@@ -17,6 +17,8 @@
 
 import           Stack.Prelude
 import           Control.Monad.Trans.Writer.Strict
+import           Data.Aeson as A
+import qualified Data.ByteString.Base64 as B64
 import           Data.ByteString.Builder (lazyByteString)
 import qualified Data.ByteString.Lazy as LB
 import           Data.Conduit
@@ -31,13 +33,14 @@
 import           Data.Time.Clock
 import           Network.HTTP.StackClient (VerifiedDownloadException (..), Request, HttpException,
                                            getResponseBody, httpLbs, mkDownloadRequest, parseRequest, parseUrlThrow,
-                                           setForceDownload, setGithubHeaders, verifiedDownloadWithProgress)
+                                           setForceDownload, setGithubHeaders, setRequestCheckStatus, verifiedDownloadWithProgress)
 import           Path
 import           Path.IO
 import           Stack.Constants
 import           Stack.Constants.Config
 import           Stack.Types.Config
 import           Stack.Types.TemplateName
+import qualified RIO.HashMap as HM
 import           RIO.Process
 import qualified Text.Mustache as Mustache
 import qualified Text.Mustache.Render as Mustache
@@ -116,45 +119,56 @@
 loadTemplate name logIt = do
     templateDir <- view $ configL.to templatesDir
     case templatePath name of
-        AbsPath absFile -> logIt LocalTemp >> loadLocalFile absFile
-        UrlPath s -> downloadFromUrl s templateDir
+        AbsPath absFile -> logIt LocalTemp >> loadLocalFile absFile eitherByteStringToText
+        UrlPath s -> do
+            let settings = asIsFromUrl s
+            downloadFromUrl settings templateDir
         RelPath rawParam relFile ->
             catch
-                (do f <- loadLocalFile relFile
+                (do f <- loadLocalFile relFile eitherByteStringToText
                     logIt LocalTemp
                     return f)
-                (\(e :: NewException) ->
-                      case relRequest rawParam of
-                        Just req -> downloadTemplate req
-                                                     (templateDir </> relFile)
+                (\(e :: NewException) -> do
+                      case relSettings rawParam of
+                        Just settings -> do
+                          req <- parseRequest (tplDownloadUrl settings)
+                          let extract = tplExtract settings
+                          downloadTemplate req extract (templateDir </> relFile)
                         Nothing -> throwM e
                 )
         RepoPath rtp -> do
-            let url = urlFromRepoTemplatePath rtp
-            downloadFromUrl (T.unpack url) templateDir
+            let settings = settingsFromRepoTemplatePath rtp
+            downloadFromUrl settings templateDir
                             
   where
-    loadLocalFile :: Path b File -> RIO env Text
-    loadLocalFile path = do
+    loadLocalFile :: Path b File -> (ByteString -> Either String Text) -> RIO env Text
+    loadLocalFile path extract = do
         logDebug ("Opening local template: \"" <> fromString (toFilePath path)
                                                 <> "\"")
         exists <- doesFileExist path
         if exists
-            then readFileUtf8 (toFilePath path)
+            then do
+                bs <- readFileBinary (toFilePath path) --readFileUtf8 (toFilePath path)
+                case extract bs of
+                    Left err -> do
+                        logWarn $ "Template extraction error: " <> display (T.pack err)
+                        throwM (FailedToLoadTemplate name (toFilePath path))
+                    Right template ->
+                        pure template
             else throwM (FailedToLoadTemplate name (toFilePath path))
-    relRequest :: String -> Maybe Request
-    relRequest req = do
+    relSettings :: String -> Maybe TemplateDownloadSettings
+    relSettings req = do
         rtp <- parseRepoPathWithService defaultRepoService (T.pack req)
-        let url = urlFromRepoTemplatePath rtp
-        parseRequest (T.unpack url)
-    downloadFromUrl :: String -> Path Abs Dir -> RIO env Text
-    downloadFromUrl s templateDir = do
-        req <- parseRequest s
-        let rel = fromMaybe backupUrlRelPath (parseRelFile s)
-        downloadTemplate req (templateDir </> rel)
-    downloadTemplate :: Request -> Path Abs File -> RIO env Text
-    downloadTemplate req path = do
-        let dReq = setForceDownload True $ mkDownloadRequest req
+        pure (settingsFromRepoTemplatePath rtp)
+    downloadFromUrl :: TemplateDownloadSettings -> Path Abs Dir -> RIO env Text
+    downloadFromUrl settings templateDir = do
+        let url = tplDownloadUrl settings
+        req <- parseRequest url
+        let rel = fromMaybe backupUrlRelPath (parseRelFile url)
+        downloadTemplate req (tplExtract settings) (templateDir </> rel)
+    downloadTemplate :: Request -> (ByteString -> Either String Text) -> Path Abs File -> RIO env Text
+    downloadTemplate req extract path = do
+        let dReq = setForceDownload True $ mkDownloadRequest (setRequestCheckStatus req)
         logIt RemoteTemp
         catch
           (void $ do
@@ -162,7 +176,7 @@
           )
           (useCachedVersionOrThrow path)
 
-        loadLocalFile path
+        loadLocalFile path extract
     useCachedVersionOrThrow :: Path Abs File -> VerifiedDownloadException -> RIO env ()
     useCachedVersionOrThrow path exception = do
       exists <- doesFileExist path
@@ -172,14 +186,41 @@
                 logWarn "Using cached local version. It may not be the most recent version though."
         else throwM (FailedToDownloadTemplate name exception)
 
+data TemplateDownloadSettings = TemplateDownloadSettings
+  { tplDownloadUrl :: String
+  , tplExtract :: ByteString -> Either String Text
+  }
+
+eitherByteStringToText :: ByteString -> Either String Text
+eitherByteStringToText = mapLeft show . decodeUtf8'
+
+asIsFromUrl :: String -> TemplateDownloadSettings
+asIsFromUrl url = TemplateDownloadSettings
+  { tplDownloadUrl = url
+  , tplExtract = eitherByteStringToText
+  }
+
 -- | Construct a URL for downloading from a repo.
-urlFromRepoTemplatePath :: RepoTemplatePath -> Text
-urlFromRepoTemplatePath (RepoTemplatePath Github user name) =
-    T.concat ["https://raw.githubusercontent.com", "/", user, "/stack-templates/master/", name]
-urlFromRepoTemplatePath (RepoTemplatePath Gitlab user name) =
-    T.concat ["https://gitlab.com",                "/", user, "/stack-templates/raw/master/", name]
-urlFromRepoTemplatePath (RepoTemplatePath Bitbucket user name) =
-    T.concat ["https://bitbucket.org",             "/", user, "/stack-templates/raw/master/", name]
+settingsFromRepoTemplatePath :: RepoTemplatePath -> TemplateDownloadSettings
+settingsFromRepoTemplatePath (RepoTemplatePath Github user name) =
+    -- T.concat ["https://raw.githubusercontent.com", "/", user, "/stack-templates/master/", name]
+    TemplateDownloadSettings
+    { tplDownloadUrl = concat ["https://api.github.com/repos/", T.unpack user, "/stack-templates/contents/", T.unpack name]
+    , tplExtract = \bs -> do
+        decodedJson <- eitherDecode (LB.fromStrict bs)
+        case decodedJson of
+          Object o | Just (String content) <- HM.lookup "content" o -> do
+                       let noNewlines = T.filter (/= '\n')
+                       bsContent <- B64.decode $ T.encodeUtf8 (noNewlines content)
+                       mapLeft show $ decodeUtf8' bsContent
+          _ ->
+            Left "Couldn't parse GitHub response as a JSON object with a \"content\" field"
+    }
+
+settingsFromRepoTemplatePath (RepoTemplatePath Gitlab user name) =
+    asIsFromUrl $ concat ["https://gitlab.com",                "/", T.unpack user, "/stack-templates/raw/master/", T.unpack name]
+settingsFromRepoTemplatePath (RepoTemplatePath Bitbucket user name) =
+    asIsFromUrl $ concat ["https://bitbucket.org",             "/", T.unpack user, "/stack-templates/raw/master/", T.unpack name]
 
 -- | Apply and unpack a template into a directory.
 applyTemplate
diff --git a/src/Stack/Nix.hs b/src/Stack/Nix.hs
--- a/src/Stack/Nix.hs
+++ b/src/Stack/Nix.hs
@@ -18,7 +18,7 @@
 import           Path.IO
 import qualified Paths_stack as Meta
 import           Stack.Config (getInContainer, withBuildConfig)
-import           Stack.Config.Nix (nixCompiler)
+import           Stack.Config.Nix (nixCompiler, nixCompilerVersion)
 import           Stack.Constants (platformVariantEnvVar,inNixShellEnvVar,inContainerEnvVar)
 import           Stack.Types.Config
 import           Stack.Types.Docker
@@ -56,14 +56,16 @@
      compilerVersion <- withBuildConfig $ view wantedCompilerVersionL
 
      ghc <- either throwIO return $ nixCompiler compilerVersion
+     ghcVersion <- either throwIO return $ nixCompilerVersion compilerVersion
      let pkgsInConfig = nixPackages (configNix config)
          pkgs = pkgsInConfig ++ [ghc, "git", "gcc", "gmp"]
          pkgsStr = "[" <> T.intercalate " " pkgs <> "]"
          pureShell = nixPureShell (configNix config)
          addGCRoots = nixAddGCRoots (configNix config)
          nixopts = case mshellFile of
-           Just fp -> [toFilePath fp, "--arg", "ghc"
-                      ,"with (import <nixpkgs> {}); " ++ T.unpack ghc]
+           Just fp -> [toFilePath fp
+                      ,"--arg", "ghc", "with (import <nixpkgs> {}); " ++ T.unpack ghc
+                      ,"--argstr", "ghcVersion", T.unpack ghcVersion]
            Nothing -> ["-E", T.unpack $ T.concat
                               ["with (import <nixpkgs> {}); "
                               ,"let inputs = ",pkgsStr,"; "
diff --git a/src/Stack/Options/BuildMonoidParser.hs b/src/Stack/Options/BuildMonoidParser.hs
--- a/src/Stack/Options/BuildMonoidParser.hs
+++ b/src/Stack/Options/BuildMonoidParser.hs
@@ -112,7 +112,7 @@
     copyBins =
         firstBoolFlagsFalse
             "copy-bins"
-            "copying binaries to the local-bin-path (see 'stack path')"
+            "copying binaries to local-bin (see 'stack path')"
             hide
     copyCompilerTool =
         firstBoolFlagsFalse
diff --git a/src/Stack/Options/ConfigParser.hs b/src/Stack/Options/ConfigParser.hs
--- a/src/Stack/Options/ConfigParser.hs
+++ b/src/Stack/Options/ConfigParser.hs
@@ -20,7 +20,7 @@
 configOptsParser :: FilePath -> GlobalOptsContext -> Parser ConfigMonoid
 configOptsParser currentDir hide0 =
     (\stackRoot workDir buildOpts dockerOpts nixOpts systemGHC installGHC arch
-        ghcVariant ghcBuild jobs includes libs overrideGccPath overrideHpack
+        ghcVariant ghcBuild jobs includes libs preprocs overrideGccPath overrideHpack
         skipGHCCheck skipMsys localBin setupInfoLocations modifyCodePage
         allowDifferentUser dumpLogs colorWhen snapLoc -> mempty
             { configMonoidStackRoot = stackRoot
@@ -37,6 +37,7 @@
             , configMonoidJobs = jobs
             , configMonoidExtraIncludeDirs = includes
             , configMonoidExtraLibDirs = libs
+            , configMonoidCustomPreprocessorExts = preprocs
             , configMonoidOverrideGccPath = overrideGccPath
             , configMonoidOverrideHpack = overrideHpack
             , configMonoidSkipMsys = skipMsys
@@ -101,6 +102,12 @@
            <> metavar "DIR"
            <> completer dirCompleter
            <> help "Extra directories to check for libraries"
+           <> hide
+            ))
+    <*> many (strOption
+            ( long "custom-preprocessor-extensions"
+           <> metavar "EXT"
+           <> help "Extensions used for custom preprocessors"
            <> hide
             ))
     <*> optionalFirst (absFileOption
diff --git a/src/Stack/Options/SDistParser.hs b/src/Stack/Options/SDistParser.hs
--- a/src/Stack/Options/SDistParser.hs
+++ b/src/Stack/Options/SDistParser.hs
@@ -7,7 +7,7 @@
 import           Stack.SDist
 import           Stack.Options.HpcReportParser (pvpBoundsOption)
 
--- | Parser for arguments to `stack sdist` and `stack upload`
+-- | Parser for arguments to `stack sdist`
 sdistOptsParser :: Parser SDistOpts
 sdistOptsParser = SDistOpts <$>
   many (strArgument $ metavar "DIR" <> completer dirCompleter) <*>
diff --git a/src/Stack/Options/UploadParser.hs b/src/Stack/Options/UploadParser.hs
new file mode 100644
--- /dev/null
+++ b/src/Stack/Options/UploadParser.hs
@@ -0,0 +1,35 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+module Stack.Options.UploadParser
+  ( UploadOpts(..)
+  , UploadVariant(..)
+  , uploadOptsParser
+  ) where
+
+import           Options.Applicative
+import           Stack.Options.SDistParser (sdistOptsParser)
+import           Stack.Prelude
+import           Stack.SDist (SDistOpts(..))
+
+data UploadOpts = UploadOpts
+  { uoptsSDistOpts :: SDistOpts
+  , uoptsUploadVariant :: UploadVariant
+  -- ^ Says whether to publish the package or upload as a release candidate
+  }
+
+data UploadVariant
+  = Publishing
+  -- ^ Publish the package
+  | Candidate
+  -- ^ Create a package candidate
+
+-- | Parser for arguments to `stack upload`
+uploadOptsParser :: Parser UploadOpts
+uploadOptsParser =
+  UploadOpts
+    <$> sdistOptsParser
+    <*> uploadVariant
+  where
+    uploadVariant =
+      flag Publishing Candidate
+        (long "candidate" <>
+         help "Upload as a package candidate")
diff --git a/src/Stack/Package.hs b/src/Stack/Package.hs
--- a/src/Stack/Package.hs
+++ b/src/Stack/Package.hs
@@ -1107,7 +1107,7 @@
     :: FilePath -> RIO Ctx (Set ModuleName, [Path Abs File])
 parseHI hiPath = do
   dir <- asks (parent . ctxFile)
-  result <- liftIO $ Iface.fromFile hiPath
+  result <- liftIO $ Iface.fromFile hiPath `catchAnyDeep` \e -> pure (Left (show e))
   case result of
     Left msg -> do
       prettyStackDevL
@@ -1173,7 +1173,9 @@
     -> RIO Ctx (Maybe DotCabalPath)
 findCandidate dirs name = do
     pkg <- asks ctxFile >>= parsePackageNameFromFilePath
-    candidates <- liftIO makeNameCandidates
+    customPreprocessorExts <- view $ configL . to configCustomPreprocessorExts
+    let haskellPreprocessorExts = haskellDefaultPreprocessorExts ++ customPreprocessorExts
+    candidates <- liftIO $ makeNameCandidates haskellPreprocessorExts
     case candidates of
         [candidate] -> return (Just (cons candidate))
         [] -> do
@@ -1193,11 +1195,12 @@
             DotCabalFile{} -> DotCabalFilePath
             DotCabalCFile{} -> DotCabalCFilePath
     paths_pkg pkg = "Paths_" ++ packageNameString pkg
-    makeNameCandidates =
-        liftM (nubOrd . concat) (mapM makeDirCandidates dirs)
-    makeDirCandidates :: Path Abs Dir
+    makeNameCandidates haskellPreprocessorExts =
+        liftM (nubOrd . concat) (mapM (makeDirCandidates haskellPreprocessorExts) dirs)
+    makeDirCandidates :: [Text]
+                      -> Path Abs Dir
                       -> IO [Path Abs File]
-    makeDirCandidates dir =
+    makeDirCandidates haskellPreprocessorExts dir =
         case name of
             DotCabalMain fp -> resolveCandidate dir fp
             DotCabalFile fp -> resolveCandidate dir fp
@@ -1268,8 +1271,8 @@
         , flow "but did find:"
         , line <> bulletedList (map pretty possibilities)
         , flow "If you are using a custom preprocessor for this module"
-        , flow "with its own file extension, consider adding the file(s)"
-        , flow "to your .cabal under extra-source-files."
+        , flow "with its own file extension, consider adding the extension"
+        , flow "to the 'custom-preprocessor-extensions' field in stack.yaml."
         ]
   where
     makePossibilities name =
diff --git a/src/Stack/Path.hs b/src/Stack/Path.hs
--- a/src/Stack/Path.hs
+++ b/src/Stack/Path.hs
@@ -167,7 +167,7 @@
     , ( "Directory containing binaries specific to a particular compiler (e.g. intero)"
       , "compiler-tools-bin"
       , WithoutHaddocks $ T.pack . toFilePathNoTrailingSep . piToolsDir )
-    , ( "Local bin dir where stack installs executables (e.g. ~/.local/bin)"
+    , ( "Local bin dir where stack installs executables (e.g. ~/.local/bin (Unix-like OSs) or %APPDATA%\\local\\bin (Windows))"
       , "local-bin"
       , WithoutHaddocks $ view $ configL.to configLocalBin.to toFilePathNoTrailingSep.to T.pack)
     , ( "Extra include directories"
diff --git a/src/Stack/Runners.hs b/src/Stack/Runners.hs
--- a/src/Stack/Runners.hs
+++ b/src/Stack/Runners.hs
@@ -111,14 +111,10 @@
     -- Want to use Nix
     (True, False) -> do
       whenM getInContainer $ throwString "Cannot use Nix from within a Docker container"
-      inShell <- getInNixShell
-      if inShell
-        then do
-          isReexec <- view reExecL
-          if isReexec
-            then inner
-            else throwString "In Nix shell but reExecL is False"
-        else Nix.runShellAndExit
+      isReexec <- view reExecL
+      if isReexec
+      then inner
+      else Nix.runShellAndExit
 
     -- Want to use Docker
     (False, True) -> do
diff --git a/src/Stack/SDist.hs b/src/Stack/SDist.hs
--- a/src/Stack/SDist.hs
+++ b/src/Stack/SDist.hs
@@ -44,10 +44,11 @@
 import           Path
 import           Path.IO hiding (getModificationTime, getPermissions, withSystemTempDir)
 import           RIO.PrettyPrint
-import           Stack.Build (mkBaseConfigOpts, build)
+import           Stack.Build (mkBaseConfigOpts, build, buildLocalTargets)
 import           Stack.Build.Execute
 import           Stack.Build.Installed
 import           Stack.Build.Source (projectLocalPackages)
+import           Stack.Types.GhcPkgId
 import           Stack.Package
 import           Stack.SourceMap
 import           Stack.Types.Build
@@ -103,9 +104,27 @@
         tweakCabal = pvpBounds /= PvpBoundsNone
         pkgFp = toFilePath pkgDir
     lp <- readLocalPackage pkgDir
+    forM_ (packageSetupDeps (lpPackage lp)) $ \customSetupDeps ->
+        case NE.nonEmpty (map (T.pack . packageNameString) (Map.keys customSetupDeps)) of
+          Just nonEmptyDepTargets -> do
+            eres <- buildLocalTargets nonEmptyDepTargets
+            case eres of
+              Left err ->
+                logError $ "Error building custom-setup dependencies: " <> displayShow err
+              Right _ ->
+                return ()
+          Nothing ->
+            logWarn "unexpected empty custom-setup dependencies"
     sourceMap <- view $ envConfigL.to envConfigSourceMap
+
+    installMap <- toInstallMap sourceMap
+    (installedMap, _globalDumpPkgs, _snapshotDumpPkgs, _localDumpPkgs) <-
+        getInstalled installMap
+    let deps = Map.fromList [ (pid, ghcPkgId)
+                            | (_, Library pid ghcPkgId _) <- Map.elems installedMap]
+
     logInfo $ "Getting file list for " <> fromString pkgFp
-    (fileList, cabalfp) <- getSDistFileList lp
+    (fileList, cabalfp) <- getSDistFileList lp deps
     logInfo $ "Building sdist tarball for " <> fromString pkgFp
     files <- normalizeTarballPaths (map (T.unpack . stripCR . T.pack) (lines fileList))
 
@@ -305,8 +324,8 @@
         }
 
 -- | Returns a newline-separate list of paths, and the absolute path to the .cabal file.
-getSDistFileList :: HasEnvConfig env => LocalPackage -> RIO env (String, Path Abs File)
-getSDistFileList lp =
+getSDistFileList :: HasEnvConfig env => LocalPackage -> Map PackageIdentifier GhcPkgId -> RIO env (String, Path Abs File)
+getSDistFileList lp deps =
     withSystemTempDir (stackProgName <> "-sdist") $ \tmpdir -> do
         let bopts = defaultBuildOpts
         let boptsCli = defaultBuildOptsCLI
@@ -315,7 +334,7 @@
         withExecuteEnv bopts boptsCli baseConfigOpts locals
             [] [] [] Nothing -- provide empty list of globals. This is a hack around custom Setup.hs files
             $ \ee ->
-            withSingleContext ac ee task Nothing (Just "sdist") $ \_package cabalfp _pkgDir cabal _announce _outputType -> do
+            withSingleContext ac ee task deps (Just "sdist") $ \_package cabalfp _pkgDir cabal _announce _outputType -> do
                 let outFile = toFilePath tmpdir FP.</> "source-files-list"
                 cabal CloseOnException KeepTHLoading ["sdist", "--list-sources", outFile]
                 contents <- liftIO (S.readFile outFile)
diff --git a/src/Stack/Setup.hs b/src/Stack/Setup.hs
--- a/src/Stack/Setup.hs
+++ b/src/Stack/Setup.hs
@@ -465,9 +465,9 @@
         logWarn "For more information, see: https://github.com/commercialhaskell/stack/issues/648"
         logWarn ""
         pure True
-    | ghcVersion >= mkVersion [8, 11] -> do
+    | ghcVersion >= mkVersion [9, 1] -> do
         logWarn $
-          "Stack has not been tested with GHC versions above 8.10, and using " <>
+          "Stack has not been tested with GHC versions above 9.0, and using " <>
           fromString (versionString ghcVersion) <>
           ", this may fail"
         pure True
@@ -492,9 +492,9 @@
         logWarn "This invocation will most likely fail."
         logWarn "To fix this, either use an older version of Stack or a newer resolver"
         logWarn "Acceptable resolvers: lts-3.0/nightly-2015-05-05 or later"
-    | cabalVersion >= mkVersion [3, 3] ->
+    | cabalVersion >= mkVersion [3, 5] ->
         logWarn $
-          "Stack has not been tested with Cabal versions above 3.2, but version " <>
+          "Stack has not been tested with Cabal versions above 3.4, but version " <>
           fromString (versionString cabalVersion) <>
           " was found, this may fail"
     | otherwise -> pure ()
@@ -1115,23 +1115,19 @@
                            -> VersionCheck
                            -> Maybe String
                            -> RIO env Tool
-downloadAndInstallCompiler ghcBuild si wanted@WCGhc{} versionCheck mbindistURL = do
+downloadAndInstallCompiler ghcBuild si wanted@(WCGhc version) versionCheck mbindistURL = do
     ghcVariant <- view ghcVariantL
     (selectedVersion, downloadInfo) <- case mbindistURL of
         Just bindistURL -> do
             case ghcVariant of
                 GHCCustom _ -> return ()
                 _ -> throwM RequireCustomGHCVariant
-            case wanted of
-                WCGhc version ->
-                    return (version, GHCDownloadInfo mempty mempty DownloadInfo
-                             { downloadInfoUrl = T.pack bindistURL
-                             , downloadInfoContentLength = Nothing
-                             , downloadInfoSha1 = Nothing
-                             , downloadInfoSha256 = Nothing
-                             })
-                _ ->
-                    throwM WantedMustBeGHC
+            return (version, GHCDownloadInfo mempty mempty DownloadInfo
+                     { downloadInfoUrl = T.pack bindistURL
+                     , downloadInfoContentLength = Nothing
+                     , downloadInfoSha1 = Nothing
+                     , downloadInfoSha256 = Nothing
+                     })
         _ -> do
             ghcKey <- getGhcKey ghcBuild
             case Map.lookup ghcKey $ siGHCs si of
@@ -1245,6 +1241,7 @@
         Platform X86_64                Cabal.Windows -> return "windows64"
         Platform Arm                   Cabal.Linux   -> return "linux-armv7"
         Platform AArch64               Cabal.Linux   -> return "linux-aarch64"
+        Platform Sparc                 Cabal.Linux   -> return "linux-sparc"
         Platform arch os -> throwM $ UnsupportedSetupCombo os arch
 
 downloadOrUseLocal
diff --git a/src/Stack/Types/Build.hs b/src/Stack/Types/Build.hs
--- a/src/Stack/Types/Build.hs
+++ b/src/Stack/Types/Build.hs
@@ -356,9 +356,9 @@
      logLocations ++
      (if null bss
           then ""
-          else "\n\n" ++ doubleIndent (map T.unpack bss))
+          else "\n\n" ++ removeTrailingSpaces (map T.unpack bss))
    where
-    doubleIndent = dropWhileEnd isSpace . unlines . fmap (\line -> "    " ++ line)
+    removeTrailingSpaces = dropWhileEnd isSpace . unlines
     dropQuotes = filter ('\"' /=)
 
 instance Exception StackBuildException
diff --git a/src/Stack/Types/Config.hs b/src/Stack/Types/Config.hs
--- a/src/Stack/Types/Config.hs
+++ b/src/Stack/Types/Config.hs
@@ -33,7 +33,6 @@
   ,Config(..)
   ,HasConfig(..)
   ,askLatestSnapshotUrl
-  ,explicitSetupDeps
   ,configProjectRoot
   -- ** BuildConfig & HasBuildConfig
   ,BuildConfig(..)
@@ -321,6 +320,8 @@
          -- ^ --extra-include-dirs arguments
          ,configExtraLibDirs        :: ![FilePath]
          -- ^ --extra-lib-dirs arguments
+         ,configCustomPreprocessorExts :: ![Text]
+         -- ^ List of custom preprocessors to complete the hard coded ones
          ,configConcurrentTests     :: !Bool
          -- ^ Run test suites concurrently
          ,configTemplateParams      :: !(Map Text Text)
@@ -342,8 +343,6 @@
          -- ^ How PVP upper bounds should be added to packages
          ,configModifyCodePage      :: !Bool
          -- ^ Force the code page to UTF-8 on Windows
-         ,configExplicitSetupDeps   :: !(Map (Maybe PackageName) Bool)
-         -- ^ See 'explicitSetupDeps'. 'Nothing' provides the default value.
          ,configRebuildGhcOptions   :: !Bool
          -- ^ Rebuild on GHC options changes
          ,configApplyGhcOptions     :: !ApplyGhcOptions
@@ -801,6 +800,8 @@
     -- ^ See: 'configExtraIncludeDirs'
     ,configMonoidExtraLibDirs        :: ![FilePath]
     -- ^ See: 'configExtraLibDirs'
+    ,configMonoidCustomPreprocessorExts :: ![Text]
+    -- ^ See: 'configCustomPreprocessorExts'
     , configMonoidOverrideGccPath    :: !(First (Path Abs File))
     -- ^ Allow users to override the path to gcc
     ,configMonoidOverrideHpack       :: !(First FilePath)
@@ -835,8 +836,6 @@
     -- ^ See 'configPvpBounds'
     ,configMonoidModifyCodePage      :: !FirstTrue
     -- ^ See 'configModifyCodePage'
-    ,configMonoidExplicitSetupDeps   :: !(Map (Maybe PackageName) Bool)
-    -- ^ See 'configExplicitSetupDeps'
     ,configMonoidRebuildGhcOptions   :: !FirstFalse
     -- ^ See 'configMonoidRebuildGhcOptions'
     ,configMonoidApplyGhcOptions     :: !(First ApplyGhcOptions)
@@ -920,6 +919,7 @@
         obj ..:?  configMonoidExtraIncludeDirsName ..!= []
     configMonoidExtraLibDirs <- map (toFilePath rootDir FilePath.</>) <$>
         obj ..:?  configMonoidExtraLibDirsName ..!= []
+    configMonoidCustomPreprocessorExts <- obj ..:?  configMonoidCustomPreprocessorExtsName ..!= []
     configMonoidOverrideGccPath <- First <$> obj ..:? configMonoidOverrideGccPathName
     configMonoidOverrideHpack <- First <$> obj ..:? configMonoidOverrideHpackName
     configMonoidConcurrentTests <- First <$> obj ..:? configMonoidConcurrentTestsName
@@ -964,9 +964,6 @@
     configMonoidLocalProgramsBase <- First <$> obj ..:? configMonoidLocalProgramsBaseName
     configMonoidPvpBounds <- First <$> obj ..:? configMonoidPvpBoundsName
     configMonoidModifyCodePage <- FirstTrue <$> obj ..:? configMonoidModifyCodePageName
-    configMonoidExplicitSetupDeps <-
-        (obj ..:? configMonoidExplicitSetupDepsName ..!= mempty)
-        >>= fmap Map.fromList . mapM handleExplicitSetupDep . Map.toList
     configMonoidRebuildGhcOptions <- FirstFalse <$> obj ..:? configMonoidRebuildGhcOptionsName
     configMonoidApplyGhcOptions <- First <$> obj ..:? configMonoidApplyGhcOptionsName
     configMonoidAllowNewer <- First <$> obj ..:? configMonoidAllowNewerName
@@ -995,16 +992,6 @@
     configMonoidStackDeveloperMode <- First <$> obj ..:? configMonoidStackDeveloperModeName
 
     return ConfigMonoid {..}
-  where
-    handleExplicitSetupDep :: (Monad m, MonadFail m) => (Text, Bool) -> m (Maybe PackageName, Bool)
-    handleExplicitSetupDep (name', b) = do
-        name <-
-            if name' == "*"
-                then return Nothing
-                else case parsePackageName $ T.unpack name' of
-                        Nothing -> fail $ "Invalid package name: " ++ show name'
-                        Just x -> return $ Just x
-        return (name, b)
 
 configMonoidWorkDirName :: Text
 configMonoidWorkDirName = "work-dir"
@@ -1066,6 +1053,9 @@
 configMonoidExtraLibDirsName :: Text
 configMonoidExtraLibDirsName = "extra-lib-dirs"
 
+configMonoidCustomPreprocessorExtsName  :: Text
+configMonoidCustomPreprocessorExtsName  = "custom-preprocessor-extensions"
+
 configMonoidOverrideGccPathName :: Text
 configMonoidOverrideGccPathName = "with-gcc"
 
@@ -1111,9 +1101,6 @@
 configMonoidModifyCodePageName :: Text
 configMonoidModifyCodePageName = "modify-code-page"
 
-configMonoidExplicitSetupDepsName :: Text
-configMonoidExplicitSetupDepsName = "explicit-setup-deps"
-
 configMonoidRebuildGhcOptionsName :: Text
 configMonoidRebuildGhcOptionsName = "rebuild-ghc-options"
 
@@ -1775,16 +1762,6 @@
     toJSON (pvpBoundsText typ <> (if asRevision then "-revision" else ""))
 instance FromJSON PvpBounds where
   parseJSON = withText "PvpBounds" (either fail return . parsePvpBounds)
-
--- | Provide an explicit list of package dependencies when running a custom Setup.hs
-explicitSetupDeps :: (MonadReader env m, HasConfig env) => PackageName -> m Bool
-explicitSetupDeps name = do
-    m <- view $ configL.to configExplicitSetupDeps
-    return $
-      Map.findWithDefault
-        (Map.findWithDefault False Nothing m)
-        (Just name)
-        m
 
 -- | Data passed into Docker container for the Docker entrypoint's use
 newtype DockerEntrypoint = DockerEntrypoint
diff --git a/src/Stack/Upload.hs b/src/Stack/Upload.hs
--- a/src/Stack/Upload.hs
+++ b/src/Stack/Upload.hs
@@ -35,6 +35,7 @@
                                                         partBS, partLBS,
                                                         applyDigestAuth,
                                                         displayDigestAuthException)
+import           Stack.Options.UploadParser
 import           Stack.Types.Config
 import           System.Directory                      (createDirectoryIfMissing,
                                                         removeFile, renameFile)
@@ -159,11 +160,17 @@
 uploadBytes :: String -- ^ Hackage base URL
             -> HackageCreds
             -> String -- ^ tar file name
+            -> UploadVariant
             -> L.ByteString -- ^ tar file contents
             -> IO ()
-uploadBytes baseUrl creds tarName bytes = do
+uploadBytes baseUrl creds tarName uploadVariant bytes = do
     let req1 = setRequestHeader "Accept" ["text/plain"]
-               (fromString $ baseUrl <> "packages/")
+               (fromString $ baseUrl
+                          <> "packages/"
+                          <> case uploadVariant of
+                               Publishing -> ""
+                               Candidate -> "candidates/"
+               )
         formData = [partFileRequestBody "package" tarName (RequestBodyLBS bytes)]
     req2 <- formDataBody formData req1
     req3 <- applyCreds creds req2
@@ -200,8 +207,10 @@
 upload :: String -- ^ Hackage base URL
        -> HackageCreds
        -> FilePath
+       -> UploadVariant
        -> IO ()
-upload baseUrl creds fp = uploadBytes baseUrl creds (takeFileName fp) =<< L.readFile fp
+upload baseUrl creds fp uploadVariant =
+  uploadBytes baseUrl creds (takeFileName fp) uploadVariant =<< L.readFile fp
 
 uploadRevision :: String -- ^ Hackage base URL
                -> HackageCreds
diff --git a/src/main/Main.hs b/src/main/Main.hs
--- a/src/main/Main.hs
+++ b/src/main/Main.hs
@@ -50,6 +50,7 @@
 import           Stack.FileWatch
 import           Stack.Ghci
 import           Stack.Hoogle
+import           Stack.List
 import           Stack.Ls
 import qualified Stack.IDE as IDE
 import           Stack.Init
@@ -67,6 +68,7 @@
 import           Stack.Options.NixParser
 import           Stack.Options.ScriptParser
 import           Stack.Options.SDistParser
+import           Stack.Options.UploadParser
 import           Stack.Options.Utils
 import qualified Stack.Path
 import           Stack.Runners
@@ -262,7 +264,7 @@
             "upload"
             "Upload a package to Hackage"
             uploadCmd
-            sdistOptsParser
+            uploadOptsParser
         addCommand'
             "sdist"
             "Create source distribution tarballs"
@@ -349,6 +351,10 @@
                     "Query general build information (experimental)"
                     queryCmd
                     (many $ strArgument $ metavar "SELECTOR...")
+        addCommand' "list"
+                    "List package id's in snapshot (experimental)"
+                    listCmd
+                    (many $ strArgument $ metavar "PACKAGE")
         addSubCommands'
             "ide"
             "IDE-specific commands"
@@ -548,7 +554,7 @@
 -- | Helper for build and install commands
 buildCmd :: BuildOptsCLI -> RIO Runner ()
 buildCmd opts = do
-  when (any (("-prof" `elem`) . either (const []) id . parseArgs Escaping) (boptsCLIGhcOptions opts)) $ do
+  when (any (("-prof" `elem`) . fromRight [] . parseArgs Escaping) (boptsCLIGhcOptions opts)) $ do
     logError "Error: When building with stack, you should not use the -prof GHC option"
     logError "Instead, please use --library-profiling and --executable-profiling"
     logError "See: https://github.com/commercialhaskell/stack/issues/1015"
@@ -613,20 +619,21 @@
         upgradeOpts'
 
 -- | Upload to Hackage
-uploadCmd :: SDistOpts -> RIO Runner ()
-uploadCmd (SDistOpts [] _ _ _ _) = do
+uploadCmd :: UploadOpts -> RIO Runner ()
+uploadCmd (UploadOpts (SDistOpts [] _ _ _ _) _) = do
     prettyErrorL
         [ flow "To upload the current package, please run"
         , PP.style Shell "stack upload ."
         , flow "(with the period at the end)"
         ]
     liftIO exitFailure
-uploadCmd sdistOpts = do
+uploadCmd uploadOpts = do
     let partitionM _ [] = return ([], [])
         partitionM f (x:xs) = do
             r <- f x
             (as, bs) <- partitionM f xs
             return $ if r then (x:as, bs) else (as, x:bs)
+        sdistOpts = uoptsSDistOpts uploadOpts
     (files, nonFiles) <- liftIO $ partitionM D.doesFileExist (sdoptsDirsToWorkWith sdistOpts)
     (dirs, invalid) <- liftIO $ partitionM D.doesDirectoryExist nonFiles
     withConfig YesReexec $ withDefaultEnvConfig $ do
@@ -647,24 +654,22 @@
             exitFailure
         config <- view configL
         let hackageUrl = T.unpack $ configHackageBaseUrl config
+            uploadVariant = uoptsUploadVariant uploadOpts
         getCreds <- liftIO $ memoizeRef $ Upload.loadCreds config
         mapM_ (resolveFile' >=> checkSDistTarball sdistOpts) files
-        forM_
-            files
-            (\file ->
-                  do tarFile <- resolveFile' file
-                     liftIO $ do
-                       creds <- runMemoized getCreds
-                       Upload.upload hackageUrl creds (toFilePath tarFile))
-        unless (null dirs) $
-            forM_ dirs $ \dir -> do
-                pkgDir <- resolveDir' dir
-                (tarName, tarBytes, mcabalRevision) <- getSDistTarball (sdoptsPvpBounds sdistOpts) pkgDir
-                checkSDistTarball' sdistOpts tarName tarBytes
-                liftIO $ do
-                  creds <- runMemoized getCreds
-                  Upload.uploadBytes hackageUrl creds tarName tarBytes
-                  forM_ mcabalRevision $ uncurry $ Upload.uploadRevision hackageUrl creds
+        forM_ files $ \file -> do
+            tarFile <- resolveFile' file
+            liftIO $ do
+              creds <- runMemoized getCreds
+              Upload.upload hackageUrl creds (toFilePath tarFile) uploadVariant
+        forM_ dirs $ \dir -> do
+            pkgDir <- resolveDir' dir
+            (tarName, tarBytes, mcabalRevision) <- getSDistTarball (sdoptsPvpBounds sdistOpts) pkgDir
+            checkSDistTarball' sdistOpts tarName tarBytes
+            liftIO $ do
+              creds <- runMemoized getCreds
+              Upload.uploadBytes hackageUrl creds tarName uploadVariant tarBytes
+              forM_ mcabalRevision $ uncurry $ Upload.uploadRevision hackageUrl creds
 
 sdistCmd :: SDistOpts -> RIO Runner ()
 sdistCmd sdistOpts =
@@ -850,7 +855,17 @@
 queryCmd :: [String] -> RIO Runner ()
 queryCmd selectors = withConfig YesReexec $ withDefaultEnvConfig $ queryBuildInfo $ map T.pack selectors
 
--- | Generate a combined HPC report
+-- | List packages
+listCmd :: [String] -> RIO Runner ()
+listCmd names = withConfig NoReexec $ do
+    mresolver <- view $ globalOptsL.to globalResolver
+    mSnapshot <- forM mresolver $ \resolver -> do
+      concrete <- makeConcreteResolver resolver
+      loc <- completeSnapshotLocation concrete
+      loadSnapshot loc
+    listPackages mSnapshot names
+
+-- | generate a combined HPC report
 hpcReportCmd :: HpcReportOpts -> RIO Runner ()
 hpcReportCmd hropts = do
     let (tixFiles, targetNames) = partition (".tix" `T.isSuffixOf`) (hroptsInputs hropts)
diff --git a/stack.cabal b/stack.cabal
--- a/stack.cabal
+++ b/stack.cabal
@@ -1,6 +1,6 @@
 cabal-version:      2.0
 name:               stack
-version:            2.5.1.1
+version:            2.7.1
 license:            BSD3
 license-file:       LICENSE
 maintainer:         manny@fpcomplete.com
@@ -68,8 +68,8 @@
 
 custom-setup
     setup-depends:
-        Cabal >=3.0.0.0,
-        base >=4.10 && <5,
+        Cabal >=3.2.1.0,
+        base >=4.13 && <5,
         filepath >=1.4.2.1
 
 flag developer-mode
@@ -148,6 +148,7 @@
         Stack.Hoogle
         Stack.IDE
         Stack.Init
+        Stack.List
         Stack.Ls
         Stack.Lock
         Stack.New
@@ -175,6 +176,7 @@
         Stack.Options.ScriptParser
         Stack.Options.SDistParser
         Stack.Options.TestParser
+        Stack.Options.UploadParser
         Stack.Options.Utils
         Stack.Package
         Stack.PackageDump
@@ -228,90 +230,90 @@
         -fwarn-identities
 
     build-depends:
-        Cabal >=3.0.0.0,
-        aeson >=1.4.6.0,
+        Cabal >=3.2.1.0,
+        aeson >=1.5.6.0,
         annotated-wl-pprint >=0.7.0,
-        ansi-terminal >=0.9.1,
-        array >=0.5.3.0,
-        async >=2.2.2,
-        attoparsec >=0.13.2.3,
+        ansi-terminal >=0.10.3,
+        array >=0.5.4.0,
+        async >=2.2.3,
+        attoparsec >=0.13.2.5,
         base >=4.10 && <5,
-        base64-bytestring >=1.0.0.3,
-        bytestring >=0.10.8.2,
+        base64-bytestring >=1.1.0.0,
+        bytestring >=0.10.12.0,
         casa-client >=0.0.1,
         casa-types >=0.0.1,
         colour >=2.3.5,
-        conduit >=1.3.1.2,
-        conduit-extra >=1.3.4,
-        containers >=0.6.0.1,
-        cryptonite >=0.25,
+        conduit >=1.3.4.1,
+        conduit-extra >=1.3.5,
+        containers >=0.6.2.1,
+        cryptonite >=0.27,
         cryptonite-conduit >=0.2.2,
         deepseq >=1.4.4.0,
-        directory >=1.3.3.0,
-        echo >=0.1.3,
+        directory >=1.3.6.0,
+        echo >=0.1.4,
         exceptions >=0.10.4,
-        extra >=1.6.19,
-        file-embed >=0.0.11.1,
+        extra >=1.7.9,
+        file-embed >=0.0.13.0,
         filelock >=0.1.1.5,
         filepath >=1.4.2.1,
         fsnotify >=0.3.0.1,
-        generic-deriving >=1.12.4,
-        hackage-security >=0.5.3.0,
-        hashable >=1.2.7.0,
-        hi-file-parser >=0.1.0.0,
-        hpack >=0.33.0,
-        hpc >=0.6.0.3,
-        http-client >=0.6.4,
+        generic-deriving >=1.13.1,
+        hackage-security >=0.6.0.1,
+        hashable >=1.3.0.0,
+        hi-file-parser >=0.1.2.0,
+        hpack >=0.34.4,
+        hpc >=0.6.1.0,
+        http-client >=0.6.4.1,
         http-client-tls >=0.3.5.3,
-        http-conduit >=2.3.7.3,
+        http-conduit >=2.3.8,
         http-download >=0.2.0.0,
         http-types >=0.12.3,
-        memory >=0.14.18,
-        microlens >=0.4.10,
+        memory >=0.15.0,
+        microlens >=0.4.11.2,
         mintty >=0.1.2,
         mono-traversable >=1.0.15.1,
         mtl >=2.2.2,
         mustache >=2.3.1,
-        neat-interpolation >=0.3.2.6,
-        network-uri >=2.6.2.0,
+        neat-interpolation >=0.5.1.2,
+        network-uri >=2.6.4.1,
         open-browser >=0.2.1.0,
         optparse-applicative >=0.14.3.0,
         pantry >=0.5.1.3,
-        path >=0.6.1,
-        path-io >=1.4.2,
-        persistent >=2.9.2,
-        persistent-sqlite >=2.9.3,
-        persistent-template >=2.6.0,
+        path >=0.7.0,
+        path-io >=1.6.2,
+        persistent >=2.11.0.4,
+        persistent-sqlite >=2.11.1.0,
+        persistent-template >=2.9.1.0,
         pretty >=1.1.3.6,
-        primitive >=0.6.4.0,
-        process >=1.6.5.0,
-        project-template >=0.2.0.1,
+        primitive >=0.7.1.0,
+        process >=1.6.9.0,
+        project-template >=0.2.1.0,
         regex-applicative-text >=0.1.0.1,
-        retry >=0.8.1.0,
+        retry >=0.8.1.2,
         rio >=0.1.18.0,
         rio-prettyprint >=0.1.1.0,
-        semigroups >=0.18.5,
-        split >=0.2.3.3,
+        semigroups >=0.19.1,
+        split >=0.2.3.4,
         stm >=2.5.0.0,
-        streaming-commons >=0.2.1.2,
+        streaming-commons >=0.2.2.1,
         tar >=0.5.1.1,
-        template-haskell >=2.14.0.0,
+        template-haskell >=2.16.0.0,
         temporary >=1.3,
-        text >=1.2.3.1,
+        text >=1.2.4.1,
         text-metrics >=0.3.0,
         th-reify-many >=0.1.9,
-        time >=1.8.0.2,
-        tls >=1.4.1,
+        time >=1.9.3,
+        tls >=1.5.5,
         transformers >=0.5.6.2,
         typed-process >=0.2.6.0,
-        unicode-transforms >=0.3.6,
-        unix-compat >=0.5.2,
-        unliftio >=0.2.12,
-        unordered-containers >=0.2.10.0,
+        unicode-transforms >=0.3.7.1,
+        unix-compat >=0.5.3,
+        unliftio >=0.2.14,
+        unordered-containers >=0.2.13.0,
         vector >=0.12.1.2,
-        yaml >=0.11.2.0,
+        yaml >=0.11.5.0,
         zip-archive >=0.4.1,
-        zlib >=0.6.2.1
+        zlib >=0.6.2.3
 
     if os(windows)
         cpp-options:   -DWINDOWS
@@ -355,91 +357,91 @@
         -threaded -rtsopts
 
     build-depends:
-        Cabal >=3.0.0.0,
-        aeson >=1.4.6.0,
+        Cabal >=3.2.1.0,
+        aeson >=1.5.6.0,
         annotated-wl-pprint >=0.7.0,
-        ansi-terminal >=0.9.1,
-        array >=0.5.3.0,
-        async >=2.2.2,
-        attoparsec >=0.13.2.3,
+        ansi-terminal >=0.10.3,
+        array >=0.5.4.0,
+        async >=2.2.3,
+        attoparsec >=0.13.2.5,
         base >=4.10 && <5,
-        base64-bytestring >=1.0.0.3,
-        bytestring >=0.10.8.2,
+        base64-bytestring >=1.1.0.0,
+        bytestring >=0.10.12.0,
         casa-client >=0.0.1,
         casa-types >=0.0.1,
         colour >=2.3.5,
-        conduit >=1.3.1.2,
-        conduit-extra >=1.3.4,
-        containers >=0.6.0.1,
-        cryptonite >=0.25,
+        conduit >=1.3.4.1,
+        conduit-extra >=1.3.5,
+        containers >=0.6.2.1,
+        cryptonite >=0.27,
         cryptonite-conduit >=0.2.2,
         deepseq >=1.4.4.0,
-        directory >=1.3.3.0,
-        echo >=0.1.3,
+        directory >=1.3.6.0,
+        echo >=0.1.4,
         exceptions >=0.10.4,
-        extra >=1.6.19,
-        file-embed >=0.0.11.1,
+        extra >=1.7.9,
+        file-embed >=0.0.13.0,
         filelock >=0.1.1.5,
         filepath >=1.4.2.1,
         fsnotify >=0.3.0.1,
-        generic-deriving >=1.12.4,
-        hackage-security >=0.5.3.0,
-        hashable >=1.2.7.0,
-        hi-file-parser >=0.1.0.0,
-        hpack >=0.33.0,
-        hpc >=0.6.0.3,
-        http-client >=0.6.4,
+        generic-deriving >=1.13.1,
+        hackage-security >=0.6.0.1,
+        hashable >=1.3.0.0,
+        hi-file-parser >=0.1.2.0,
+        hpack >=0.34.4,
+        hpc >=0.6.1.0,
+        http-client >=0.6.4.1,
         http-client-tls >=0.3.5.3,
-        http-conduit >=2.3.7.3,
+        http-conduit >=2.3.8,
         http-download >=0.2.0.0,
         http-types >=0.12.3,
-        memory >=0.14.18,
-        microlens >=0.4.10,
+        memory >=0.15.0,
+        microlens >=0.4.11.2,
         mintty >=0.1.2,
         mono-traversable >=1.0.15.1,
         mtl >=2.2.2,
         mustache >=2.3.1,
-        neat-interpolation >=0.3.2.6,
-        network-uri >=2.6.2.0,
+        neat-interpolation >=0.5.1.2,
+        network-uri >=2.6.4.1,
         open-browser >=0.2.1.0,
         optparse-applicative >=0.14.3.0,
         pantry >=0.5.1.3,
-        path >=0.6.1,
-        path-io >=1.4.2,
-        persistent >=2.9.2,
-        persistent-sqlite >=2.9.3,
-        persistent-template >=2.6.0,
+        path >=0.7.0,
+        path-io >=1.6.2,
+        persistent >=2.11.0.4,
+        persistent-sqlite >=2.11.1.0,
+        persistent-template >=2.9.1.0,
         pretty >=1.1.3.6,
-        primitive >=0.6.4.0,
-        process >=1.6.5.0,
-        project-template >=0.2.0.1,
+        primitive >=0.7.1.0,
+        process >=1.6.9.0,
+        project-template >=0.2.1.0,
         regex-applicative-text >=0.1.0.1,
-        retry >=0.8.1.0,
+        retry >=0.8.1.2,
         rio >=0.1.18.0,
         rio-prettyprint >=0.1.1.0,
-        semigroups >=0.18.5,
-        split >=0.2.3.3,
+        semigroups >=0.19.1,
+        split >=0.2.3.4,
         stack -any,
         stm >=2.5.0.0,
-        streaming-commons >=0.2.1.2,
+        streaming-commons >=0.2.2.1,
         tar >=0.5.1.1,
-        template-haskell >=2.14.0.0,
+        template-haskell >=2.16.0.0,
         temporary >=1.3,
-        text >=1.2.3.1,
+        text >=1.2.4.1,
         text-metrics >=0.3.0,
         th-reify-many >=0.1.9,
-        time >=1.8.0.2,
-        tls >=1.4.1,
+        time >=1.9.3,
+        tls >=1.5.5,
         transformers >=0.5.6.2,
         typed-process >=0.2.6.0,
-        unicode-transforms >=0.3.6,
-        unix-compat >=0.5.2,
-        unliftio >=0.2.12,
-        unordered-containers >=0.2.10.0,
+        unicode-transforms >=0.3.7.1,
+        unix-compat >=0.5.3,
+        unliftio >=0.2.14,
+        unordered-containers >=0.2.13.0,
         vector >=0.12.1.2,
-        yaml >=0.11.2.0,
+        yaml >=0.11.5.0,
         zip-archive >=0.4.1,
-        zlib >=0.6.2.1
+        zlib >=0.6.2.3
 
     if os(windows)
         cpp-options:   -DWINDOWS
@@ -461,8 +463,8 @@
     if !flag(disable-git-info)
         cpp-options:   -DUSE_GIT_INFO
         build-depends:
-            githash >=0.1.3.3,
-            optparse-simple >=0.1.1.2
+            githash >=0.1.5.0,
+            optparse-simple >=0.1.1.3
 
     if flag(hide-dependency-versions)
         cpp-options: -DHIDE_DEP_VERSIONS
@@ -484,92 +486,92 @@
         -threaded -rtsopts -with-rtsopts=-N
 
     build-depends:
-        Cabal >=3.0.0.0,
-        aeson >=1.4.6.0,
+        Cabal >=3.2.1.0,
+        aeson >=1.5.6.0,
         annotated-wl-pprint >=0.7.0,
-        ansi-terminal >=0.9.1,
-        array >=0.5.3.0,
-        async >=2.2.2,
-        attoparsec >=0.13.2.3,
+        ansi-terminal >=0.10.3,
+        array >=0.5.4.0,
+        async >=2.2.3,
+        attoparsec >=0.13.2.5,
         base >=4.10 && <5,
-        base64-bytestring >=1.0.0.3,
-        bytestring >=0.10.8.2,
+        base64-bytestring >=1.1.0.0,
+        bytestring >=0.10.12.0,
         casa-client >=0.0.1,
         casa-types >=0.0.1,
         colour >=2.3.5,
-        conduit >=1.3.1.2,
-        conduit-extra >=1.3.4,
-        containers >=0.6.0.1,
-        cryptonite >=0.25,
+        conduit >=1.3.4.1,
+        conduit-extra >=1.3.5,
+        containers >=0.6.2.1,
+        cryptonite >=0.27,
         cryptonite-conduit >=0.2.2,
         deepseq >=1.4.4.0,
-        directory >=1.3.3.0,
-        echo >=0.1.3,
+        directory >=1.3.6.0,
+        echo >=0.1.4,
         exceptions >=0.10.4,
-        extra >=1.6.19,
-        file-embed >=0.0.11.1,
+        extra >=1.7.9,
+        file-embed >=0.0.13.0,
         filelock >=0.1.1.5,
         filepath >=1.4.2.1,
         fsnotify >=0.3.0.1,
-        generic-deriving >=1.12.4,
-        hackage-security >=0.5.3.0,
-        hashable >=1.2.7.0,
-        hi-file-parser >=0.1.0.0,
-        hpack >=0.33.0,
-        hpc >=0.6.0.3,
-        hspec >=2.7.1,
-        http-client >=0.6.4,
+        generic-deriving >=1.13.1,
+        hackage-security >=0.6.0.1,
+        hashable >=1.3.0.0,
+        hi-file-parser >=0.1.2.0,
+        hpack >=0.34.4,
+        hpc >=0.6.1.0,
+        hspec >=2.7.8,
+        http-client >=0.6.4.1,
         http-client-tls >=0.3.5.3,
-        http-conduit >=2.3.7.3,
+        http-conduit >=2.3.8,
         http-download >=0.2.0.0,
         http-types >=0.12.3,
-        memory >=0.14.18,
-        microlens >=0.4.10,
+        memory >=0.15.0,
+        microlens >=0.4.11.2,
         mintty >=0.1.2,
         mono-traversable >=1.0.15.1,
         mtl >=2.2.2,
         mustache >=2.3.1,
-        neat-interpolation >=0.3.2.6,
-        network-uri >=2.6.2.0,
+        neat-interpolation >=0.5.1.2,
+        network-uri >=2.6.4.1,
         open-browser >=0.2.1.0,
         optparse-applicative >=0.14.3.0,
         optparse-generic >=1.3.1,
         pantry >=0.5.1.3,
-        path >=0.6.1,
-        path-io >=1.4.2,
-        persistent >=2.9.2,
-        persistent-sqlite >=2.9.3,
-        persistent-template >=2.6.0,
+        path >=0.7.0,
+        path-io >=1.6.2,
+        persistent >=2.11.0.4,
+        persistent-sqlite >=2.11.1.0,
+        persistent-template >=2.9.1.0,
         pretty >=1.1.3.6,
-        primitive >=0.6.4.0,
-        process >=1.6.5.0,
-        project-template >=0.2.0.1,
+        primitive >=0.7.1.0,
+        process >=1.6.9.0,
+        project-template >=0.2.1.0,
         regex-applicative-text >=0.1.0.1,
-        retry >=0.8.1.0,
+        retry >=0.8.1.2,
         rio >=0.1.18.0,
         rio-prettyprint >=0.1.1.0,
-        semigroups >=0.18.5,
-        split >=0.2.3.3,
+        semigroups >=0.19.1,
+        split >=0.2.3.4,
         stm >=2.5.0.0,
-        streaming-commons >=0.2.1.2,
+        streaming-commons >=0.2.2.1,
         tar >=0.5.1.1,
-        template-haskell >=2.14.0.0,
+        template-haskell >=2.16.0.0,
         temporary >=1.3,
-        text >=1.2.3.1,
+        text >=1.2.4.1,
         text-metrics >=0.3.0,
         th-reify-many >=0.1.9,
-        time >=1.8.0.2,
-        tls >=1.4.1,
+        time >=1.9.3,
+        tls >=1.5.5,
         transformers >=0.5.6.2,
         typed-process >=0.2.6.0,
-        unicode-transforms >=0.3.6,
-        unix-compat >=0.5.2,
-        unliftio >=0.2.12,
-        unordered-containers >=0.2.10.0,
+        unicode-transforms >=0.3.7.1,
+        unix-compat >=0.5.3,
+        unliftio >=0.2.14,
+        unordered-containers >=0.2.13.0,
         vector >=0.12.1.2,
-        yaml >=0.11.2.0,
+        yaml >=0.11.5.0,
         zip-archive >=0.4.1,
-        zlib >=0.6.2.1
+        zlib >=0.6.2.3
 
     if os(windows)
         cpp-options:   -DWINDOWS
@@ -619,95 +621,95 @@
         -threaded
 
     build-depends:
-        Cabal >=3.0.0.0,
-        QuickCheck >=2.13.2,
-        aeson >=1.4.6.0,
+        Cabal >=3.2.1.0,
+        QuickCheck >=2.14.2,
+        aeson >=1.5.6.0,
         annotated-wl-pprint >=0.7.0,
-        ansi-terminal >=0.9.1,
-        array >=0.5.3.0,
-        async >=2.2.2,
-        attoparsec >=0.13.2.3,
+        ansi-terminal >=0.10.3,
+        array >=0.5.4.0,
+        async >=2.2.3,
+        attoparsec >=0.13.2.5,
         base >=4.10 && <5,
-        base64-bytestring >=1.0.0.3,
-        bytestring >=0.10.8.2,
+        base64-bytestring >=1.1.0.0,
+        bytestring >=0.10.12.0,
         casa-client >=0.0.1,
         casa-types >=0.0.1,
         colour >=2.3.5,
-        conduit >=1.3.1.2,
-        conduit-extra >=1.3.4,
-        containers >=0.6.0.1,
-        cryptonite >=0.25,
+        conduit >=1.3.4.1,
+        conduit-extra >=1.3.5,
+        containers >=0.6.2.1,
+        cryptonite >=0.27,
         cryptonite-conduit >=0.2.2,
         deepseq >=1.4.4.0,
-        directory >=1.3.3.0,
-        echo >=0.1.3,
+        directory >=1.3.6.0,
+        echo >=0.1.4,
         exceptions >=0.10.4,
-        extra >=1.6.19,
-        file-embed >=0.0.11.1,
+        extra >=1.7.9,
+        file-embed >=0.0.13.0,
         filelock >=0.1.1.5,
         filepath >=1.4.2.1,
         fsnotify >=0.3.0.1,
-        generic-deriving >=1.12.4,
-        hackage-security >=0.5.3.0,
-        hashable >=1.2.7.0,
-        hi-file-parser >=0.1.0.0,
-        hpack >=0.33.0,
-        hpc >=0.6.0.3,
-        hspec >=2.7.1,
-        http-client >=0.6.4,
+        generic-deriving >=1.13.1,
+        hackage-security >=0.6.0.1,
+        hashable >=1.3.0.0,
+        hi-file-parser >=0.1.2.0,
+        hpack >=0.34.4,
+        hpc >=0.6.1.0,
+        hspec >=2.7.8,
+        http-client >=0.6.4.1,
         http-client-tls >=0.3.5.3,
-        http-conduit >=2.3.7.3,
+        http-conduit >=2.3.8,
         http-download >=0.2.0.0,
         http-types >=0.12.3,
-        memory >=0.14.18,
-        microlens >=0.4.10,
+        memory >=0.15.0,
+        microlens >=0.4.11.2,
         mintty >=0.1.2,
         mono-traversable >=1.0.15.1,
         mtl >=2.2.2,
         mustache >=2.3.1,
-        neat-interpolation >=0.3.2.6,
-        network-uri >=2.6.2.0,
+        neat-interpolation >=0.5.1.2,
+        network-uri >=2.6.4.1,
         open-browser >=0.2.1.0,
         optparse-applicative >=0.14.3.0,
         pantry >=0.5.1.3,
-        path >=0.6.1,
-        path-io >=1.4.2,
-        persistent >=2.9.2,
-        persistent-sqlite >=2.9.3,
-        persistent-template >=2.6.0,
+        path >=0.7.0,
+        path-io >=1.6.2,
+        persistent >=2.11.0.4,
+        persistent-sqlite >=2.11.1.0,
+        persistent-template >=2.9.1.0,
         pretty >=1.1.3.6,
-        primitive >=0.6.4.0,
-        process >=1.6.5.0,
-        project-template >=0.2.0.1,
+        primitive >=0.7.1.0,
+        process >=1.6.9.0,
+        project-template >=0.2.1.0,
         raw-strings-qq >=1.1,
         regex-applicative-text >=0.1.0.1,
-        retry >=0.8.1.0,
+        retry >=0.8.1.2,
         rio >=0.1.18.0,
         rio-prettyprint >=0.1.1.0,
-        semigroups >=0.18.5,
-        smallcheck >=1.1.5,
-        split >=0.2.3.3,
+        semigroups >=0.19.1,
+        smallcheck >=1.2.1,
+        split >=0.2.3.4,
         stack -any,
         stm >=2.5.0.0,
-        streaming-commons >=0.2.1.2,
+        streaming-commons >=0.2.2.1,
         tar >=0.5.1.1,
-        template-haskell >=2.14.0.0,
+        template-haskell >=2.16.0.0,
         temporary >=1.3,
-        text >=1.2.3.1,
+        text >=1.2.4.1,
         text-metrics >=0.3.0,
         th-reify-many >=0.1.9,
-        time >=1.8.0.2,
-        tls >=1.4.1,
+        time >=1.9.3,
+        tls >=1.5.5,
         transformers >=0.5.6.2,
         typed-process >=0.2.6.0,
-        unicode-transforms >=0.3.6,
-        unix-compat >=0.5.2,
-        unliftio >=0.2.12,
-        unordered-containers >=0.2.10.0,
+        unicode-transforms >=0.3.7.1,
+        unix-compat >=0.5.3,
+        unliftio >=0.2.14,
+        unordered-containers >=0.2.13.0,
         vector >=0.12.1.2,
-        yaml >=0.11.2.0,
+        yaml >=0.11.5.0,
         zip-archive >=0.4.1,
-        zlib >=0.6.2.1
+        zlib >=0.6.2.3
 
     if os(windows)
         cpp-options:   -DWINDOWS
diff --git a/stack.yaml b/stack.yaml
--- a/stack.yaml
+++ b/stack.yaml
@@ -1,13 +1,12 @@
-resolver: lts-14.27
+resolver: lts-17.10
 
 packages:
 - .
 
 docker:
   enable: false
-
-  #image: fpco/alpine-haskell-stack:8.6.5
-  image: fpco/alpine-haskell-stack@sha256:49e7e15f3b1d3f882ba5bb701463b1d508fbf40e5aafce6ea31acd210da570ba
+  #repo: fpco/alpine-haskell-stack:8.10.4
+  repo: fpco/alpine-haskell-stack@sha256:1024fe4b3b082a8df64d00e8563b3151220ed90af09604a8f7e1d44040500c30
 
 nix:
   # --nix on the command-line to enable.
@@ -16,23 +15,12 @@
     - unzip
 flags:
   stack:
-    hide-dependency-versions: true
-    supported-build: true
     developer-mode: true
 
 ghc-options:
    "$locals": -fhide-source-paths
 
-extra-deps:
-- Cabal-3.0.0.0@rev:0
-- hpack-0.33.0@rev:0
-- http-download-0.2.0.0@rev:0
-- filelock-0.1.1.5@rev:0
-- rio-0.1.19.0@rev:0
-- rio-prettyprint-0.1.1.0@rev:0
-- casa-client-0.0.1@rev:0
-- casa-types-0.0.1@rev:0
-- pantry-0.5.1.3@rev:0
+extra-deps: []
 
 drop-packages:
 # See https://github.com/commercialhaskell/stack/pull/4712
