diff --git a/lib/Prelate/App.hs b/lib/Prelate/App.hs
new file mode 100644
--- /dev/null
+++ b/lib/Prelate/App.hs
@@ -0,0 +1,85 @@
+{-# language NoImplicitPrelude #-}
+{-# options_haddock prune #-}
+
+module Prelate.App (
+  runApp,
+  runAppLevel,
+  runAppLevelE,
+  AppStack,
+  resumeExit,
+  stopExit,
+  ExitErrorMessage (exitErrorMessage),
+) where
+
+import Conc (ConcStack, Critical, interpretCritical, interpretInterrupt)
+import qualified Data.Text.IO as Text
+import Incipit
+import Log (Severity (Info), interpretLogStderrLevelConc)
+import Polysemy.Chronos (ChronosTime, interpretTimeChronos)
+import System.IO (stderr)
+
+-- | The default stack for a Prelate app.
+type AppStack =
+  [
+    ChronosTime,
+    Log,
+    Interrupt,
+    Critical,
+    Error Text
+  ] ++ ConcStack
+
+printError :: Text -> IO ()
+printError msg =
+  Text.hPutStrLn stderr ("Error: " <> msg)
+
+-- | Run the default 'AppStack' with the specified log level and return a potential error as 'Left'.
+runAppLevelE ::
+  Severity ->
+  Sem AppStack a ->
+  IO (Either Text a)
+runAppLevelE level =
+  runConc .
+  errorToIOFinal .
+  interpretCritical .
+  interpretInterrupt .
+  interpretLogStderrLevelConc (Just level) .
+  interpretTimeChronos
+
+-- | Run the default 'AppStack' with the specified log level and print an potential error to stderr.
+runAppLevel ::
+  Severity ->
+  Sem AppStack () ->
+  IO ()
+runAppLevel level =
+  leftA printError <=< runAppLevelE level
+
+-- | Run the default 'AppStack' and print an potential error to stderr.
+runApp :: Sem AppStack () -> IO ()
+runApp =
+  runAppLevel Info
+
+-- | Render an error for printing it as an exit message.
+class ExitErrorMessage err where
+  exitErrorMessage :: err -> Sem r Text
+
+instance {-# overlappable #-} Show err => ExitErrorMessage err where
+  exitErrorMessage = pure . show
+
+-- | Convert an effect to 'Resumable' and throw a potential error as 'Text', exiting the program if used with 'runApp'.
+--
+-- Uses 'ExitErrorMessage' to render the error.
+resumeExit ::
+  ∀ err eff r .
+  ExitErrorMessage err =>
+  Members [eff !! err, Error Text] r =>
+  InterpreterFor eff r
+resumeExit =
+  resuming @err (throw <=< exitErrorMessage)
+
+stopExit ::
+  ∀ err r .
+  ExitErrorMessage err =>
+  Member (Error Text) r =>
+  InterpreterFor (Stop err) r
+stopExit =
+  leftA (throw <=< exitErrorMessage) <=< runStop
diff --git a/lib/Prelate/Prelude.hs b/lib/Prelate/Prelude.hs
--- a/lib/Prelate/Prelude.hs
+++ b/lib/Prelate/Prelude.hs
@@ -3,6 +3,7 @@
   module Incipit,
   module Prelate.Prelude,
   module Prelate.Atomic,
+  module Prelate.App,
   module Prelate.Control.Applicative,
   module Prelate.Control.Monad,
   module Prelate.Data.List,
@@ -20,6 +21,7 @@
 import Lens.Micro.GHC (at)
 
 import Prelate.Atomic
+import Prelate.App
 import Prelate.Control.Applicative
 import Prelate.Control.Monad
 import Prelate.Data.List
diff --git a/prelate.cabal b/prelate.cabal
--- a/prelate.cabal
+++ b/prelate.cabal
@@ -5,7 +5,7 @@
 -- see: https://github.com/sol/hpack
 
 name:           prelate
-version:        0.5.0.0
+version:        0.5.1.0
 synopsis:       A Prelude
 description:    See https://hackage.haskell.org/package/prelate/docs/Prelate.html
 category:       Prelude
@@ -25,6 +25,7 @@
 library
   exposed-modules:
       Prelate
+      Prelate.App
       Prelate.Atomic
       Prelate.Control.Applicative
       Prelate.Control.Monad
