diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright Author name here (c) 2020
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Author name here nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,7 @@
+# little-rio
+
+[![CircleCI](https://circleci.com/gh/ejconlon/little-rio/tree/master.svg?style=svg)](https://circleci.com/gh/ejconlon/little-rio/tree/master)
+
+When you need just the `RIO` monad (but you want a `MonadCatch` instance)
+
+This is derived from the RIO library ([LICENSE](https://hackage.haskell.org/package/rio-0.1.14.0/src/LICENSE)).
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/little-rio.cabal b/little-rio.cabal
new file mode 100644
--- /dev/null
+++ b/little-rio.cabal
@@ -0,0 +1,44 @@
+cabal-version: 1.12
+
+-- This file has been generated from package.yaml by hpack version 0.33.0.
+--
+-- see: https://github.com/sol/hpack
+--
+-- hash: 2b2090b27367642626349e26b93496440dae5c6ca1e56579cbbdee0ea5b68200
+
+name:           little-rio
+version:        0.1.0
+synopsis:       When you need just the RIO monad
+description:    Please see the README on GitHub at <https://github.com/ejconlon/little-rio#readme>
+category:       Control
+homepage:       https://github.com/ejconlon/little-rio#readme
+bug-reports:    https://github.com/ejconlon/little-rio/issues
+author:         Eric Conlon
+maintainer:     ejconlon@gmail.com
+copyright:      (c) 2020 Eric Conlon
+license:        BSD3
+license-file:   LICENSE
+build-type:     Simple
+extra-source-files:
+    README.md
+
+source-repository head
+  type: git
+  location: https://github.com/ejconlon/little-rio
+
+library
+  exposed-modules:
+      LittleRIO
+  other-modules:
+      Paths_little_rio
+  hs-source-dirs:
+      src
+  ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wpartial-fields -Wredundant-constraints -fno-warn-unused-top-binds
+  build-depends:
+      base >=4.12 && <5
+    , exceptions >=0.10
+    , microlens >=0.4
+    , microlens-mtl >=0.2
+    , mtl >=2.2
+    , unliftio-core >=0.1
+  default-language: Haskell2010
diff --git a/src/LittleRIO.hs b/src/LittleRIO.hs
new file mode 100644
--- /dev/null
+++ b/src/LittleRIO.hs
@@ -0,0 +1,144 @@
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE FunctionalDependencies #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE UndecidableInstances #-}
+
+{- |
+Most definitions follow the RIO lib: https://hackage.haskell.org/package/rio-0.1.14.0/docs/RIO.html
+See LICENSE info in the README.
+-}
+module LittleRIO
+  ( HasStateRef (..)
+  , HasWriteRef (..)
+  , SomeRef
+  , RIO (..)
+  , getStateRef
+  , liftRIO
+  , listenWriteRef
+  , newSomeRef
+  , mapRIO
+  , modifySomeRef
+  , modifyStateRef
+  , passWriteRef
+  , putStateRef
+  , runRIO
+  , readSomeRef
+  , tellWriteRef
+  , unliftRIO
+  , writeSomeRef
+  ) where
+
+import Control.Applicative (liftA2)
+import Control.Monad.Catch (MonadCatch, MonadMask, MonadThrow)
+import Control.Monad.IO.Class (MonadIO (..))
+import Control.Monad.IO.Unlift (MonadUnliftIO, UnliftIO, askUnliftIO)
+import Control.Monad.Reader (MonadReader (..), ReaderT (..))
+import Control.Monad.State (MonadState (..))
+import Control.Monad.Writer (MonadWriter (..))
+import Data.IORef (IORef, newIORef, readIORef, writeIORef)
+import Lens.Micro (Lens')
+import Lens.Micro.Mtl (view)
+import Prelude
+
+newtype RIO env a = RIO { unRIO :: ReaderT env IO a }
+  deriving (Functor, Applicative, Monad, MonadReader env, MonadIO, MonadThrow, MonadFail, MonadCatch, MonadMask, MonadUnliftIO)
+
+instance Semigroup a => Semigroup (RIO env a) where
+  (<>) = liftA2 (<>)
+
+instance Monoid a => Monoid (RIO env a) where
+  mempty = pure mempty
+  mappend = (<>)
+
+mapRIO :: (env -> env') -> RIO env' a -> RIO env a
+mapRIO f m = do
+  env <- ask
+  let env' = f env
+  runRIO env' m
+
+liftRIO :: (MonadIO m, MonadReader env m) => RIO env a -> m a
+liftRIO rio = do
+  env <- ask
+  runRIO env rio
+
+unliftRIO :: MonadIO m => env -> m (UnliftIO (RIO env))
+unliftRIO env = liftIO (runRIO env askUnliftIO)
+
+runRIO :: MonadIO m => env -> RIO env a -> m a
+runRIO r m = liftIO (runReaderT (unRIO m) r)
+
+data SomeRef a = SomeRef !(IO a) !(a -> IO ())
+
+readSomeRef :: MonadIO m => SomeRef a -> m a
+readSomeRef (SomeRef x _) = liftIO x
+
+writeSomeRef :: MonadIO m => SomeRef a -> a -> m ()
+writeSomeRef (SomeRef _ x) = liftIO . x
+
+modifySomeRef :: MonadIO m => SomeRef a -> (a -> a) -> m ()
+modifySomeRef (SomeRef read' write) f = liftIO (fmap f read' >>= write)
+
+ioRefToSomeRef :: IORef a -> SomeRef a
+ioRefToSomeRef ref = SomeRef (readIORef ref) (writeIORef ref)
+
+newSomeRef :: MonadIO m => a -> m (SomeRef a)
+newSomeRef = liftIO . fmap ioRefToSomeRef . newIORef
+
+class HasStateRef st env | env -> st where
+  stateRefL :: Lens' env (SomeRef st)
+
+instance HasStateRef a (SomeRef a) where
+  stateRefL = id
+
+getStateRef :: (HasStateRef st env, MonadReader env m, MonadIO m) => m st
+getStateRef = do
+  ref <- view stateRefL
+  liftIO (readSomeRef ref)
+
+putStateRef :: (HasStateRef st env, MonadReader env m, MonadIO m) => st -> m ()
+putStateRef st = do
+  ref <- view stateRefL
+  liftIO (writeSomeRef ref st)
+
+modifyStateRef :: (HasStateRef st env, MonadReader env m, MonadIO m) => (st -> st) -> m ()
+modifyStateRef f = do
+  ref <- view stateRefL
+  liftIO (modifySomeRef ref f)
+
+instance HasStateRef st env => MonadState st (RIO env) where
+  get = getStateRef
+  put = putStateRef
+
+class HasWriteRef w env | env -> w where
+  writeRefL :: Lens' env (SomeRef w)
+
+instance HasWriteRef a (SomeRef a) where
+  writeRefL = id
+
+tellWriteRef :: (HasWriteRef w env, MonadReader env m, MonadIO m, Semigroup w) => w -> m ()
+tellWriteRef value = do
+  ref <- view writeRefL
+  liftIO $ modifySomeRef ref (<> value)
+
+listenWriteRef :: (HasWriteRef w env, MonadReader env m, MonadIO m) => m a -> m (a, w)
+listenWriteRef action = do
+  w1 <- view writeRefL >>= liftIO . readSomeRef
+  a <- action
+  w2 <- do
+    refEnv <- view writeRefL
+    v <- liftIO $ readSomeRef refEnv
+    _ <- liftIO $ writeSomeRef refEnv w1
+    return v
+  return (a, w2)
+
+passWriteRef :: (HasWriteRef w env, MonadReader env m, MonadIO m) => m (a, w -> w) -> m a
+passWriteRef action = do
+  (a, transF) <- action
+  ref <- view writeRefL
+  liftIO $ modifySomeRef ref transF
+  return a
+
+instance (Monoid w, HasWriteRef w env) => MonadWriter w (RIO env) where
+  tell = tellWriteRef
+  listen = listenWriteRef
+  pass = passWriteRef
