diff --git a/changelog.md b/changelog.md
deleted file mode 100644
--- a/changelog.md
+++ /dev/null
@@ -1,6 +0,0 @@
-# Unreleased
-
-# 0.2.0.0
-
-* Add `unitT`, returning `()` in a `Tactical` environment
-* Hide Polysemy's effect GADT constructors
diff --git a/incipit-core.cabal b/incipit-core.cabal
--- a/incipit-core.cabal
+++ b/incipit-core.cabal
@@ -5,30 +5,27 @@
 -- see: https://github.com/sol/hpack
 
 name:           incipit-core
-version:        0.2.0.0
+version:        0.3.0.0
 synopsis:       A Prelude for Polysemy
-description:    See <https://hackage.haskell.org/package/incipit/docs/Incipit.html>
+description:    See https://hackage.haskell.org/package/incipit-core/docs/IncipitCore.html
 category:       Prelude
-homepage:       https://github.com/tek/incipit#readme
-bug-reports:    https://github.com/tek/incipit/issues
+homepage:       https://github.com/tek/incipit-core#readme
+bug-reports:    https://github.com/tek/incipit-core/issues
 author:         Torsten Schmits
-maintainer:     haskell@tryp.io
+maintainer:     hackage@tryp.io
 copyright:      2022 Torsten Schmits
 license:        BSD-2-Clause-Patent
 license-file:   LICENSE
 build-type:     Simple
-extra-source-files:
-    readme.md
-    changelog.md
 
 source-repository head
   type: git
-  location: https://github.com/tek/incipit
+  location: https://github.com/tek/incipit-core
 
 library
   exposed-modules:
-      Incipit
-      Prelude
+      Incipit.Exception
+      IncipitCore
   reexported-modules:
       Control.Concurrent.STM
     , Control.Concurrent.STM.TArray
@@ -73,6 +70,7 @@
       DeriveFoldable
       DeriveFunctor
       DeriveGeneric
+      DeriveLift
       DeriveTraversable
       DerivingStrategies
       DerivingVia
@@ -93,7 +91,6 @@
       MultiParamTypeClasses
       MultiWayIf
       NamedFieldPuns
-      NoImplicitPrelude
       OverloadedStrings
       OverloadedLists
       PackageImports
@@ -106,6 +103,7 @@
       RankNTypes
       RecordWildCards
       RecursiveDo
+      RoleAnnotations
       ScopedTypeVariables
       StandaloneDeriving
       TemplateHaskell
@@ -118,15 +116,10 @@
       UndecidableInstances
       UnicodeSyntax
       ViewPatterns
-  ghc-options: -Wall -Wredundant-constraints -Wincomplete-uni-patterns -Wmissing-deriving-strategies -Widentities
+      NoImplicitPrelude
+  ghc-options: -Wall -Wredundant-constraints -Wincomplete-uni-patterns -Wmissing-deriving-strategies -Widentities -Wunused-packages
   build-depends:
-      base ==4.*
-    , incipit-base ==0.2.0.0
+      base >=4.13 && <4.17
+    , incipit-base ==0.3.0.0
     , polysemy >=1.6
-  mixins:
-      base hiding (Prelude)
-    , incipit-base (Incipit as IncipitBase)
-    , incipit-base hiding (Prelude, Incipit)
-  if impl(ghc >= 8.10)
-    ghc-options: -Wunused-packages
   default-language: Haskell2010
diff --git a/lib/Incipit.hs b/lib/Incipit.hs
deleted file mode 100644
--- a/lib/Incipit.hs
+++ /dev/null
@@ -1,83 +0,0 @@
--- |This is the central module on which to build upon when constructing Preludes for Polysemy libraries.
--- It reexports most core effects.
-module Incipit (
-  module IncipitBase,
-  module Polysemy,
-  module Polysemy.Async,
-  module Polysemy.AtomicState,
-  module Polysemy.Error,
-  module Polysemy.Fail,
-  module Polysemy.Input,
-  module Polysemy.Output,
-  module Polysemy.Reader,
-  module Polysemy.Resource,
-  module Polysemy.State,
-  module Polysemy.Tagged,
-  module Polysemy.Writer,
-  module Incipit,
-  send,
-) where
-
-import qualified Control.Exception as Base
-import IncipitBase
-import Polysemy hiding (run)
-import Polysemy.Async (Async)
-import Polysemy.Async hiding (Async, Await, Cancel)
-import Polysemy.AtomicState (AtomicState)
-import Polysemy.AtomicState hiding (AtomicGet, AtomicState)
-import Polysemy.Error hiding (Catch, Throw)
-import Polysemy.Fail (Fail)
-import Polysemy.Fail hiding (Fail)
-import Polysemy.Input (Input)
-import Polysemy.Input hiding (Input)
-import Polysemy.Internal (send)
-import Polysemy.Internal.Kind (Append)
-import Polysemy.Output (Output)
-import Polysemy.Output hiding (Output)
-import Polysemy.Reader hiding (Ask, Local)
-import Polysemy.Resource hiding (Bracket, BracketOnError)
-import Polysemy.State hiding (Get, Put)
-import Polysemy.Tagged (Tagged)
-import Polysemy.Tagged hiding (Tagged)
-import Polysemy.Writer hiding (Listen, Pass, Tell)
-
--- |Run an 'IO' via 'Embed' and catch all exceptions, returning 'Either'.
-tryAny ::
-  Member (Embed IO) r =>
-  IO a ->
-  Sem r (Either Text a)
-tryAny =
-  embed @IO . fmap (first show) . Base.try @SomeException
-{-# inline tryAny #-}
-
--- |Run an 'IO' via 'Embed' and catch all exceptions, returning 'Maybe'.
-tryMaybe ::
-  Member (Embed IO) r =>
-  IO a ->
-  Sem r (Maybe a)
-tryMaybe =
-  embed @IO . fmap rightToMaybe . Base.try @SomeException
-{-# inline tryMaybe #-}
-
--- |Run an 'IO' via 'Embed' and catch and ignore all exceptions.
-ignoreException ::
-  Member (Embed IO) r =>
-  IO () ->
-  Sem r ()
-ignoreException =
-  void . embed @IO . Base.try @SomeException
-{-# inline ignoreException #-}
-
--- |Convenience type alias for concatenating two effect rows.
-type a ++ b =
-  Append a b
-
-infixr 5 ++
-
--- |Convenience alias for @pureT ()@.
-unitT ::
-  Functor f =>
-  Sem (WithTactics e f m r) (f ())
-unitT =
-  pureT ()
-{-# inline unitT #-}
diff --git a/lib/Incipit/Exception.hs b/lib/Incipit/Exception.hs
new file mode 100644
--- /dev/null
+++ b/lib/Incipit/Exception.hs
@@ -0,0 +1,132 @@
+-- |Combinators that catch exceptions in 'IO' and embed them into 'Sem'.
+module Incipit.Exception where
+
+import qualified Control.Exception as Base
+import Control.Exception (Exception, SomeException)
+import Data.Bifunctor (first)
+import Data.Either (Either)
+import Data.Function ((.))
+import Data.Functor (fmap, void)
+import Data.Maybe (Maybe)
+import Polysemy (Embed, Member, Sem, embed)
+import System.IO (IO)
+import System.IO.Error (IOError)
+
+import Incipit.Either (rightToMaybe)
+import Incipit.String.Conversion (show)
+import Incipit.String.Reexport (Text)
+
+-- |Run an 'IO' via 'Embed' and catch exceptions of type @e@, returning 'Either'.
+-- Unlike all other combinators, this doesn't convert the exception to 'Text'.
+tryIOE ::
+  ∀ e r a .
+  Exception e =>
+  Member (Embed IO) r =>
+  IO a ->
+  Sem r (Either e a)
+tryIOE =
+  embed @IO . Base.try @e
+{-# inline tryIOE #-}
+
+-- |Run an 'IO' via 'Embed' and catch exceptions of type @e@, returning 'Either'.
+tryIO ::
+  ∀ e r a .
+  Exception e =>
+  Member (Embed IO) r =>
+  IO a ->
+  Sem r (Either Text a)
+tryIO =
+  embed @IO . fmap (first show) . Base.try @e
+{-# inline tryIO #-}
+
+-- |Run an 'IO' via 'Embed' and catch IOError, returning 'Either'.
+tryIOError ::
+  ∀ r a .
+  Member (Embed IO) r =>
+  IO a ->
+  Sem r (Either Text a)
+tryIOError =
+  tryIO @IOError
+{-# inline tryIOError #-}
+
+-- |Run an 'IO' via 'Embed' and catch all exceptions, returning 'Either'.
+tryAny ::
+  ∀ r a .
+  Member (Embed IO) r =>
+  IO a ->
+  Sem r (Either Text a)
+tryAny =
+  tryIO @SomeException
+{-# inline tryAny #-}
+
+-- |Run an 'IO' via 'Embed' and catch exceptions of type @e@, returning 'Maybe'.
+tryIOMaybe ::
+  ∀ e r a .
+  Exception e =>
+  Member (Embed IO) r =>
+  IO a ->
+  Sem r (Maybe a)
+tryIOMaybe =
+  fmap rightToMaybe . tryIO @e
+{-# inline tryIOMaybe #-}
+
+-- |Run an 'IO' via 'Embed' and catch 'IOError', returning 'Maybe'.
+tryIOErrorMaybe ::
+  ∀ r a .
+  Member (Embed IO) r =>
+  IO a ->
+  Sem r (Maybe a)
+tryIOErrorMaybe =
+  tryIOMaybe @IOError
+{-# inline tryIOErrorMaybe #-}
+
+-- |Run an 'IO' via 'Embed' and catch all exceptions, returning 'Maybe'.
+tryMaybe ::
+  ∀ r a .
+  Member (Embed IO) r =>
+  IO a ->
+  Sem r (Maybe a)
+tryMaybe =
+  tryIOMaybe @SomeException
+{-# inline tryMaybe #-}
+
+-- |Run an 'IO' via 'Embed' and catch and ignore exceptions of type @e@.
+tryIO_ ::
+  ∀ e r .
+  Exception e =>
+  Member (Embed IO) r =>
+  IO () ->
+  Sem r ()
+tryIO_ =
+  void . tryIO @e
+{-# inline tryIO_ #-}
+
+-- |Run an 'IO' via 'Embed' and catch and ignore 'IOError'.
+tryIOError_ ::
+  ∀ r .
+  Member (Embed IO) r =>
+  IO () ->
+  Sem r ()
+tryIOError_ =
+  void . tryIO @IOError
+{-# inline tryIOError_ #-}
+
+-- |Run an 'IO' via 'Embed' and catch and ignore all exceptions.
+tryAny_ ::
+  ∀ r .
+  Member (Embed IO) r =>
+  IO () ->
+  Sem r ()
+tryAny_ =
+  void . tryIO @SomeException
+{-# inline tryAny_ #-}
+
+-- |Run an 'IO' via 'Embed' and catch and ignore all exceptions.
+ignoreException ::
+  Member (Embed IO) r =>
+  IO () ->
+  Sem r ()
+ignoreException =
+  tryAny_
+{-# inline ignoreException #-}
+{-# deprecated ignoreException "renamed to 'tryAny_'" #-}
diff --git a/lib/IncipitCore.hs b/lib/IncipitCore.hs
new file mode 100644
--- /dev/null
+++ b/lib/IncipitCore.hs
@@ -0,0 +1,57 @@
+-- |This is the central module on which to build upon when constructing Preludes for Polysemy libraries.
+-- It reexports most core effects.
+module IncipitCore (
+  module Incipit.Exception,
+  module IncipitBase,
+  module Polysemy,
+  module Polysemy.Async,
+  module Polysemy.AtomicState,
+  module Polysemy.Error,
+  module Polysemy.Fail,
+  module Polysemy.Input,
+  module Polysemy.Output,
+  module Polysemy.Reader,
+  module Polysemy.Resource,
+  module Polysemy.State,
+  module Polysemy.Tagged,
+  module Polysemy.Writer,
+  module IncipitCore,
+  send,
+) where
+
+import Incipit.Exception
+import IncipitBase
+import Polysemy hiding (run)
+import Polysemy.Async (Async)
+import Polysemy.Async hiding (Async, Await, Cancel)
+import Polysemy.AtomicState (AtomicState)
+import Polysemy.AtomicState hiding (AtomicGet, AtomicState)
+import Polysemy.Error hiding (Catch, Throw)
+import Polysemy.Fail (Fail)
+import Polysemy.Fail hiding (Fail)
+import Polysemy.Input (Input)
+import Polysemy.Input hiding (Input)
+import Polysemy.Internal (send)
+import Polysemy.Internal.Kind (Append)
+import Polysemy.Output (Output)
+import Polysemy.Output hiding (Output)
+import Polysemy.Reader hiding (Ask, Local)
+import Polysemy.Resource hiding (Bracket, BracketOnError)
+import Polysemy.State hiding (Get, Put)
+import Polysemy.Tagged (Tagged)
+import Polysemy.Tagged hiding (Tagged)
+import Polysemy.Writer hiding (Listen, Pass, Tell)
+
+-- |Convenience type alias for concatenating two effect rows.
+type a ++ b =
+  Append a b
+
+infixr 5 ++
+
+-- |Convenience alias for @pureT ()@.
+unitT ::
+  Functor f =>
+  Sem (WithTactics e f m r) (f ())
+unitT =
+  pureT ()
+{-# inline unitT #-}
diff --git a/lib/Prelude.hs b/lib/Prelude.hs
deleted file mode 100644
--- a/lib/Prelude.hs
+++ /dev/null
@@ -1,6 +0,0 @@
--- |Exposing this module makes it possible to depend on the package without a mixin.
-module Prelude (
-  module Incipit
-) where
-
-import Incipit
diff --git a/readme.md b/readme.md
deleted file mode 100644
--- a/readme.md
+++ /dev/null
@@ -1,61 +0,0 @@
-# About
-
-This library provides a `Prelude` for [Polysemy] libraries, building upon [incipit-base] and exporting most of
-Polysemy's core modules.
-For a more comprehensive variant that includes some basic libraries, consider [incipit].
-
-# Usage
-
-`incipit-core` exports `Prelude`, so in order to use it you only have to hide `Prelude` from `base`:
-
-For `hpack`:
-```yaml
-dependencies:
-  - name: base
-    version: '>= 4 && < 5'
-    mixin:
-      - hiding (Prelude)
-  - incipit-core >= 0.1.0.3
-```
-
-For `cabal`:
-```cabal
-build-depends:
-    base >=4 && <5, incipit-core >= 0.1.0.3
-mixins:
-    base hiding (Prelude)
-```
-
-# Custom Prelude
-
-In order to extend `incipit-core` with a local `Prelude`, the module `Incipit` has to be reexported and `incipit-core`'s
-`Prelude` needs to be hidden:
-
-```yaml
-dependencies:
-  - name: base
-    version: '>= 4 && < 5'
-    mixin:
-      - hiding (Prelude)
-  - name: incipit-core
-    version: >= 0.1.0.3
-    mixin:
-      - hiding (Prelude)
-```
-
-```haskell
-module Prelude (
-  module Prelude,
-  module Incipit,
-) where
-
-import Incipit
-
-projectName :: Text
-projectName =
-  "spaceship"
-```
-
-[incipit-base]: https://hackage.haskell.org/package/incipit-base
-[incipit]: https://hackage.haskell.org/package/incipit
-[Polysemy]: https://hackage.haskell.org/package/polysemy
