diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,3 @@
+## 0.0.1.0
+
+- Initial release
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,13 @@
+Copyright 2017 CJ Affiliate by Conversant
+
+Permission to use, copy, modify, and/or distribute this software for any purpose
+with or without fee is hereby granted, provided that the above copyright notice
+and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,34 @@
+# monad-persist [![Build Status](https://travis-ci.org/cjdev/monad-persist.svg?branch=master)](https://travis-ci.org/cjdev/monad-persist)
+
+This module provides an [mtl][]-style `MonadPersist` typeclass for [persistent][], as well as a `PersistT` monad transformer that implements it. This makes it easier to use persistent in an arbitrary monad transformer stack, rather than one that must be `ReaderT` over `MonadIO`.
+
+```haskell
+import Control.Monad.Logger (runNoLoggingT)
+import Control.Monad.Persist
+import Data.Text (Text)
+import Database.Persist.Sqlite (withSqliteConn)
+import Database.Persist.TH
+
+share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
+User
+  name Text
+  email Text
+
+  UniqueEmail email
+
+  deriving Eq Show
+|]
+
+
+ghci> runNoLoggingT $ withSqliteConn ":memory:" $ \conn -> flip runSqlPersistT conn $ do
+        runMigration migrateAll
+        insert_ User { userName = "Alyssa", userEmail = "alyssa@example.com" }
+        users <- selectList [] []
+        return (users :: [Entity User])
+
+Migrating: CREATE TABLE "user"("id" INTEGER PRIMARY KEY,"name" VARCHAR NOT NULL,"email" VARCHAR NOT NULL,CONSTRAINT "unique_email" UNIQUE ("email"))
+[Entity {entityKey = UserKey {unUserKey = SqlBackendKey {unSqlBackendKey = 1}}, entityVal = User {userName = "Alyssa", userEmail = "alyssa@example.com"}}]
+```
+
+[mtl]: https://hackage.haskell.org/package/mtl
+[persistent]: https://hackage.haskell.org/package/persistent
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,7 @@
+-- This script is used to build and install your package. Typically you don't
+-- need to change it. The Cabal documentation has more information about this
+-- file: <https://www.haskell.org/cabal/users-guide/installing-packages.html>.
+import qualified Distribution.Simple
+
+main :: IO ()
+main = Distribution.Simple.defaultMain
diff --git a/library/Control/Monad/Persist.hs b/library/Control/Monad/Persist.hs
new file mode 100644
--- /dev/null
+++ b/library/Control/Monad/Persist.hs
@@ -0,0 +1,508 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE DefaultSignatures #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE FunctionalDependencies #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE UndecidableInstances #-}
+
+{-|
+  This module provides an @mtl@-style 'MonadPersist' typeclass for @persistent@,
+  as well as a 'PersistT' monad transformer that implements it. If you use this
+  module, it is recommended that you do /not/ import "Database.Persist.Class" or
+  "Database.Persist.Sql", since this module defines its own versions of the
+  things defined in those modules and exports them.
+
+  Most notably, the 'SqlPersistT' transformer defined in this module is distinct
+  from the 'Database.Persist.Sql.SqlPersistT' defined in "Database.Persist.Sql".
+  The former is an alias for the 'PersistT' type defined in this module, while
+  the latter is an alias for 'ReaderT' over a 'SqlBackend'.
+
+  In general, if you are using a SQL database, you should use the helper aliases
+  'MonadSqlPersist' and 'SqlPersistT' to avoid ambiguous types and complicated
+  type errors.
+-}
+module Control.Monad.Persist
+  ( module Database.Persist.Sql
+  -- * MonadPersist
+  , MonadPersist(..)
+  , PersistT
+  , runPersistT
+  -- * Specialized to SqlBackend
+  , MonadSqlPersist
+  , SqlPersistT
+  , runSqlPersistT
+  ) where
+
+import qualified Database.Persist.Sql as Sql
+
+import Control.Monad.Base (MonadBase)
+import Control.Monad.Except (MonadError, ExceptT)
+import Control.Monad.IO.Class (MonadIO)
+import Control.Monad.Logger (MonadLogger, MonadLoggerIO, LoggingT, NoLoggingT)
+import Control.Monad.Reader (MonadReader(..), ReaderT, mapReaderT, runReaderT)
+import Control.Monad.RWS (RWST)
+import Control.Monad.State (MonadState, StateT)
+import Control.Monad.Trans (MonadTrans, lift)
+import Control.Monad.Trans.Control
+  ( ComposeSt
+  , MonadBaseControl(..)
+  , MonadTransControl(..)
+  , defaultLiftBaseWith
+  , defaultLiftWith
+  , defaultRestoreM
+  , defaultRestoreT
+  )
+import Control.Monad.Writer (MonadWriter, WriterT)
+import Data.Int (Int64)
+import Data.Text (Text)
+import Database.Persist.Sql
+  ( CautiousMigration
+  , DeleteCascade
+  , Entity(..)
+  , Filter
+  , IsPersistBackend
+  , Key
+  , Migration
+  , PersistQueryRead
+  , PersistQueryWrite
+  , PersistRecordBackend
+  , PersistStoreRead
+  , PersistStoreWrite
+  , PersistUniqueRead
+  , PersistUniqueWrite
+  , PersistValue
+  , RawSql
+  , SelectOpt
+  , Sql
+  , SqlBackend
+  , Unique
+  , Update
+  , runSqlConn
+  )
+
+-- | A concrete monad transformer that implements 'MonadPersist'. To run it, use
+-- 'runPersistT'.
+--
+-- If you are using a SQL database, it’s /highly/ recommended that you use the
+-- simpler 'SqlPersistT' alias, instead.
+newtype PersistT backend m a = PersistT (ReaderT backend m a)
+  deriving ( Functor, Applicative, Monad, MonadTrans, MonadBase b, MonadError e
+           , MonadIO, MonadLogger, MonadLoggerIO, MonadState s, MonadWriter w )
+
+-- | Runs a 'PersistT' computation with an arbitrary backend.
+--
+-- If you are using a SQL database, it’s /highly/ recommended that you use
+-- 'runSqlPersistT', instead, which will run the computation in a transaction.
+runPersistT :: IsPersistBackend backend => PersistT backend m a -> backend -> m a
+runPersistT (PersistT m) = runReaderT m
+{-# INLINE runPersistT #-}
+
+-- | A simple alias that specializes 'PersistT' to 'SqlBackend'.
+type SqlPersistT = PersistT SqlBackend
+
+-- | Runs a 'SqlPersistT' computation against a SQL database. __Unlike__
+-- 'runPersistT', the computation is run inside a transaction.
+runSqlPersistT :: (MonadIO m, MonadBaseControl IO m) => SqlPersistT m a -> SqlBackend -> m a
+runSqlPersistT (PersistT m) = runSqlConn m
+{-# INLINE runSqlPersistT #-}
+
+instance MonadTransControl (PersistT backend) where
+  type StT (PersistT backend) a = StT (ReaderT SqlBackend) a
+  liftWith = defaultLiftWith PersistT (\(PersistT m) -> m)
+  {-# INLINE liftWith #-}
+  restoreT = defaultRestoreT PersistT
+  {-# INLINE restoreT #-}
+instance MonadBaseControl b m => MonadBaseControl b (PersistT backend m) where
+  type StM (PersistT backend m) a = ComposeSt (PersistT backend) m a
+  liftBaseWith = defaultLiftBaseWith
+  {-# INLINE liftBaseWith #-}
+  restoreM = defaultRestoreM
+  {-# INLINE restoreM #-}
+
+instance MonadReader r m => MonadReader r (PersistT backend m) where
+  ask = lift ask
+  {-# INLINE ask #-}
+  local f (PersistT m) = PersistT $ mapReaderT (local f) m
+  {-# INLINE local #-}
+  reader = lift . reader
+  {-# INLINE reader #-}
+
+-- | This typeclass is a simple enumeration of the functions available from
+-- "Database.Persist.Class", simply parameterized over the monad (rather than
+-- requiring 'ReaderT' over 'MonadIO'). This makes it easier to use @persistent@
+-- in an arbitrary monad transformer stack. Each method corresponds directly to
+-- a function or method defined in "Database.Persist.Class" or
+-- "Database.Persist.Sql". See the documentation for those modules for
+-- information about what each method does.
+--
+-- This typeclass is primarily implemented by the 'PersistT' monad transformer,
+-- which abstracts away the role of threading a database connection through your
+-- program. If you are using a SQL database, it is recommended that you use the
+-- 'SqlPersistT' alias and the corresponding 'runSqlPersistT' function in order
+-- to avoid unnecessarily confusing type errors and to ensure all database
+-- access is performed within a transaction.
+--
+-- This module provides 'MonadPersist' instances for various commonly-used monad
+-- transformers, but it’s possible that you may want to use a monad transformer
+-- from a different library that does not have an appropriate instance. In this
+-- case, 'MonadPersist' provides default instances for all monad transformers
+-- using the @DefaultSignatures@ GHC extension, which allows you to write empty
+-- instance declarations to make any 'MonadTrans' instance an instance of
+-- 'MonadPersist':
+--
+-- @
+-- instance MonadPersist m => MonadPersist (T m)
+-- @
+class Monad m => MonadPersist backend m | m -> backend where
+  -- PersistStore
+  get :: (PersistStoreRead backend, PersistRecordBackend record backend) => Key record -> m (Maybe record)
+
+  insert :: (PersistStoreWrite backend, PersistRecordBackend record backend) => record -> m (Key record)
+  insert_ :: (PersistStoreWrite backend, PersistRecordBackend record backend) => record -> m ()
+  insertMany :: (PersistStoreWrite backend, PersistRecordBackend record backend) => [record] -> m [Key record]
+  insertMany_ :: (PersistStoreWrite backend, PersistRecordBackend record backend) => [record] -> m ()
+  insertEntityMany :: (PersistStoreWrite backend, PersistRecordBackend record backend) => [Entity record] -> m ()
+  insertKey :: (PersistStoreWrite backend, PersistRecordBackend record backend) => Key record -> record -> m ()
+  repsert :: (PersistStoreWrite backend, PersistRecordBackend record backend) => Key record -> record -> m ()
+  replace :: (PersistStoreWrite backend, PersistRecordBackend record backend) => Key record -> record -> m ()
+  delete :: (PersistStoreWrite backend, PersistRecordBackend record backend) => Key record -> m ()
+  update :: (PersistStoreWrite backend, PersistRecordBackend record backend) => Key record -> [Update record] -> m ()
+  updateGet :: (PersistStoreWrite backend, PersistRecordBackend record backend) => Key record -> [Update record] -> m record
+
+  getJust :: (PersistStoreRead backend, PersistRecordBackend record backend) => Key record -> m record
+  belongsTo :: (PersistStoreRead backend, PersistRecordBackend record1 backend, PersistRecordBackend record2 backend) => (record1 -> Maybe (Key record2)) -> record1 -> m (Maybe record2)
+  belongsToJust :: (PersistStoreRead backend, PersistRecordBackend record1 backend, PersistRecordBackend record2 backend) => (record1 -> Key record2) -> record1 -> m record2
+  insertEntity :: (PersistStoreWrite backend, PersistRecordBackend record backend) => record -> m (Entity record)
+
+  -- PersistUnique
+  getBy :: (PersistUniqueRead backend, PersistRecordBackend record backend) => Unique record -> m (Maybe (Entity record))
+
+  deleteBy :: (PersistUniqueWrite backend, PersistRecordBackend record backend) => Unique record -> m ()
+  insertUnique :: (PersistUniqueWrite backend, PersistRecordBackend record backend) => record -> m (Maybe (Key record))
+  upsert :: (PersistUniqueWrite backend, PersistRecordBackend record backend) => record -> [Update record] -> m (Entity record)
+
+  getByValue :: (PersistUniqueRead backend, PersistRecordBackend record backend) => record -> m (Maybe (Entity record))
+  insertBy :: (PersistUniqueWrite backend, PersistRecordBackend record backend) => record -> m (Either (Entity record) (Key record))
+  replaceUnique :: (PersistUniqueWrite backend, PersistRecordBackend record backend, Eq record, Eq (Unique record)) => Key record -> record -> m (Maybe (Unique record))
+  checkUnique :: (PersistUniqueRead backend, PersistRecordBackend record backend) => record -> m (Maybe (Unique record))
+  onlyUnique :: (PersistUniqueWrite backend, PersistRecordBackend record backend) => record -> m (Unique record)
+
+  -- PersistQuery
+  selectFirst :: (PersistQueryRead backend, PersistRecordBackend record backend) => [Filter record] -> [SelectOpt record] -> m (Maybe (Entity record))
+  count :: (PersistQueryRead backend, PersistRecordBackend record backend) => [Filter record] -> m Int
+
+  updateWhere :: (PersistQueryWrite backend, PersistRecordBackend record backend) => [Filter record] -> [Update record] -> m ()
+  deleteWhere :: (PersistQueryWrite backend, PersistRecordBackend record backend) => [Filter record] -> m ()
+
+  selectList :: (PersistQueryRead backend, PersistRecordBackend record backend) => [Filter record] -> [SelectOpt record] -> m [Entity record]
+  selectKeysList :: (PersistQueryRead backend, PersistRecordBackend record backend) => [Filter record] -> [SelectOpt record] -> m [Key record]
+
+  -- DeleteCascade
+  deleteCascade :: DeleteCascade record backend => Key record -> m ()
+  deleteCascadeWhere :: (DeleteCascade record backend, PersistQueryWrite backend) => [Filter record] -> m ()
+
+  -- Database.Persist.Sql
+  parseMigration :: (backend ~ SqlBackend) => Migration -> m (Either [Text] CautiousMigration)
+  parseMigration' :: (backend ~ SqlBackend) => Migration -> m CautiousMigration
+  printMigration :: (backend ~ SqlBackend) => Migration -> m ()
+  showMigration :: (backend ~ SqlBackend) => Migration -> m [Text]
+  getMigration :: (backend ~ SqlBackend) => Migration -> m [Sql]
+  runMigration :: (backend ~ SqlBackend) => Migration -> m ()
+  runMigrationSilent :: (backend ~ SqlBackend) => Migration -> m [Text]
+  runMigrationUnsafe :: (backend ~ SqlBackend) => Migration -> m ()
+
+  rawExecute :: (backend ~ SqlBackend) => Text -> [PersistValue] -> m ()
+  rawExecuteCount :: (backend ~ SqlBackend) => Text -> [PersistValue] -> m Int64
+  rawSql :: (backend ~ SqlBackend, RawSql a) => Text -> [PersistValue] -> m [a]
+  transactionSave :: (backend ~ SqlBackend) => m ()
+  transactionUndo :: (backend ~ SqlBackend) => m ()
+
+  default get :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, PersistStoreRead backend, PersistRecordBackend record backend) => Key record -> m (Maybe record)
+  default insert :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, PersistStoreWrite backend, PersistRecordBackend record backend) => record -> m (Key record)
+  default insert_ :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, PersistStoreWrite backend, PersistRecordBackend record backend) => record -> m ()
+  default insertMany :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, PersistStoreWrite backend, PersistRecordBackend record backend) => [record] -> m [Key record]
+  default insertMany_ :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, PersistStoreWrite backend, PersistRecordBackend record backend) => [record] -> m ()
+  default insertEntityMany :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, PersistStoreWrite backend, PersistRecordBackend record backend) => [Entity record] -> m ()
+  default insertKey :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, PersistStoreWrite backend, PersistRecordBackend record backend) => Key record -> record -> m ()
+  default repsert :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, PersistStoreWrite backend, PersistRecordBackend record backend) => Key record -> record -> m ()
+  default replace :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, PersistStoreWrite backend, PersistRecordBackend record backend) => Key record -> record -> m ()
+  default delete :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, PersistStoreWrite backend, PersistRecordBackend record backend) => Key record -> m ()
+  default update :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, PersistStoreWrite backend, PersistRecordBackend record backend) => Key record -> [Update record] -> m ()
+  default updateGet :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, PersistStoreWrite backend, PersistRecordBackend record backend) => Key record -> [Update record] -> m record
+  default getJust :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, PersistStoreRead backend, PersistRecordBackend record backend) => Key record -> m record
+  default belongsTo :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, PersistStoreRead backend, PersistRecordBackend record1 backend, PersistRecordBackend record2 backend) => (record1 -> Maybe (Key record2)) -> record1 -> m (Maybe record2)
+  default belongsToJust :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, PersistStoreRead backend, PersistRecordBackend record1 backend, PersistRecordBackend record2 backend) => (record1 -> Key record2) -> record1 -> m record2
+  default insertEntity :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, PersistStoreWrite backend, PersistRecordBackend record backend) => record -> m (Entity record)
+  default getBy :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, PersistUniqueRead backend, PersistRecordBackend record backend) => Unique record -> m (Maybe (Entity record))
+  default deleteBy :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, PersistUniqueWrite backend, PersistRecordBackend record backend) => Unique record -> m ()
+  default insertUnique :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, PersistUniqueWrite backend, PersistRecordBackend record backend) => record -> m (Maybe (Key record))
+  default upsert :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, PersistUniqueWrite backend, PersistRecordBackend record backend) => record -> [Update record] -> m (Entity record)
+  default getByValue :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, PersistUniqueRead backend, PersistRecordBackend record backend) => record -> m (Maybe (Entity record))
+  default insertBy :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, PersistUniqueWrite backend, PersistRecordBackend record backend) => record -> m (Either (Entity record) (Key record))
+  default replaceUnique :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, PersistUniqueWrite backend, PersistRecordBackend record backend, Eq record, Eq (Unique record)) => Key record -> record -> m (Maybe (Unique record))
+  default checkUnique :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, PersistUniqueRead backend, PersistRecordBackend record backend) => record -> m (Maybe (Unique record))
+  default onlyUnique :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, PersistUniqueWrite backend, PersistRecordBackend record backend) => record -> m (Unique record)
+  default selectFirst :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, PersistQueryRead backend, PersistRecordBackend record backend) => [Filter record] -> [SelectOpt record] -> m (Maybe (Entity record))
+  default count :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, PersistQueryRead backend, PersistRecordBackend record backend) => [Filter record] -> m Int
+  default updateWhere :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, PersistQueryWrite backend, PersistRecordBackend record backend) => [Filter record] -> [Update record] -> m ()
+  default deleteWhere :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, PersistQueryWrite backend, PersistRecordBackend record backend) => [Filter record] -> m ()
+  default selectList :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, PersistQueryRead backend, PersistRecordBackend record backend) => [Filter record] -> [SelectOpt record] -> m [Entity record]
+  default selectKeysList :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, PersistQueryRead backend, PersistRecordBackend record backend) => [Filter record] -> [SelectOpt record] -> m [Key record]
+  default deleteCascade :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, DeleteCascade record backend) => Key record -> m ()
+  default deleteCascadeWhere :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, DeleteCascade record backend, PersistQueryWrite backend) => [Filter record] -> m ()
+  default parseMigration :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, backend ~ SqlBackend) => Migration -> m (Either [Text] CautiousMigration)
+  default parseMigration' :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, backend ~ SqlBackend) => Migration -> m CautiousMigration
+  default printMigration :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, backend ~ SqlBackend) => Migration -> m ()
+  default showMigration :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, backend ~ SqlBackend) => Migration -> m [Text]
+  default getMigration :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, backend ~ SqlBackend) => Migration -> m [Sql]
+  default runMigration :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, backend ~ SqlBackend) => Migration -> m ()
+  default runMigrationSilent :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, backend ~ SqlBackend) => Migration -> m [Text]
+  default runMigrationUnsafe :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, backend ~ SqlBackend) => Migration -> m ()
+  default rawExecute :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, backend ~ SqlBackend) => Text -> [PersistValue] -> m ()
+  default rawExecuteCount :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, backend ~ SqlBackend) => Text -> [PersistValue] -> m Int64
+  default rawSql :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, backend ~ SqlBackend, RawSql a) => Text -> [PersistValue] -> m [a]
+  default transactionSave :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, backend ~ SqlBackend) => m ()
+  default transactionUndo :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, backend ~ SqlBackend) => m ()
+
+  get a = lift $ get a
+  insert a = lift $ insert a
+  insert_ a = lift $ insert_ a
+  insertMany a = lift $ insertMany a
+  insertMany_ a = lift $ insertMany_ a
+  insertEntityMany a = lift $ insertEntityMany a
+  insertKey a b = lift $ insertKey a b
+  repsert a b = lift $ repsert a b
+  replace a b = lift $ replace a b
+  delete a = lift $ delete a
+  update a b = lift $ update a b
+  updateGet a b = lift $ updateGet a b
+  getJust a = lift $ getJust a
+  belongsTo a b = lift $ belongsTo a b
+  belongsToJust a b = lift $ belongsToJust a b
+  insertEntity a = lift $ insertEntity a
+  getBy a = lift $ getBy a
+  deleteBy a = lift $ deleteBy a
+  insertUnique a = lift $ insertUnique a
+  upsert a b = lift $ upsert a b
+  getByValue a = lift $ getByValue a
+  insertBy a = lift $ insertBy a
+  replaceUnique a b = lift $ replaceUnique a b
+  checkUnique a = lift $ checkUnique a
+  onlyUnique a = lift $ onlyUnique a
+  selectFirst a b = lift $ selectFirst a b
+  count a = lift $ count a
+  updateWhere a b = lift $ updateWhere a b
+  deleteWhere a = lift $ deleteWhere a
+  selectList a b = lift $ selectList a b
+  selectKeysList a b = lift $ selectKeysList a b
+  deleteCascade a = lift $ deleteCascade a
+  deleteCascadeWhere a = lift $ deleteCascadeWhere a
+  parseMigration a = lift $ parseMigration a
+  parseMigration' a = lift $ parseMigration' a
+  printMigration a = lift $ printMigration a
+  showMigration a = lift $ showMigration a
+  getMigration a = lift $ getMigration a
+  runMigration a = lift $ runMigration a
+  runMigrationSilent a = lift $ runMigrationSilent a
+  runMigrationUnsafe a = lift $ runMigrationUnsafe a
+  rawExecute a b = lift $ rawExecute a b
+  rawExecuteCount a b = lift $ rawExecuteCount a b
+  rawSql a b = lift $ rawSql a b
+  transactionSave = lift transactionSave
+  transactionUndo = lift transactionUndo
+
+  {-# INLINE get #-}
+  {-# INLINE insert #-}
+  {-# INLINE insert_ #-}
+  {-# INLINE insertMany #-}
+  {-# INLINE insertMany_ #-}
+  {-# INLINE insertEntityMany #-}
+  {-# INLINE insertKey #-}
+  {-# INLINE repsert #-}
+  {-# INLINE replace #-}
+  {-# INLINE delete #-}
+  {-# INLINE update #-}
+  {-# INLINE updateGet #-}
+  {-# INLINE getJust #-}
+  {-# INLINE belongsTo #-}
+  {-# INLINE belongsToJust #-}
+  {-# INLINE insertEntity #-}
+  {-# INLINE getBy #-}
+  {-# INLINE deleteBy #-}
+  {-# INLINE insertUnique #-}
+  {-# INLINE upsert #-}
+  {-# INLINE getByValue #-}
+  {-# INLINE insertBy #-}
+  {-# INLINE replaceUnique #-}
+  {-# INLINE checkUnique #-}
+  {-# INLINE onlyUnique #-}
+  {-# INLINE selectFirst #-}
+  {-# INLINE count #-}
+  {-# INLINE updateWhere #-}
+  {-# INLINE deleteWhere #-}
+  {-# INLINE selectList #-}
+  {-# INLINE selectKeysList #-}
+  {-# INLINE deleteCascade #-}
+  {-# INLINE deleteCascadeWhere #-}
+  {-# INLINE parseMigration #-}
+  {-# INLINE parseMigration' #-}
+  {-# INLINE printMigration #-}
+  {-# INLINE showMigration #-}
+  {-# INLINE getMigration #-}
+  {-# INLINE runMigration #-}
+  {-# INLINE runMigrationSilent #-}
+  {-# INLINE runMigrationUnsafe #-}
+  {-# INLINE rawExecute #-}
+  {-# INLINE rawExecuteCount #-}
+  {-# INLINE rawSql #-}
+  {-# INLINE transactionSave #-}
+  {-# INLINE transactionUndo #-}
+
+#if MIN_VERSION_persistent(2,6,0)
+  upsertBy :: (PersistUniqueWrite backend, PersistRecordBackend record backend) => Unique record -> record -> [Update record] -> m (Entity record)
+  default upsertBy :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, PersistUniqueWrite backend, PersistRecordBackend record backend) => Unique record -> record -> [Update record] -> m (Entity record)
+  upsertBy a b c = lift $ upsertBy a b c
+  {-# INLINE upsertBy #-}
+#endif
+#if MIN_VERSION_persistent(2,6,1)
+  getJustEntity :: (PersistStoreRead backend, PersistRecordBackend record backend) => Key record -> m (Entity record)
+  getEntity :: (PersistStoreWrite backend, PersistRecordBackend record backend) => Key record -> m (Maybe (Entity record))
+  insertRecord :: (PersistStoreWrite backend, PersistRecordBackend record backend) => record -> m record
+
+  default getJustEntity :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, PersistStoreRead backend, PersistRecordBackend record backend) => Key record -> m (Entity record)
+  default getEntity :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, PersistStoreWrite backend, PersistRecordBackend record backend) => Key record -> m (Maybe (Entity record))
+  default insertRecord :: (Monad (t m'), MonadPersist backend m', MonadTrans t, t m' ~ m, PersistStoreWrite backend, PersistRecordBackend record backend) => record -> m record
+
+  getJustEntity a = lift $ getJustEntity a
+  getEntity a = lift $ getEntity a
+  insertRecord a = lift $ insertRecord a
+
+  {-# INLINE getJustEntity #-}
+  {-# INLINE getEntity #-}
+  {-# INLINE insertRecord #-}
+#endif
+
+-- | A simple alias that specializes 'MonadPersist' to 'SqlBackend'.
+type MonadSqlPersist = MonadPersist SqlBackend
+
+instance (MonadIO m, MonadBaseControl IO m) => MonadPersist backend (PersistT backend m) where
+  get a = PersistT $ Sql.get a
+  insert a = PersistT $ Sql.insert a
+  insert_ a = PersistT $ Sql.insert_ a
+  insertMany a = PersistT $ Sql.insertMany a
+  insertMany_ a = PersistT $ Sql.insertMany_ a
+  insertEntityMany a = PersistT $ Sql.insertEntityMany a
+  insertKey a b = PersistT $ Sql.insertKey a b
+  repsert a b = PersistT $ Sql.repsert a b
+  replace a b = PersistT $ Sql.replace a b
+  delete a = PersistT $ Sql.delete a
+  update a b = PersistT $ Sql.update a b
+  updateGet a b = PersistT $ Sql.updateGet a b
+  getJust a = PersistT $ Sql.getJust a
+  belongsTo a b = PersistT $ Sql.belongsTo a b
+  belongsToJust a b = PersistT $ Sql.belongsToJust a b
+  insertEntity a = PersistT $ Sql.insertEntity a
+  getBy a = PersistT $ Sql.getBy a
+  deleteBy a = PersistT $ Sql.deleteBy a
+  insertUnique a = PersistT $ Sql.insertUnique a
+  upsert a b = PersistT $ Sql.upsert a b
+  getByValue a = PersistT $ Sql.getByValue a
+  insertBy a = PersistT $ Sql.insertBy a
+  replaceUnique a b = PersistT $ Sql.replaceUnique a b
+  checkUnique a = PersistT $ Sql.checkUnique a
+  onlyUnique a = PersistT $ Sql.onlyUnique a
+  selectFirst a b = PersistT $ Sql.selectFirst a b
+  count a = PersistT $ Sql.count a
+  updateWhere a b = PersistT $ Sql.updateWhere a b
+  deleteWhere a = PersistT $ Sql.deleteWhere a
+  selectList a b = PersistT $ Sql.selectList a b
+  selectKeysList a b = PersistT $ Sql.selectKeysList a b
+  deleteCascade a = PersistT $ Sql.deleteCascade a
+  deleteCascadeWhere a = PersistT $ Sql.deleteCascadeWhere a
+  parseMigration a = PersistT $ Sql.parseMigration a
+  parseMigration' a = PersistT $ Sql.parseMigration' a
+  printMigration a = PersistT $ Sql.printMigration a
+  showMigration a = PersistT $ Sql.showMigration a
+  getMigration a = PersistT $ Sql.getMigration a
+  runMigration a = PersistT $ Sql.runMigration a
+  runMigrationSilent a = PersistT $ Sql.runMigrationSilent a
+  runMigrationUnsafe a = PersistT $ Sql.runMigrationUnsafe a
+  rawExecute a b = PersistT $ Sql.rawExecute a b
+  rawExecuteCount a b = PersistT $ Sql.rawExecuteCount a b
+  rawSql a b = PersistT $ Sql.rawSql a b
+  transactionSave = PersistT Sql.transactionSave
+  transactionUndo = PersistT Sql.transactionUndo
+
+  {-# INLINE get #-}
+  {-# INLINE insert #-}
+  {-# INLINE insert_ #-}
+  {-# INLINE insertMany #-}
+  {-# INLINE insertMany_ #-}
+  {-# INLINE insertEntityMany #-}
+  {-# INLINE insertKey #-}
+  {-# INLINE repsert #-}
+  {-# INLINE replace #-}
+  {-# INLINE delete #-}
+  {-# INLINE update #-}
+  {-# INLINE updateGet #-}
+  {-# INLINE getJust #-}
+  {-# INLINE belongsTo #-}
+  {-# INLINE belongsToJust #-}
+  {-# INLINE insertEntity #-}
+  {-# INLINE getBy #-}
+  {-# INLINE deleteBy #-}
+  {-# INLINE insertUnique #-}
+  {-# INLINE upsert #-}
+  {-# INLINE getByValue #-}
+  {-# INLINE insertBy #-}
+  {-# INLINE replaceUnique #-}
+  {-# INLINE checkUnique #-}
+  {-# INLINE onlyUnique #-}
+  {-# INLINE selectFirst #-}
+  {-# INLINE count #-}
+  {-# INLINE updateWhere #-}
+  {-# INLINE deleteWhere #-}
+  {-# INLINE selectList #-}
+  {-# INLINE selectKeysList #-}
+  {-# INLINE deleteCascade #-}
+  {-# INLINE deleteCascadeWhere #-}
+  {-# INLINE parseMigration #-}
+  {-# INLINE parseMigration' #-}
+  {-# INLINE printMigration #-}
+  {-# INLINE showMigration #-}
+  {-# INLINE getMigration #-}
+  {-# INLINE runMigration #-}
+  {-# INLINE runMigrationSilent #-}
+  {-# INLINE runMigrationUnsafe #-}
+  {-# INLINE rawExecute #-}
+  {-# INLINE rawExecuteCount #-}
+  {-# INLINE rawSql #-}
+  {-# INLINE transactionSave #-}
+  {-# INLINE transactionUndo #-}
+
+#if MIN_VERSION_persistent(2,6,0)
+  upsertBy a b c = PersistT $ Sql.upsertBy a b c
+  {-# INLINE upsertBy #-}
+#endif
+#if MIN_VERSION_persistent(2,6,1)
+  getJustEntity a = PersistT $ Sql.getJustEntity a
+  getEntity a = PersistT $ Sql.getEntity a
+  insertRecord a = PersistT $ Sql.insertRecord a
+
+  {-# INLINE getJustEntity #-}
+  {-# INLINE getEntity #-}
+  {-# INLINE insertRecord #-}
+#endif
+
+instance MonadPersist backend m => MonadPersist backend (ExceptT e m)
+instance MonadPersist backend m => MonadPersist backend (ReaderT r m)
+instance (Monoid w, MonadPersist backend m) => MonadPersist backend (RWST r w s m)
+instance MonadPersist backend m => MonadPersist backend (StateT s m)
+instance (Monoid w, MonadPersist backend m) => MonadPersist backend (WriterT w m)
+
+instance MonadPersist backend m => MonadPersist backend (LoggingT m)
+instance MonadPersist backend m => MonadPersist backend (NoLoggingT m)
diff --git a/monad-persist.cabal b/monad-persist.cabal
new file mode 100644
--- /dev/null
+++ b/monad-persist.cabal
@@ -0,0 +1,58 @@
+-- This file has been generated from package.yaml by hpack version 0.15.0.
+--
+-- see: https://github.com/sol/hpack
+
+name:           monad-persist
+version:        0.0.1.0
+synopsis:       An mtl-style typeclass and transformer for persistent.
+description:    An mtl-style typeclass and transformer for persistent.
+category:       Database
+author:         Alexis King <lexi.lambda@gmail.com>
+maintainer:     Alexis King <lexi.lambda@gmail.com>
+copyright:      2017 CJ Affiliate by Conversant
+license:        ISC
+license-file:   LICENSE
+build-type:     Simple
+cabal-version:  >= 1.10
+
+extra-source-files:
+    CHANGELOG.md
+    package.yaml
+    README.md
+    stack.yaml
+
+library
+  hs-source-dirs:
+      library
+  ghc-options: -Wall
+  build-depends:
+      base >= 4.7 && < 5
+    , monad-control >= 1.0.0.0 && < 2
+    , monad-logger >= 0.3.10
+    , mtl
+    , persistent >= 2.5 && < 3
+    , text
+    , transformers-base
+  exposed-modules:
+      Control.Monad.Persist
+  default-language: Haskell2010
+
+test-suite monad-persist-test-suite
+  type: exitcode-stdio-1.0
+  main-is: Main.hs
+  hs-source-dirs:
+      test-suite
+  ghc-options: -Wall -rtsopts -threaded -with-rtsopts=-N
+  build-depends:
+      base
+    , hspec
+    , monad-control
+    , monad-logger
+    , monad-persist
+    , persistent
+    , persistent-sqlite
+    , persistent-template
+    , text
+  other-modules:
+      Control.Monad.PersistSpec
+  default-language: Haskell2010
diff --git a/package.yaml b/package.yaml
new file mode 100644
--- /dev/null
+++ b/package.yaml
@@ -0,0 +1,47 @@
+name: monad-persist
+version: 0.0.1.0
+category: Database
+synopsis: An mtl-style typeclass and transformer for persistent.
+description: An mtl-style typeclass and transformer for persistent.
+author: Alexis King <lexi.lambda@gmail.com>
+maintainer: Alexis King <lexi.lambda@gmail.com>
+copyright: 2017 CJ Affiliate by Conversant
+
+license: ISC
+extra-source-files:
+- CHANGELOG.md
+- package.yaml
+- README.md
+- stack.yaml
+
+ghc-options: -Wall
+
+library:
+  dependencies:
+  - base >= 4.7 && < 5
+  - monad-control >= 1.0.0.0 && < 2
+  - monad-logger >= 0.3.10
+  - mtl
+  - persistent >= 2.5 && < 3
+  - text
+  - transformers-base
+  source-dirs: library
+
+tests:
+  monad-persist-test-suite:
+    dependencies:
+    - base
+    - hspec
+    - monad-control
+    - monad-logger
+    - monad-persist
+    - persistent
+    - persistent-sqlite
+    - persistent-template
+    - text
+    ghc-options:
+    - -rtsopts
+    - -threaded
+    - -with-rtsopts=-N
+    main: Main.hs
+    source-dirs: test-suite
diff --git a/stack.yaml b/stack.yaml
new file mode 100644
--- /dev/null
+++ b/stack.yaml
@@ -0,0 +1,9 @@
+resolver: lts-8.11
+
+packages:
+- '.'
+extra-deps: []
+
+flags: {}
+
+extra-package-dbs: []
diff --git a/test-suite/Control/Monad/PersistSpec.hs b/test-suite/Control/Monad/PersistSpec.hs
new file mode 100644
--- /dev/null
+++ b/test-suite/Control/Monad/PersistSpec.hs
@@ -0,0 +1,58 @@
+{-# OPTIONS_GHC -fno-warn-unused-top-binds #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE QuasiQuotes #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TypeFamilies #-}
+
+module Control.Monad.PersistSpec (spec) where
+
+import qualified Test.Hspec as Hspec
+
+import Control.Monad.Logger (NoLoggingT, runNoLoggingT)
+import Control.Monad.IO.Class (MonadIO, liftIO)
+import Control.Monad.Trans.Control (MonadBaseControl)
+import Data.Text (Text)
+import Database.Persist.Sqlite (withSqliteConn)
+import Database.Persist.TH
+import Test.Hspec hiding (shouldBe)
+
+import Control.Monad.Persist
+
+share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
+User
+  name Text
+  email Text
+
+  UniqueEmail email
+
+  deriving Eq Show
+|]
+
+runSqlite :: (MonadIO m, MonadBaseControl IO m) => SqlPersistT (NoLoggingT m) a -> m a
+runSqlite x = runNoLoggingT $ withSqliteConn ":memory:" (runSqlPersistT (runMigrationSilent migrateAll >> x))
+
+shouldBe :: (Eq a, Show a, MonadIO m) => a -> a -> m ()
+shouldBe x y = liftIO $ Hspec.shouldBe x y
+
+spec :: Spec
+spec = describe "MonadPersist" $ do
+  it "can make queries against a database" $ example $ do
+    result :: [Entity User] <- runSqlite $ selectList [] []
+    result `shouldBe` []
+
+  it "can insert records into a database" $ example $ runSqlite $ do
+    let user = User { userName = "Alyssa", userEmail = "alyssa@example.com" }
+    key <- insert user
+    result <- get key
+    result `shouldBe` Just user
+
+  it "can query records by unique keys" $ example $ runSqlite $ do
+    let user = User { userName = "Alyssa", userEmail = "alyssa@example.com" }
+    insert_ user
+    result <- getBy $ UniqueEmail "alyssa@example.com"
+    fmap entityVal result `shouldBe` Just user
diff --git a/test-suite/Main.hs b/test-suite/Main.hs
new file mode 100644
--- /dev/null
+++ b/test-suite/Main.hs
@@ -0,0 +1,1 @@
+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
