diff --git a/COPYING b/COPYING
new file mode 100644
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,13 @@
+Copyright © 2011, Stephen Paul Weber <singpolyma.net>
+
+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/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/UnexceptionalIO.hs b/UnexceptionalIO.hs
new file mode 100644
--- /dev/null
+++ b/UnexceptionalIO.hs
@@ -0,0 +1,65 @@
+-- | When you've caught all the exceptions that can be handled safely,
+--   this is what you're left with.
+--
+-- > runEitherIO . fromIO ≡ id
+module UnexceptionalIO (
+	UnexceptionalIO,
+	fromIO,
+	runUnexceptionalIO,
+	runEitherIO,
+	-- * Unsafe entry points
+	fromIO',
+	unsafeFromIO
+) where
+
+import Control.Applicative (Applicative(..))
+import Control.Monad (liftM, ap, (<=<))
+import Control.Monad.Fix (MonadFix(..))
+import Control.Error (syncIO, mapEitherT, EitherT(..), fmapLT)
+import Control.Exception (SomeException, Exception, fromException, throwIO)
+import Control.Monad.IO.Class (liftIO, MonadIO)
+
+-- | IO without any non-error, synchronous exceptions
+newtype UnexceptionalIO a = UnexceptionalIO (IO a)
+
+instance Functor UnexceptionalIO where
+	fmap = liftM
+
+instance Applicative UnexceptionalIO where
+	pure = return
+	(<*>) = ap
+
+instance Monad UnexceptionalIO where
+	return = UnexceptionalIO . return
+	(UnexceptionalIO x) >>= f = UnexceptionalIO (x >>= runUnexceptionalIO . f)
+
+	fail s = error $ "UnexceptionalIO cannot fail (" ++ s ++ ")"
+
+instance MonadFix UnexceptionalIO where
+	mfix f = UnexceptionalIO (mfix $ runUnexceptionalIO . f)
+
+-- | Catch any non-error, synchronous exceptions in an 'IO' action
+fromIO :: IO a -> EitherT SomeException UnexceptionalIO a
+fromIO = mapEitherT unsafeFromIO . syncIO
+
+-- | Re-embed 'UnexceptionalIO' into 'IO'
+runUnexceptionalIO :: (MonadIO m) => UnexceptionalIO a -> m a
+runUnexceptionalIO (UnexceptionalIO io) = liftIO io
+
+-- | Re-embed 'UnexceptionalIO' and possible exception back into 'IO'
+runEitherIO :: (MonadIO m, Exception e) => EitherT e UnexceptionalIO a -> m a
+runEitherIO = either (liftIO . throwIO) return <=< runUnexceptionalIO . runEitherT
+
+-- | You promise that 'e' covers all non-error, synchronous exceptions
+--   thrown by this 'IO' action
+--
+-- This function is partial if you lie
+fromIO' :: (Exception e) => IO a -> EitherT e UnexceptionalIO a
+fromIO' = fmapLT (maybePartial . fromException) . fromIO
+	where
+	maybePartial (Just x) = x
+	maybePartial Nothing = error "UnexceptionalIO.fromIO' exception of unspecified type"
+
+-- | You promise there are no exceptions thrown by this 'IO' action
+unsafeFromIO :: IO a -> UnexceptionalIO a
+unsafeFromIO = UnexceptionalIO
diff --git a/unexceptionalio.cabal b/unexceptionalio.cabal
new file mode 100644
--- /dev/null
+++ b/unexceptionalio.cabal
@@ -0,0 +1,30 @@
+name:            unexceptionalio
+version:         0.1.0
+cabal-version:   >=1.8
+license:         OtherLicense
+license-file:    COPYING
+copyright:       © 2013 Stephen Paul Weber
+category:        Control
+author:          Stephen Paul Weber <singpolyma@singpolyma.net>
+maintainer:      Stephen Paul Weber <singpolyma@singpolyma.net>
+stability:       experimental
+build-type:      Simple
+homepage:        https://github.com/singpolyma/unexceptionalio
+bug-reports:     http://github.com/singpolyma/unexceptionalio/issues
+synopsis:        IO without any non-error, synchronous exceptions
+description:
+        When you've caught all the exceptions that can be handled safely,
+        this is what you're left with.
+
+library
+        exposed-modules:
+                UnexceptionalIO
+
+        build-depends:
+                base == 4.*,
+                errors >= 1.4.2,
+                transformers
+
+source-repository head
+        type:     git
+        location: git://github.com/singpolyma/unexceptionalio.git
