diff --git a/benchmark/Main.hs b/benchmark/Main.hs
--- a/benchmark/Main.hs
+++ b/benchmark/Main.hs
@@ -1,7 +1,7 @@
 -- You can benchmark your code quickly and effectively with Criterion. See its
 -- website for help: <http://www.serpentine.com/criterion/>.
 
-import Universum
+import Relude
 
 main :: IO ()
 main = putTextLn "Hello"
diff --git a/executable/AutoRequire/Main.hs b/executable/AutoRequire/Main.hs
--- a/executable/AutoRequire/Main.hs
+++ b/executable/AutoRequire/Main.hs
@@ -1,8 +1,9 @@
 -- It is generally a good idea to keep all your business logic in your library
 -- and only use it in the executable. Doing so allows others to use what you
 -- wrote in their libraries.
+
+import Relude
 import qualified Require
-import Universum
 
 main :: IO ()
 main = Require.autorequireMain
diff --git a/executable/Require/Main.hs b/executable/Require/Main.hs
--- a/executable/Require/Main.hs
+++ b/executable/Require/Main.hs
@@ -1,8 +1,9 @@
 -- It is generally a good idea to keep all your business logic in your library
 -- and only use it in the executable. Doing so allows others to use what you
 -- wrote in their libraries.
+
+import Relude
 import qualified Require
-import Universum
 
 main :: IO ()
 main = Require.requireMain
diff --git a/library/Require.hs b/library/Require.hs
--- a/library/Require.hs
+++ b/library/Require.hs
@@ -1,27 +1,30 @@
 module Require where
 
-import Universum
-
-import qualified Text.Megaparsec      as Megaparsec
-import qualified Text.Megaparsec.Char as Megaparsec
-import qualified Data.Text            as Text
+import qualified Data.Text as Text
 import Options.Generic
+import Relude
 import System.Directory
+import qualified Text.Megaparsec as Megaparsec
+import qualified Text.Megaparsec.Char as Megaparsec
 
-newtype FileName   = FileName { unFileName :: Text }
+newtype FileName = FileName {unFileName :: Text}
+
 newtype LineNumber = LineNumber Int
-type Parser        = Megaparsec.Parsec Void Text
 
-data RequireInfo = RequireInfo
-  { riFullModuleName :: Text
-  , riModuleAlias    :: Text
-  , riImportedTypes  :: Maybe [Text]
-  } deriving Show
+type Parser = Megaparsec.Parsec Void Text
 
-data CommandArguments =
-  CommandArguments Text Text Text
-  deriving Generic
+data RequireInfo
+  = RequireInfo
+      { riFullModuleName :: Text,
+        riModuleAlias :: Text,
+        riImportedTypes :: Maybe [Text]
+      }
+  deriving (Show)
 
+data CommandArguments
+  = CommandArguments Text Text Text
+  deriving (Generic)
+
 instance ParseRecord CommandArguments
 
 findRequires :: IO (Maybe Text)
@@ -29,24 +32,25 @@
   currentDir <- getCurrentDirectory
   files <- getDirectoryContents currentDir
   let textFiles = fmap toText files
-  return $ head <$> (nonEmpty $ filter (Text.isSuffixOf "Requires") textFiles)
+  return $ head <$> nonEmpty (filter (Text.isSuffixOf "Requires") textFiles)
 
 requireMain :: IO ()
 requireMain = do
-  CommandArguments _ inputFile outputFile <- getRecord "Require Haskell preprocessor" :: IO CommandArguments
+  CommandArguments inputFile _ outputFile <- getRecord "Require Haskell preprocessor" :: IO CommandArguments
   content <- readFile (toString inputFile)
   writeFile
     (toString outputFile)
-    ( Require.transform
-        False
-        (Require.FileName inputFile)
-        ""
-        content
+    ( toString $
+        Require.transform
+          False
+          (Require.FileName inputFile)
+          ""
+          (toText content)
     )
 
 autorequireMain :: IO ()
 autorequireMain = do
-  CommandArguments _ inputFile outputFile <- getRecord "Require Haskell preprocessor" :: IO CommandArguments
+  CommandArguments inputFile _ outputFile <- getRecord "Require Haskell preprocessor" :: IO CommandArguments
   requiresFile <- findRequires
   case requiresFile of
     Nothing -> die "There is no Requires file in the system"
@@ -55,97 +59,97 @@
       content <- readFile (toString inputFile)
       writeFile
         (toString outputFile)
-        (Require.transform
-          True
-          (Require.FileName inputFile)
-          file
-          content)
+        ( toString $
+            Require.transform
+              True
+              (Require.FileName inputFile)
+              (toText file)
+              (toText content)
+        )
 
 transform :: Bool -> FileName -> Text -> Text -> Text
 transform autorequireEnabled filename imports input
   | autorequireEnabled = transform' True filename imports input
-  | noAutorequire  = transform' False filename imports input
-  | otherwise      = transform' True filename imports input
- where
-  noAutorequire = (length $ filter (\t -> "autorequire" `Text.isPrefixOf` t) $ lines input) == 0
-
+  | noAutorequire = transform' False filename imports input
+  | otherwise = transform' True filename imports input
+  where
+    noAutorequire = not (any ("autorequire" `Text.isPrefixOf`) $ lines input)
 
 transform' :: Bool -> FileName -> Text -> Text -> Text
 transform' shouldPrepend filename prepended input =
   Text.lines input
-  &   filter (\t -> not $ "autorequire" `Text.isPrefixOf` t)
-  &   zip [1..]
-  >>= prependAfterModuleLine
-  <&> (\(ln, text) -> maybe (text <> "\n") (renderImport filename (LineNumber ln)) $ Megaparsec.parseMaybe requireParser text)
-  &   (lineTag filename (LineNumber 1) :)
-  &   Text.concat
- where
-  enumeratedPrepend ln
-   | shouldPrepend = zip (repeat ln) (Text.lines prepended)
-   | otherwise     = []
-  prependAfterModuleLine (ln, text)
-   | ("module" `Text.isPrefixOf` text)
-     && ("where" `Text.isSuffixOf`) text = (ln, text) : enumeratedPrepend ln
-   | ("instance" `Text.isPrefixOf` text)
-     && ("where" `Text.isSuffixOf`) text = [(ln, text)]
-   | ("data" `Text.isPrefixOf` text)
-     && ("where" `Text.isSuffixOf`) text = [(ln, text)]
-   | ("class" `Text.isPrefixOf` text)
-     && ("where" `Text.isSuffixOf`) text = [(ln, text)]
-   | (not $ "instance" `Text.isPrefixOf` text)
-     && (not $ "class" `Text.isPrefixOf` text)
-     && (not $ "data" `Text.isPrefixOf` text)
-     && ("where" `Text.isPrefixOf`) text = (ln, text) : enumeratedPrepend (ln)
-   | otherwise                      = [(ln, text)]
+    & filter (\t -> not $ "autorequire" `Text.isPrefixOf` t)
+    & zip [1 ..]
+    >>= prependAfterModuleLine
+    <&> (\(ln, text) -> maybe (text <> "\n") (renderImport filename (LineNumber ln)) $ Megaparsec.parseMaybe requireParser text)
+    & (lineTag filename (LineNumber 1) :)
+    & Text.concat
+  where
+    enumeratedPrepend ln
+      | shouldPrepend = zip (repeat ln) (Text.lines prepended)
+      | otherwise = []
+    prependAfterModuleLine (ln, text)
+      | ("module" `Text.isPrefixOf` text)
+          && ("where" `Text.isSuffixOf`) text =
+        (ln, text) : enumeratedPrepend ln
+      | ("instance" `Text.isPrefixOf` text)
+          && ("where" `Text.isSuffixOf`) text =
+        [(ln, text)]
+      | ("data" `Text.isPrefixOf` text)
+          && ("where" `Text.isSuffixOf`) text =
+        [(ln, text)]
+      | ("class" `Text.isPrefixOf` text)
+          && ("where" `Text.isSuffixOf`) text =
+        [(ln, text)]
+      | not ("instance" `Text.isPrefixOf` text)
+          && not ("class" `Text.isPrefixOf` text)
+          && not ("data" `Text.isPrefixOf` text)
+          && ("where" `Text.isPrefixOf`) text =
+        (ln, text) : enumeratedPrepend ln
+      | otherwise = [(ln, text)]
 
 lineTag :: FileName -> LineNumber -> Text
 lineTag (FileName fn) (LineNumber ln) =
   "{-# LINE "
-  <> show ln
-  <> " \""
-  <> fn
-  <> "\" #-}\n"
-
+    <> show ln
+    <> " \""
+    <> fn
+    <> "\" #-}\n"
 
 renderImport :: FileName -> LineNumber -> RequireInfo -> Text
 renderImport filename linenumber RequireInfo {..} =
-  case (Text.isInfixOf riFullModuleName (unFileName filename)) of
-    True  -> ""
-    False -> typesImport <> lineTag filename linenumber <> qualifiedImport
- where
-  types = maybe (Text.takeWhileEnd (/= '.') riFullModuleName) (Text.intercalate ",") riImportedTypes
-  typesImport = "import " <> riFullModuleName <> " (" <> types <> ")\n"
-  qualifiedImport = "import qualified " <> riFullModuleName <> " as " <> riModuleAlias <> "\n"
-
+  if Text.isInfixOf riFullModuleName (unFileName filename)
+    then ""
+    else typesImport <> lineTag filename linenumber <> qualifiedImport
+  where
+    types = maybe (Text.takeWhileEnd (/= '.') riFullModuleName) (Text.intercalate ",") riImportedTypes
+    typesImport = "import " <> riFullModuleName <> " (" <> types <> ")\n"
+    qualifiedImport = "import qualified " <> riFullModuleName <> " as " <> riModuleAlias <> "\n"
 
 requireParser :: Parser RequireInfo
 requireParser = do
   void $ Megaparsec.string "require"
-  void $ Megaparsec.space1
+  void Megaparsec.space1
   module' <- Megaparsec.some (Megaparsec.alphaNumChar <|> Megaparsec.punctuationChar)
-  void $ Megaparsec.space
-
-  alias'  <- Megaparsec.try $ Megaparsec.option Nothing $ do
+  void Megaparsec.space
+  alias' <- Megaparsec.try $ Megaparsec.option Nothing $ do
     void $ Megaparsec.string "as"
-    void $ Megaparsec.space1
-    Just <$> Megaparsec.some (Megaparsec.alphaNumChar)
-
-  void $ Megaparsec.space
-
-  types'  <- Megaparsec.option Nothing $ do
+    void Megaparsec.space1
+    Just <$> Megaparsec.some Megaparsec.alphaNumChar
+  void Megaparsec.space
+  types' <- Megaparsec.option Nothing $ do
     void $ Megaparsec.char '('
     t' <- Megaparsec.many (Megaparsec.alphaNumChar <|> Megaparsec.char ',' <|> Megaparsec.char ' ')
     void $ Megaparsec.char ')'
     return $ Just t'
-
   void $ Megaparsec.option Nothing $ do
-    void $ Megaparsec.space
+    void Megaparsec.space
     void $ Megaparsec.some (Megaparsec.char '-')
     void $ Megaparsec.many (Megaparsec.alphaNumChar <|> Megaparsec.char ' ')
     return Nothing
-
-  return RequireInfo
-    { riFullModuleName = toText $ module'
-    , riModuleAlias    = maybe (Text.takeWhileEnd (/= '.') $ toText module') toText alias'
-    , riImportedTypes  = fmap Text.strip <$> Text.splitOn "," <$> toText <$> types'
-    }
+  return
+    RequireInfo
+      { riFullModuleName = toText module',
+        riModuleAlias = maybe (Text.takeWhileEnd (/= '.') $ toText module') toText alias',
+        riImportedTypes = (fmap Text.strip <$> Text.splitOn ",") . toText <$> types'
+      }
diff --git a/package.yaml b/package.yaml
--- a/package.yaml
+++ b/package.yaml
@@ -1,5 +1,5 @@
 name: require
-version: "0.4.5"
+version: "0.4.6"
 github: "theam/require"
 license: Apache-2.0
 author: "The Agile Monkeys"
@@ -29,7 +29,7 @@
 
 dependencies:
   - base >= 4.9 && < 5
-  - universum >= 1.2.0 && < 2
+  - relude
   - bytestring >= 0.10 && < 0.11
   - text >= 1.2.3.0 && < 2
   - megaparsec >= 7 && < 8
diff --git a/require.cabal b/require.cabal
--- a/require.cabal
+++ b/require.cabal
@@ -4,10 +4,10 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: b849a629980c70464aa83e3846fceb3efdc2bed39b17efb17ad90970ee0da8e7
+-- hash: f6bc9c2371f0a167829d05ea4cb94a51e5d3ca3e2bc863a82685611213b5cb05
 
 name:           require
-version:        0.4.5
+version:        0.4.6
 synopsis:       Scrap your qualified import clutter
 description:    See <https://theam.github.io/require>
 category:       Other
@@ -47,8 +47,8 @@
     , inliterate
     , megaparsec >=7 && <8
     , optparse-generic
+    , relude
     , text >=1.2.3.0 && <2
-    , universum >=1.2.0 && <2
   default-language: Haskell2010
 
 executable autorequirepp
@@ -66,9 +66,9 @@
     , inliterate
     , megaparsec >=7 && <8
     , optparse-generic
+    , relude
     , require
     , text >=1.2.3.0 && <2
-    , universum >=1.2.0 && <2
   default-language: Haskell2010
 
 executable requirepp
@@ -86,9 +86,9 @@
     , inliterate
     , megaparsec >=7 && <8
     , optparse-generic
+    , relude
     , require
     , text >=1.2.3.0 && <2
-    , universum >=1.2.0 && <2
   default-language: Haskell2010
 
 test-suite require-test-suite
@@ -107,11 +107,11 @@
     , inliterate
     , megaparsec >=7 && <8
     , optparse-generic
+    , relude
     , require
     , tasty
     , tasty-hspec
     , text >=1.2.3.0 && <2
-    , universum >=1.2.0 && <2
   default-language: Haskell2010
 
 benchmark require-benchmarks
@@ -131,7 +131,7 @@
     , inliterate
     , megaparsec >=7 && <8
     , optparse-generic
+    , relude
     , require
     , text >=1.2.3.0 && <2
-    , universum >=1.2.0 && <2
   default-language: Haskell2010
diff --git a/stack.yaml b/stack.yaml
--- a/stack.yaml
+++ b/stack.yaml
@@ -1,67 +1,6 @@
-# This file was automatically generated by 'stack init'
-#
-# Some commonly used options have been documented as comments in this file.
-# For advanced use and comprehensive documentation of the format, please see:
-# https://docs.haskellstack.org/en/stable/yaml_configuration/
-
-# Resolver to choose a 'specific' stackage snapshot or a compiler version.
-# A snapshot resolver dictates the compiler version and the set of packages
-# to be used for project dependencies. For example:
-#
-# resolver: lts-3.5
-# resolver: nightly-2015-09-21
-# resolver: ghc-7.10.2
-# resolver: ghcjs-0.1.0_ghc-7.10.2
-# resolver:
-#  name: custom-snapshot
-#  location: "./custom-snapshot.yaml"
-resolver: lts-13.3
+resolver: lts-14.27
 
-# User packages to be built.
-# Various formats can be used as shown in the example below.
-#
-# packages:
-# - some-directory
-# - https://example.com/foo/bar/baz-0.0.2.tar.gz
-# - location:
-#    git: https://github.com/commercialhaskell/stack.git
-#    commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a
-# - location: https://github.com/commercialhaskell/stack/commit/e7b331f14bcffb8367cd58fbfc8b40ec7642100a
-#   extra-dep: true
-#  subdirs:
-#  - auto-update
-#  - wai
-#
-# A package marked 'extra-dep: true' will only be built if demanded by a
-# non-dependency (i.e. a user package), and its test suites and benchmarks
-# will not be run. This is useful for tweaking upstream packages.
 packages:
-- .
-# Dependency packages to be pulled from upstream that are not in the resolver
-# (e.g., acme-missiles-0.3)
-extra-deps:
-  - universum-1.2.0
-
-# Override default flag values for local packages and extra-deps
-# flags: {}
-
-# Extra package databases containing global packages
-# extra-package-dbs: []
+  - .
 
-# Control whether we use the GHC we find on the path
-# system-ghc: true
-#
-# Require a specific version of stack, using version ranges
-# require-stack-version: -any # Default
-# require-stack-version: ">=1.6"
-#
-# Override the architecture used by stack, especially useful on Windows
-# arch: i386
-# arch: x86_64
-#
-# Extra directories used by stack for building
-# extra-include-dirs: [/path/to/dir]
-# extra-lib-dirs: [/path/to/dir]
-#
-# Allow a newer minor version of GHC than the snapshot specifies
-# compiler-check: newer-minor
+extra-deps: []
diff --git a/test-suite/Main.hs b/test-suite/Main.hs
--- a/test-suite/Main.hs
+++ b/test-suite/Main.hs
@@ -1,81 +1,69 @@
-import           Universum
-
-import qualified Data.Text        as Text
-import qualified Test.Tasty
-import           Test.Tasty.Hspec
-
+import qualified Data.Text as Text
+import Relude
 import qualified Require
-
+import qualified Test.Tasty
+import Test.Tasty.Hspec
 
 main :: IO ()
 main = do
-    test <- testSpec "require" spec
-    Test.Tasty.defaultMain test
-
+  test <- testSpec "require" spec
+  Test.Tasty.defaultMain test
 
 spec :: Spec
 spec = parallel $ do
   it "transforms the 'require' keyword into a properly qualified import" $ do
-    let input    = "require Data.Text"
+    let input = "require Data.Text"
     let expected = "import qualified Data.Text as Text"
-    let actual   = Require.transform False (Require.FileName "Foo.hs") "" input
+    let actual = Require.transform False (Require.FileName "Foo.hs") "" input
     expected `Text.isInfixOf` actual
-
   it "imports the type based on the module" $ do
-    let input    = "require Data.Text"
+    let input = "require Data.Text"
     let expected = "import Data.Text (Text)"
-    let actual   = Require.transform False (Require.FileName "Foo.hs") "" input
+    let actual = Require.transform False (Require.FileName "Foo.hs") "" input
     expected `Text.isInfixOf` actual
-
   it "keeps the rest of the content intact" $ do
-    let input                   = "module Foo where\nrequire Data.Text\nfoo = 42"
-    let expectedStart           = "{-# LINE 1"
-    let expectedModule          = "module Foo where"
-    let expectedTypeImport      = "import Data.Text (Text)"
+    let input = "module Foo where\nrequire Data.Text\nfoo = 42"
+    let expectedStart = "{-# LINE 1"
+    let expectedModule = "module Foo where"
+    let expectedTypeImport = "import Data.Text (Text)"
     let expectedQualifiedImport = "import qualified Data.Text as Text"
-    let expectedContent         = "foo = 42\n"
-    let actual                  = toString $ Require.transform False (Require.FileName "Foo.hs") "" input
+    let expectedContent = "foo = 42\n"
+    let actual = toString $ Require.transform False (Require.FileName "Foo.hs") "" input
     actual `shouldStartWith` expectedStart
-    actual `shouldContain`   expectedModule
-    actual `shouldContain`   expectedTypeImport
-    actual `shouldContain`   expectedQualifiedImport
-    actual `shouldEndWith`   expectedContent
-
+    actual `shouldContain` expectedModule
+    actual `shouldContain` expectedTypeImport
+    actual `shouldContain` expectedQualifiedImport
+    actual `shouldEndWith` expectedContent
   it "aliases the modules properly" $ do
     let input = "require Data.Text as Foo"
     let expectedTypeImport = "import Data.Text (Text)"
     let expectedQualifiedImport = "import qualified Data.Text as Foo"
     let actual = toString $ Require.transform False (Require.FileName "Foo.hs") "" input
-    actual `shouldContain`   expectedTypeImport
-    actual `shouldContain`   expectedQualifiedImport
-
+    actual `shouldContain` expectedTypeImport
+    actual `shouldContain` expectedQualifiedImport
   it "imports the types properly" $ do
     let input = "require Data.Text (Foo)"
     let expectedTypeImport = "import Data.Text (Foo)"
     let expectedQualifiedImport = "import qualified Data.Text as Text"
     let actual = toString $ Require.transform False (Require.FileName "Foo.hs") "" input
-    actual `shouldContain`   expectedTypeImport
-    actual `shouldContain`   expectedQualifiedImport
-
+    actual `shouldContain` expectedTypeImport
+    actual `shouldContain` expectedQualifiedImport
   it "imports the types and aliases the modules properly" $ do
     let input = "require Data.Text as Quux (Foo)"
     let expectedTypeImport = "import Data.Text (Foo)"
     let expectedQualifiedImport = "import qualified Data.Text as Quux"
     let actual = toString $ Require.transform False (Require.FileName "Foo.hs") "" input
-    actual `shouldContain`   expectedTypeImport
-    actual `shouldContain`   expectedQualifiedImport
-
+    actual `shouldContain` expectedTypeImport
+    actual `shouldContain` expectedQualifiedImport
   it "skips comments" $ do
-    let input    = "require Data.Text -- test of comments"
+    let input = "require Data.Text -- test of comments"
     let expected = "import Data.Text (Text)"
-    let actual   = Require.transform False (Require.FileName "Foo.hs") "" input
+    let actual = Require.transform False (Require.FileName "Foo.hs") "" input
     expected `Text.isInfixOf` actual
-
   it "allows empty parentheses" $ do
-    let input       = "require Data.Text ()"
-    let expected1   = "import Data.Text ()"
-    let expected2   = "import qualified Data.Text as Text"
-    let actual      = lines $ Require.transform False (Require.FileName "Foo.hs") "" input
+    let input = "require Data.Text ()"
+    let expected1 = "import Data.Text ()"
+    let expected2 = "import qualified Data.Text as Text"
+    let actual = lines $ Require.transform False (Require.FileName "Foo.hs") "" input
     actual `shouldSatisfy` elem expected1
     actual `shouldSatisfy` elem expected2
-
