diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -147,7 +147,7 @@
   $ cabal-gild --input p.cabal --output p.cabal
   ```
 
-  This option is ignored when the mode is `check`.
+  It is an error to provide a value for this option when the mode is `check`.
 
 - `--stdin=FILE`: When reading input from STDIN, use `FILE` as the effective
   input file. This is useful when a file's contents are already available, like
@@ -157,7 +157,7 @@
   $ cabal-gild --stdin p.cabal < p.cabal
   ```
 
-  This option is ignored when the input is not `-`.
+  It is an error to provide a value for this option unless the input is `-`.
 
 ### Pragmas
 
@@ -188,8 +188,8 @@
   `signatures` fields. It will be ignored on all other fields.
 
   Any existing modules or signatures in the list will be ignored. The entire
-  field (including comments) will be replaced. This means adding, removing, and
-  renaming modules or signatures should be handled automatically.
+  field will be replaced. This means adding, removing, and renaming modules or
+  signatures should be handled automatically.
 
   This pragma searches for files with any of the following extensions: `*.chs`,
   `*.cpphs`, `*.gc`, `*.hs`, `*.hsc`, `*.hsig`, `*.lhs`, `*.lhsig`, `*.ly`,
diff --git a/cabal-gild.cabal b/cabal-gild.cabal
--- a/cabal-gild.cabal
+++ b/cabal-gild.cabal
@@ -11,7 +11,7 @@
 maintainer: Taylor Fausak
 name: cabal-gild
 synopsis: Formats package descriptions.
-version: 1.0.2.4
+version: 1.1.0.0
 
 source-repository head
   type: git
@@ -85,6 +85,8 @@
     CabalGild.Exception.InvalidMode
     CabalGild.Exception.InvalidOption
     CabalGild.Exception.ParseError
+    CabalGild.Exception.SpecifiedOutputWithCheckMode
+    CabalGild.Exception.SpecifiedStdinWithFileInput
     CabalGild.Exception.UnexpectedArgument
     CabalGild.Exception.UnknownOption
     CabalGild.Extra.Either
@@ -100,17 +102,21 @@
     CabalGild.Type.Chunk
     CabalGild.Type.Comment
     CabalGild.Type.Config
+    CabalGild.Type.Context
     CabalGild.Type.Dependency
     CabalGild.Type.ExeDependency
     CabalGild.Type.Extension
     CabalGild.Type.Flag
     CabalGild.Type.ForeignLibOption
+    CabalGild.Type.Input
     CabalGild.Type.Language
     CabalGild.Type.LegacyExeDependency
     CabalGild.Type.Line
     CabalGild.Type.List
     CabalGild.Type.Mode
     CabalGild.Type.ModuleReexport
+    CabalGild.Type.Optional
+    CabalGild.Type.Output
     CabalGild.Type.PkgconfigDependency
     CabalGild.Type.PkgconfigVersionRange
     CabalGild.Type.Pragma
diff --git a/source/library/CabalGild/Class/MonadLog.hs b/source/library/CabalGild/Class/MonadLog.hs
--- a/source/library/CabalGild/Class/MonadLog.hs
+++ b/source/library/CabalGild/Class/MonadLog.hs
@@ -2,13 +2,9 @@
 
 -- | A 'Monad' that can also log messages.
 class (Monad m) => MonadLog m where
-  -- | Logs the given message. Typical usage should prefer 'logLn'.
-  log :: String -> m ()
+  -- | Logs the given message followed by a newline.
+  logLn :: String -> m ()
 
--- | Uses 'putStr'.
+-- | Uses 'putStrLn'.
 instance MonadLog IO where
-  log = putStr
-
--- | Logs the message followed by a newline.
-logLn :: (MonadLog m) => String -> m ()
-logLn = CabalGild.Class.MonadLog.log . (<> "\n")
+  logLn = putStrLn
diff --git a/source/library/CabalGild/Class/MonadRead.hs b/source/library/CabalGild/Class/MonadRead.hs
--- a/source/library/CabalGild/Class/MonadRead.hs
+++ b/source/library/CabalGild/Class/MonadRead.hs
@@ -1,14 +1,16 @@
 module CabalGild.Class.MonadRead where
 
+import qualified CabalGild.Type.Input as Input
 import qualified Data.ByteString as ByteString
 
 -- | A 'Monad' that can also read input, either from standard input (STDIN) or
 -- from a file.
 class (Monad m) => MonadRead m where
-  -- | Reads input from the given file, or from STDIN if the given file is
-  -- 'Nothing'.
-  read :: Maybe FilePath -> m ByteString.ByteString
+  -- | Reads input from the given 'Input.Input'.
+  read :: Input.Input -> m ByteString.ByteString
 
 -- | Uses 'ByteString.getContents' or 'ByteString.readFile'.
 instance MonadRead IO where
-  read = maybe ByteString.getContents ByteString.readFile
+  read i = case i of
+    Input.Stdin -> ByteString.getContents
+    Input.File f -> ByteString.readFile f
diff --git a/source/library/CabalGild/Class/MonadWrite.hs b/source/library/CabalGild/Class/MonadWrite.hs
--- a/source/library/CabalGild/Class/MonadWrite.hs
+++ b/source/library/CabalGild/Class/MonadWrite.hs
@@ -1,14 +1,16 @@
 module CabalGild.Class.MonadWrite where
 
+import qualified CabalGild.Type.Output as Output
 import qualified Data.ByteString as ByteString
 
 -- | A 'Monad' that can also write output, either to standard output (STDOUT)
 -- or to a file.
 class (Monad m) => MonadWrite m where
-  -- | Writes output to the given file, or to STDOUT if the given file is
-  -- 'Nothing'.
-  write :: Maybe FilePath -> ByteString.ByteString -> m ()
+  -- | Writes output to the given 'Output.Output'.
+  write :: Output.Output -> ByteString.ByteString -> m ()
 
 -- | Uses 'ByteString.putStr' or 'ByteString.writeFile'.
 instance MonadWrite IO where
-  write = maybe ByteString.putStr ByteString.writeFile
+  write o = case o of
+    Output.Stdout -> ByteString.putStr
+    Output.File f -> ByteString.writeFile f
diff --git a/source/library/CabalGild/Exception/SpecifiedOutputWithCheckMode.hs b/source/library/CabalGild/Exception/SpecifiedOutputWithCheckMode.hs
new file mode 100644
--- /dev/null
+++ b/source/library/CabalGild/Exception/SpecifiedOutputWithCheckMode.hs
@@ -0,0 +1,12 @@
+module CabalGild.Exception.SpecifiedOutputWithCheckMode where
+
+import qualified Control.Monad.Catch as Exception
+
+-- | This exception is thrown when the user specifies the output while using
+-- the check mode. In other words, when @--mode=check@ and @--output=anything@.
+data SpecifiedOutputWithCheckMode
+  = SpecifiedOutputWithCheckMode
+  deriving (Eq, Show)
+
+instance Exception.Exception SpecifiedOutputWithCheckMode where
+  displayException = const "cannot use --output when --mode is check"
diff --git a/source/library/CabalGild/Exception/SpecifiedStdinWithFileInput.hs b/source/library/CabalGild/Exception/SpecifiedStdinWithFileInput.hs
new file mode 100644
--- /dev/null
+++ b/source/library/CabalGild/Exception/SpecifiedStdinWithFileInput.hs
@@ -0,0 +1,13 @@
+module CabalGild.Exception.SpecifiedStdinWithFileInput where
+
+import qualified Control.Monad.Catch as Exception
+
+-- | This exception is thrown when the user specifies the STDIN name while
+-- using an input file. In other words, when @--input=file@ and
+-- @--stdin=anything@.
+data SpecifiedStdinWithFileInput
+  = SpecifiedStdinWithFileInput
+  deriving (Eq, Show)
+
+instance Exception.Exception SpecifiedStdinWithFileInput where
+  displayException = const "cannot use --stdin when --input is a file"
diff --git a/source/library/CabalGild/Main.hs b/source/library/CabalGild/Main.hs
--- a/source/library/CabalGild/Main.hs
+++ b/source/library/CabalGild/Main.hs
@@ -17,17 +17,15 @@
 import qualified CabalGild.Exception.CheckFailure as CheckFailure
 import qualified CabalGild.Exception.ParseError as ParseError
 import qualified CabalGild.Type.Config as Config
+import qualified CabalGild.Type.Context as Context
 import qualified CabalGild.Type.Flag as Flag
+import qualified CabalGild.Type.Input as Input
 import qualified CabalGild.Type.Mode as Mode
 import qualified Control.Monad as Monad
 import qualified Control.Monad.Catch as Exception
 import qualified Data.ByteString as ByteString
 import qualified Data.ByteString.Char8 as Latin1
-import qualified Data.Maybe as Maybe
-import qualified Data.Version as Version
 import qualified Distribution.Fields as Fields
-import qualified Paths_cabal_gild as This
-import qualified System.Console.GetOpt as GetOpt
 import qualified System.Environment as Environment
 import qualified System.Exit as Exit
 import qualified System.IO as IO
@@ -37,9 +35,8 @@
 -- thrown, they will be handled by 'onException'.
 defaultMain :: IO ()
 defaultMain = Exception.handle onException $ do
-  name <- Environment.getProgName
   arguments <- Environment.getArgs
-  mainWith name arguments
+  mainWith arguments
 
 -- | If the exception was an 'Exit.ExitCode', simply exit with that code.
 -- Otherwise handle exceptions by printing them to STDERR using
@@ -62,46 +59,35 @@
     MonadWalk.MonadWalk m,
     MonadWrite.MonadWrite m
   ) =>
-  String ->
   [String] ->
   m ()
-mainWith name arguments = do
+mainWith arguments = do
   flags <- Flag.fromArguments arguments
   config <- Config.fromFlags flags
-  let version = Version.showVersion This.version
-
-  Monad.when (Config.help config) $ do
-    let header =
-          unlines
-            [ name <> " version " <> version,
-              "",
-              "<https://github.com/tfausak/cabal-gild>"
-            ]
-    MonadLog.log $ GetOpt.usageInfo header Flag.options
-    Exception.throwM Exit.ExitSuccess
-
-  Monad.when (Config.version config) $ do
-    MonadLog.logLn version
-    Exception.throwM Exit.ExitSuccess
+  context <- Context.fromConfig config
 
-  input <- MonadRead.read $ Config.input config
+  let source = Context.input context
+  input <- MonadRead.read source
   fields <-
     either (Exception.throwM . ParseError.ParseError) pure $
       Fields.readFields input
   let csv = GetCabalVersion.fromFields fields
       comments = ExtractComments.fromByteString input
+      path = case source of
+        Input.Stdin -> Context.stdin context
+        Input.File f -> f
   output <-
     ( StripBlanks.run
         Monad.>=> AttachComments.run
         Monad.>=> ReflowText.run csv
         Monad.>=> RemovePositions.run
-        Monad.>=> EvaluatePragmas.run (Maybe.fromMaybe (Config.stdin config) $ Config.input config)
+        Monad.>=> EvaluatePragmas.run path
         Monad.>=> FormatFields.run csv
         Monad.>=> Render.run
       )
       (fields, comments)
 
-  case Config.mode config of
+  case Context.mode context of
     Mode.Check -> do
       -- The input might have CRLF ("\r\n", 0x0d 0x0a) line endings, but the
       -- output will always have LF line endings. For the purposes of the check
@@ -114,4 +100,6 @@
           inputLines = stripCR <$> Latin1.lines input
       Monad.when (outputLines /= inputLines) $
         Exception.throwM CheckFailure.CheckFailure
-    Mode.Format -> MonadWrite.write (Config.output config) output
+    Mode.Format -> do
+      let target = Context.output context
+      MonadWrite.write target output
diff --git a/source/library/CabalGild/Type/Config.hs b/source/library/CabalGild/Type/Config.hs
--- a/source/library/CabalGild/Type/Config.hs
+++ b/source/library/CabalGild/Type/Config.hs
@@ -2,19 +2,22 @@
 module CabalGild.Type.Config where
 
 import qualified CabalGild.Type.Flag as Flag
+import qualified CabalGild.Type.Input as Input
 import qualified CabalGild.Type.Mode as Mode
+import qualified CabalGild.Type.Optional as Optional
+import qualified CabalGild.Type.Output as Output
 import qualified Control.Monad as Monad
 import qualified Control.Monad.Catch as Exception
 
 -- | This data type represents the configuration for the command line utility.
 -- Each field typically corresponds to a flag.
 data Config = Config
-  { help :: Bool,
-    input :: Maybe FilePath,
-    mode :: Mode.Mode,
-    output :: Maybe FilePath,
-    stdin :: FilePath,
-    version :: Bool
+  { help :: Optional.Optional Bool,
+    input :: Optional.Optional Input.Input,
+    mode :: Optional.Optional Mode.Mode,
+    output :: Optional.Optional Output.Output,
+    stdin :: Optional.Optional FilePath,
+    version :: Optional.Optional Bool
   }
   deriving (Eq, Show)
 
@@ -22,29 +25,25 @@
 initial :: Config
 initial =
   Config
-    { help = False,
-      input = Nothing,
-      mode = Mode.Format,
-      output = Nothing,
-      stdin = ".",
-      version = False
+    { help = Optional.Default,
+      input = Optional.Default,
+      mode = Optional.Default,
+      output = Optional.Default,
+      stdin = Optional.Default,
+      version = Optional.Default
     }
 
 -- | Applies a flag to the config, returning the new config.
 applyFlag :: (Exception.MonadThrow m) => Config -> Flag.Flag -> m Config
 applyFlag config flag = case flag of
-  Flag.Help b -> pure config {help = b}
-  Flag.Input s -> case s of
-    "-" -> pure config {input = Nothing}
-    _ -> pure config {input = Just s}
+  Flag.Help b -> pure config {help = Optional.Specific b}
+  Flag.Input s -> pure config {input = Optional.Specific $ Input.fromString s}
   Flag.Mode s -> do
     m <- Mode.fromString s
-    pure config {mode = m}
-  Flag.Output s -> case s of
-    "-" -> pure config {output = Nothing}
-    _ -> pure config {output = Just s}
-  Flag.Stdin s -> pure config {stdin = s}
-  Flag.Version b -> pure config {version = b}
+    pure config {mode = Optional.Specific m}
+  Flag.Output s -> pure config {output = Optional.Specific $ Output.fromString s}
+  Flag.Stdin s -> pure config {stdin = Optional.Specific s}
+  Flag.Version b -> pure config {version = Optional.Specific b}
 
 -- | Converts a list of flags into a config by starting with 'initial' and
 -- repeatedly calling 'applyFlag'.
diff --git a/source/library/CabalGild/Type/Context.hs b/source/library/CabalGild/Type/Context.hs
new file mode 100644
--- /dev/null
+++ b/source/library/CabalGild/Type/Context.hs
@@ -0,0 +1,73 @@
+module CabalGild.Type.Context where
+
+import qualified CabalGild.Class.MonadLog as MonadLog
+import qualified CabalGild.Exception.SpecifiedOutputWithCheckMode as SpecifiedOutputWithCheckMode
+import qualified CabalGild.Exception.SpecifiedStdinWithFileInput as SpecifiedStdinWithFileInput
+import qualified CabalGild.Type.Config as Config
+import qualified CabalGild.Type.Flag as Flag
+import qualified CabalGild.Type.Input as Input
+import qualified CabalGild.Type.Mode as Mode
+import qualified CabalGild.Type.Optional as Optional
+import qualified CabalGild.Type.Output as Output
+import qualified Control.Monad as Monad
+import qualified Control.Monad.Catch as Exception
+import qualified Data.Char as Char
+import qualified Data.List as List
+import qualified Data.Version as Version
+import qualified Paths_cabal_gild as This
+import qualified System.Console.GetOpt as GetOpt
+import qualified System.Exit as Exit
+
+-- | Represents the context necessary to run the program. This is essentially a
+-- simplified 'Config.Config'.
+data Context = Context
+  { input :: Input.Input,
+    mode :: Mode.Mode,
+    output :: Output.Output,
+    stdin :: FilePath
+  }
+  deriving (Eq, Show)
+
+-- | Creates a 'Context' from a 'Config.Config'. If the help or version was
+-- requested, then this will throw an 'Exit.ExitSuccess'. Otherwise this makes
+-- sure the config is valid before returning the context.
+fromConfig ::
+  (MonadLog.MonadLog m, Exception.MonadThrow m) =>
+  Config.Config ->
+  m Context
+fromConfig config = do
+  let version = Version.showVersion This.version
+
+  Monad.when (Optional.withDefault False $ Config.help config) $ do
+    let header =
+          unlines
+            [ "cabal-gild version " <> version,
+              "",
+              "<https://github.com/tfausak/cabal-gild>"
+            ]
+    MonadLog.logLn
+      . List.dropWhileEnd Char.isSpace
+      $ GetOpt.usageInfo header Flag.options
+    Exception.throwM Exit.ExitSuccess
+
+  Monad.when (Optional.withDefault False $ Config.version config) $ do
+    MonadLog.logLn version
+    Exception.throwM Exit.ExitSuccess
+
+  case (Config.input config, Config.stdin config) of
+    (Optional.Specific (Input.File _), Optional.Specific _) ->
+      Exception.throwM SpecifiedStdinWithFileInput.SpecifiedStdinWithFileInput
+    _ -> pure ()
+
+  case (Config.mode config, Config.output config) of
+    (Optional.Specific Mode.Check, Optional.Specific _) ->
+      Exception.throwM SpecifiedOutputWithCheckMode.SpecifiedOutputWithCheckMode
+    _ -> pure ()
+
+  pure
+    Context
+      { input = Optional.withDefault Input.Stdin $ Config.input config,
+        mode = Optional.withDefault Mode.Format $ Config.mode config,
+        output = Optional.withDefault Output.Stdout $ Config.output config,
+        stdin = Optional.withDefault "." $ Config.stdin config
+      }
diff --git a/source/library/CabalGild/Type/Input.hs b/source/library/CabalGild/Type/Input.hs
new file mode 100644
--- /dev/null
+++ b/source/library/CabalGild/Type/Input.hs
@@ -0,0 +1,15 @@
+module CabalGild.Type.Input where
+
+-- | Represents an input stream, which can either be standard input (STDIN) or
+-- a file.
+data Input
+  = Stdin
+  | File FilePath
+  deriving (Eq, Ord, Show)
+
+-- | Converts a string into an input. The string @"-"@ will be converted into
+-- 'Stdin', and any other string will be converted into 'File'.
+fromString :: String -> Input
+fromString s = case s of
+  "-" -> Stdin
+  _ -> File s
diff --git a/source/library/CabalGild/Type/Optional.hs b/source/library/CabalGild/Type/Optional.hs
new file mode 100644
--- /dev/null
+++ b/source/library/CabalGild/Type/Optional.hs
@@ -0,0 +1,20 @@
+module CabalGild.Type.Optional where
+
+-- | Represents a value that may or may not be present. Isomorphic to 'Maybe'.
+-- Useful to distinguish between a value not being given and a value happening
+-- to be the same as the default.
+data Optional a
+  = Default
+  | Specific a
+  deriving (Eq, Show)
+
+-- | Uses the provided default value if the optional is 'Default', otherwise
+-- gets the value out of the 'Specific'. Similar to 'Data.Maybe.fromMaybe'.
+withDefault :: a -> Optional a -> a
+withDefault = flip optional id
+
+-- | Basic destructor, similar to 'maybe'.
+optional :: b -> (a -> b) -> Optional a -> b
+optional b f o = case o of
+  Default -> b
+  Specific s -> f s
diff --git a/source/library/CabalGild/Type/Output.hs b/source/library/CabalGild/Type/Output.hs
new file mode 100644
--- /dev/null
+++ b/source/library/CabalGild/Type/Output.hs
@@ -0,0 +1,15 @@
+module CabalGild.Type.Output where
+
+-- | Represents an output stream, which can either be standard output
+-- (STDOUT) or a file.
+data Output
+  = Stdout
+  | File FilePath
+  deriving (Eq, Ord, Show)
+
+-- | Converts a string into an output. The string @"-"@ will be converted into
+-- 'Stdout', and any other string will be converted into 'File'.
+fromString :: String -> Output
+fromString s = case s of
+  "-" -> Stdout
+  _ -> File s
diff --git a/source/test-suite/Main.hs b/source/test-suite/Main.hs
--- a/source/test-suite/Main.hs
+++ b/source/test-suite/Main.hs
@@ -4,18 +4,23 @@
 import qualified CabalGild.Class.MonadRead as MonadRead
 import qualified CabalGild.Class.MonadWalk as MonadWalk
 import qualified CabalGild.Class.MonadWrite as MonadWrite
+import qualified CabalGild.Exception.CheckFailure as CheckFailure
+import qualified CabalGild.Exception.SpecifiedOutputWithCheckMode as SpecifiedOutputWithCheckMode
+import qualified CabalGild.Exception.SpecifiedStdinWithFileInput as SpecifiedStdinWithFileInput
 import qualified CabalGild.Extra.String as String
 import qualified CabalGild.Main as Gild
+import qualified CabalGild.Type.Input as Input
+import qualified CabalGild.Type.Output as Output
 import qualified Control.Monad.Catch as Exception
 import qualified Control.Monad.Trans.Class as Trans
 import qualified Control.Monad.Trans.Except as ExceptT
 import qualified Control.Monad.Trans.RWS as RWST
 import qualified Data.ByteString as ByteString
-import qualified Data.Either as Either
 import qualified Data.Function as Function
 import qualified Data.Functor.Identity as Identity
 import qualified Data.Map as Map
 import qualified GHC.Stack as Stack
+import qualified System.Exit as Exit
 import qualified System.FilePath as FilePath
 import qualified Test.Hspec as Hspec
 
@@ -24,48 +29,48 @@
   Hspec.it "shows the help" $ do
     let (a, s, w) =
           runTest
-            (Gild.mainWith "" ["--help"])
+            (Gild.mainWith ["--help"])
             (Map.empty, Map.empty)
             Map.empty
-    a `Hspec.shouldSatisfy` Either.isLeft
+    a `Hspec.shouldBe` Left (Problem $ Exception.toException Exit.ExitSuccess)
     w `Hspec.shouldNotSatisfy` null
     s `Hspec.shouldBe` Map.empty
 
   Hspec.it "shows the version" $ do
     let (a, s, w) =
           runTest
-            (Gild.mainWith "" ["--version"])
+            (Gild.mainWith ["--version"])
             (Map.empty, Map.empty)
             Map.empty
-    a `Hspec.shouldSatisfy` Either.isLeft
+    a `Hspec.shouldBe` Left (Problem $ Exception.toException Exit.ExitSuccess)
     w `Hspec.shouldNotSatisfy` null
     s `Hspec.shouldBe` Map.empty
 
   Hspec.it "reads from an input file" $ do
     let (a, s, w) =
           runTest
-            (Gild.mainWith "" ["--input", "input.cabal"])
-            (Map.singleton (Just "input.cabal") (String.toUtf8 ""), Map.empty)
+            (Gild.mainWith ["--input", "input.cabal"])
+            (Map.singleton (Input.File "input.cabal") (String.toUtf8 ""), Map.empty)
             Map.empty
     a `Hspec.shouldBe` Right ()
     w `Hspec.shouldBe` []
-    s `Hspec.shouldSatisfy` Map.member Nothing
+    s `Hspec.shouldSatisfy` Map.member Output.Stdout
 
   Hspec.it "writes to an output file" $ do
     let (a, s, w) =
           runTest
-            (Gild.mainWith "" ["--output", "output.cabal"])
-            (Map.singleton Nothing (String.toUtf8 ""), Map.empty)
+            (Gild.mainWith ["--output", "output.cabal"])
+            (Map.singleton Input.Stdin (String.toUtf8 ""), Map.empty)
             Map.empty
     a `Hspec.shouldBe` Right ()
     w `Hspec.shouldBe` []
-    s `Hspec.shouldSatisfy` Map.member (Just "output.cabal")
+    s `Hspec.shouldSatisfy` Map.member (Output.File "output.cabal")
 
   Hspec.it "succeeds when checking formatted input" $ do
     let (a, s, w) =
           runTest
-            (Gild.mainWith "" ["--mode", "check"])
-            (Map.singleton Nothing (String.toUtf8 ""), Map.empty)
+            (Gild.mainWith ["--mode", "check"])
+            (Map.singleton Input.Stdin (String.toUtf8 ""), Map.empty)
             Map.empty
     a `Hspec.shouldBe` Right ()
     w `Hspec.shouldBe` []
@@ -74,23 +79,43 @@
   Hspec.it "fails when checking unformatted input" $ do
     let (a, s, w) =
           runTest
-            (Gild.mainWith "" ["--mode", "check"])
-            (Map.singleton Nothing (String.toUtf8 "fail:yes"), Map.empty)
+            (Gild.mainWith ["--mode", "check"])
+            (Map.singleton Input.Stdin (String.toUtf8 "fail:yes"), Map.empty)
             Map.empty
-    a `Hspec.shouldSatisfy` Either.isLeft
+    a `Hspec.shouldBe` Left (Problem $ Exception.toException CheckFailure.CheckFailure)
     w `Hspec.shouldBe` []
     s `Hspec.shouldBe` Map.empty
 
   Hspec.it "succeeds when checking CRLF input" $ do
     let (a, s, w) =
           runTest
-            (Gild.mainWith "" ["--mode", "check"])
-            (Map.singleton Nothing (String.toUtf8 "pass: yes\r\n"), Map.empty)
+            (Gild.mainWith ["--mode", "check"])
+            (Map.singleton Input.Stdin (String.toUtf8 "pass: yes\r\n"), Map.empty)
             Map.empty
     a `Hspec.shouldBe` Right ()
     w `Hspec.shouldBe` []
     s `Hspec.shouldBe` Map.empty
 
+  Hspec.it "fails when --stdin is given with an input file" $ do
+    let (a, s, w) =
+          runTest
+            (Gild.mainWith ["--input", "f", "--stdin", "g"])
+            (Map.empty, Map.empty)
+            Map.empty
+    a `Hspec.shouldBe` Left (Problem $ Exception.toException SpecifiedStdinWithFileInput.SpecifiedStdinWithFileInput)
+    w `Hspec.shouldBe` []
+    s `Hspec.shouldBe` Map.empty
+
+  Hspec.it "fails when --output is given with check mode" $ do
+    let (a, s, w) =
+          runTest
+            (Gild.mainWith ["--mode", "check", "--output", "-"])
+            (Map.empty, Map.empty)
+            Map.empty
+    a `Hspec.shouldBe` Left (Problem $ Exception.toException SpecifiedOutputWithCheckMode.SpecifiedOutputWithCheckMode)
+    w `Hspec.shouldBe` []
+    s `Hspec.shouldBe` Map.empty
+
   Hspec.it "succeeds with empty input" $ do
     expectGilded
       ""
@@ -949,13 +974,13 @@
 expectGilded input expected = do
   let (a, s, w) =
         runTest
-          (Gild.mainWith "" [])
-          (Map.singleton Nothing $ String.toUtf8 input, Map.empty)
+          (Gild.mainWith [])
+          (Map.singleton Input.Stdin $ String.toUtf8 input, Map.empty)
           Map.empty
   a `Hspec.shouldBe` Right ()
   w `Hspec.shouldBe` []
   actual <- case Map.toList s of
-    [(Nothing, x)] -> pure x
+    [(Output.Stdout, x)] -> pure x
     _ -> fail $ "impossible: " <> show s
   actual `Hspec.shouldBe` String.toUtf8 expected
   -- After formatting, the output should not change if we format it again.
@@ -965,13 +990,13 @@
 expectStable input = do
   let (a, s, w) =
         runTest
-          (Gild.mainWith "" [])
-          (Map.singleton Nothing input, Map.empty)
+          (Gild.mainWith [])
+          (Map.singleton Input.Stdin input, Map.empty)
           Map.empty
   a `Hspec.shouldBe` Right ()
   w `Hspec.shouldBe` []
   output <- case Map.toList s of
-    [(Nothing, x)] -> pure x
+    [(Output.Stdout, x)] -> pure x
     _ -> fail $ "impossible: " <> show s
   output `Hspec.shouldBe` input
 
@@ -979,15 +1004,15 @@
 expectDiscover files input expected = do
   let (a, s, w) =
         runTest
-          (Gild.mainWith "" [])
-          ( Map.singleton Nothing $ String.toUtf8 input,
+          (Gild.mainWith [])
+          ( Map.singleton Input.Stdin $ String.toUtf8 input,
             Map.fromList $ fmap (\(d, fs) -> (d, FilePath.combine d <$> fs)) files
           )
           Map.empty
   a `Hspec.shouldBe` Right ()
   w `Hspec.shouldBe` []
   actual <- case Map.toList s of
-    [(Nothing, x)] -> pure x
+    [(Output.Stdout, x)] -> pure x
     _ -> fail $ "impossible: " <> show s
   actual `Hspec.shouldBe` String.toUtf8 expected
 
@@ -1006,9 +1031,9 @@
 
 type E = Problem
 
-type R = (S, Map.Map FilePath [FilePath])
+type R = (Map.Map Input.Input ByteString.ByteString, Map.Map FilePath [FilePath])
 
-type S = Map.Map (Maybe FilePath) ByteString.ByteString
+type S = Map.Map Output.Output ByteString.ByteString
 
 type W = [String]
 
@@ -1018,7 +1043,7 @@
   deriving (Applicative, Functor, Monad)
 
 instance (Monad m) => MonadLog.MonadLog (TestT m) where
-  log = TestT . Trans.lift . RWST.tell . pure
+  logLn = TestT . Trans.lift . RWST.tell . pure
 
 instance (Monad m) => MonadRead.MonadRead (TestT m) where
   read k = do
