diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,3 +1,7 @@
+## 0.2.6.0
+
+* Add `UnliftIO.Directory`
+
 ## 0.2.5.0
 
 * Add `UnliftIO.Environment`/`UnliftIO.Foreign`/`UnliftIO.Process`
diff --git a/src/UnliftIO/Directory.hs b/src/UnliftIO/Directory.hs
new file mode 100644
--- /dev/null
+++ b/src/UnliftIO/Directory.hs
@@ -0,0 +1,483 @@
+{-# LANGUAGE CPP #-}
+-- | Unlifted "System.Directory".
+--
+-- @since 0.2.6.0
+
+module UnliftIO.Directory (
+    -- * Actions on directories
+    createDirectory
+  , createDirectoryIfMissing
+  , removeDirectory
+  , removeDirectoryRecursive
+#if MIN_VERSION_directory(1,2,7)
+  , removePathForcibly
+#endif
+  , renameDirectory
+#if MIN_VERSION_directory(1,2,5)
+  , listDirectory
+#endif
+  , getDirectoryContents
+
+  -- ** Current working directory
+  , getCurrentDirectory
+  , setCurrentDirectory
+#if MIN_VERSION_directory(1,2,3)
+  , withCurrentDirectory
+#endif
+
+  -- * Pre-defined directories
+  , getHomeDirectory
+#if MIN_VERSION_directory(1,2,3)
+  , XdgDirectory(..)
+  , getXdgDirectory
+#endif
+  , getAppUserDataDirectory
+  , getUserDocumentsDirectory
+  , getTemporaryDirectory
+
+  -- * Actions on files
+  , removeFile
+  , renameFile
+#if MIN_VERSION_directory(1,2,7)
+  , renamePath
+#endif
+  , copyFile
+#if MIN_VERSION_directory(1,2,6)
+  , copyFileWithMetadata
+#endif
+  , canonicalizePath
+#if MIN_VERSION_directory(1,2,2)
+  , makeAbsolute
+#endif
+  , makeRelativeToCurrentDirectory
+  , findExecutable
+#if MIN_VERSION_directory(1,2,2)
+  , findExecutables
+#endif
+#if MIN_VERSION_directory(1,2,4)
+  , findExecutablesInDirectories
+#endif
+  , findFile
+#if MIN_VERSION_directory(1,2,1)
+  , findFiles
+#endif
+#if MIN_VERSION_directory(1,2,6)
+  , findFileWith
+#endif
+#if MIN_VERSION_directory(1,2,1)
+  , findFilesWith
+#endif
+#if MIN_VERSION_directory(1,2,4)
+  , exeExtension
+#endif
+#if MIN_VERSION_directory(1,2,7)
+  , getFileSize
+#endif
+
+  -- * Existence tests
+#if MIN_VERSION_directory(1,2,7)
+  , doesPathExist
+#endif
+  , doesFileExist
+  , doesDirectoryExist
+
+#if MIN_VERSION_directory(1,3,0)
+  -- * Symbolic links
+  , pathIsSymbolicLink
+#endif
+
+  -- * Permissions
+  , Permissions
+  , emptyPermissions
+  , readable
+  , writable
+  , executable
+  , searchable
+  , setOwnerReadable
+  , setOwnerWritable
+  , setOwnerExecutable
+  , setOwnerSearchable
+  , getPermissions
+  , setPermissions
+  , copyPermissions
+
+  -- * Timestamps
+#if MIN_VERSION_directory(1,2,3)
+  , getAccessTime
+#endif
+  , getModificationTime
+#if MIN_VERSION_directory(1,2,3)
+  , setAccessTime
+  , setModificationTime
+#endif
+  ) where
+
+import Control.Monad.IO.Unlift
+import Data.Time.Clock
+import qualified System.Directory as D
+import System.Directory
+  ( Permissions
+#if MIN_VERSION_directory(1,2,3)
+  , XdgDirectory(..)
+#endif
+  , emptyPermissions
+#if MIN_VERSION_directory(1,2,4)
+  , exeExtension
+#endif
+  , executable
+  , readable
+  , searchable
+  , setOwnerExecutable
+  , setOwnerReadable
+  , setOwnerSearchable
+  , setOwnerWritable
+  , writable
+  )
+
+-- | Lifted 'D.createDirectory'.
+--
+-- @since 0.2.6.0
+{-# INLINE createDirectory #-}
+createDirectory :: MonadIO m => FilePath -> m ()
+createDirectory = liftIO . D.createDirectory
+
+-- | Lifted 'D.createDirectoryIfMissing'.
+--
+-- @since 0.2.6.0
+{-# INLINE createDirectoryIfMissing #-}
+createDirectoryIfMissing :: MonadIO m => Bool -> FilePath -> m ()
+createDirectoryIfMissing create_parents path0 =
+  liftIO (D.createDirectoryIfMissing create_parents path0)
+
+-- | Lifted 'D.removeDirectory'.
+--
+-- @since 0.2.6.0
+{-# INLINE removeDirectory #-}
+removeDirectory :: MonadIO m => FilePath -> m ()
+removeDirectory = liftIO . D.removeDirectory
+
+-- | Lifted 'D.removeDirectoryRecursive'.
+--
+-- @since 0.2.6.0
+{-# INLINE removeDirectoryRecursive #-}
+removeDirectoryRecursive :: MonadIO m => FilePath -> m ()
+removeDirectoryRecursive = liftIO . D.removeDirectoryRecursive
+
+#if MIN_VERSION_directory(1,2,7)
+-- | Lifted 'D.removePathForcibly'.
+--
+-- @since 0.2.6.0
+{-# INLINE removePathForcibly #-}
+removePathForcibly :: MonadIO m => FilePath -> m ()
+removePathForcibly = liftIO . D.removePathForcibly
+#endif
+
+-- | Lifted 'D.renameDirectory'.
+--
+-- @since 0.2.6.0
+{-# INLINE renameDirectory #-}
+renameDirectory :: MonadIO m => FilePath -> FilePath -> m ()
+renameDirectory opath npath = liftIO (D.renameDirectory opath npath)
+
+#if MIN_VERSION_directory(1,2,5)
+-- | Lifted 'D.listDirectory'.
+--
+-- @since 0.2.6.0
+{-# INLINE listDirectory #-}
+listDirectory :: MonadIO m => FilePath -> m [FilePath]
+listDirectory = liftIO . D.listDirectory
+#endif
+
+-- | Lifted 'D.getDirectoryContents'.
+--
+-- @since 0.2.6.0
+{-# INLINE getDirectoryContents #-}
+getDirectoryContents :: MonadIO m => FilePath -> m [FilePath]
+getDirectoryContents = liftIO . D.getDirectoryContents
+
+-- | Lifted 'D.getCurrentDirectory'.
+--
+-- @since 0.2.6.0
+{-# INLINE getCurrentDirectory #-}
+getCurrentDirectory :: MonadIO m => m FilePath
+getCurrentDirectory = liftIO D.getCurrentDirectory
+
+-- | Lifted 'D.setCurrentDirectory'.
+--
+-- @since 0.2.6.0
+{-# INLINE setCurrentDirectory #-}
+setCurrentDirectory :: MonadIO m => FilePath -> m ()
+setCurrentDirectory = liftIO . D.setCurrentDirectory
+
+#if MIN_VERSION_directory(1,2,3)
+-- | Unlifted 'D.withCurrentDirectory'.
+--
+-- @since 0.2.6.0
+{-# INLINE withCurrentDirectory #-}
+withCurrentDirectory :: MonadUnliftIO m => FilePath -> m a -> m a
+withCurrentDirectory dir action =
+  withRunInIO (\u -> D.withCurrentDirectory dir (u action))
+#endif
+
+-- | Lifted 'D.getHomeDirectory'.
+--
+-- @since 0.2.6.0
+{-# INLINE getHomeDirectory #-}
+getHomeDirectory :: MonadIO m => m FilePath
+getHomeDirectory = liftIO D.getHomeDirectory
+
+#if MIN_VERSION_directory(1,2,3)
+-- | Lifted 'D.getXdgDirectory'.
+--
+-- @since 0.2.6.0
+{-# INLINE getXdgDirectory #-}
+getXdgDirectory :: MonadIO m => XdgDirectory -> FilePath -> m FilePath
+getXdgDirectory xdgDir suffix = liftIO (D.getXdgDirectory xdgDir suffix)
+#endif
+
+-- | Lifted 'D.getAppUserDataDirectory'.
+--
+-- @since 0.2.6.0
+{-# INLINE getAppUserDataDirectory #-}
+getAppUserDataDirectory :: MonadIO m => FilePath -> m FilePath
+getAppUserDataDirectory = liftIO . D.getAppUserDataDirectory
+
+-- | Lifted 'D.getUserDocumentsDirectory'.
+--
+-- @since 0.2.6.0
+{-# INLINE getUserDocumentsDirectory #-}
+getUserDocumentsDirectory :: MonadIO m => m FilePath
+getUserDocumentsDirectory = liftIO D.getUserDocumentsDirectory
+
+-- | Lifted 'D.getTemporaryDirectory'.
+--
+-- @since 0.2.6.0
+{-# INLINE getTemporaryDirectory #-}
+getTemporaryDirectory :: MonadIO m => m FilePath
+getTemporaryDirectory = liftIO D.getTemporaryDirectory
+
+-- | Lifted 'D.removeFile'.
+--
+-- @since 0.2.6.0
+{-# INLINE removeFile #-}
+removeFile :: MonadIO m => FilePath -> m ()
+removeFile = liftIO . D.removeFile
+
+-- | Lifted 'D.renameFile'.
+--
+-- @since 0.2.6.0
+{-# INLINE renameFile #-}
+renameFile :: MonadIO m => FilePath -> FilePath -> m ()
+renameFile opath npath = liftIO (D.renameFile opath npath)
+
+#if MIN_VERSION_directory(1,2,7)
+-- | Lifted 'D.renamePath'.
+--
+-- @since 0.2.6.0
+{-# INLINE renamePath #-}
+renamePath :: MonadIO m => FilePath -> FilePath -> m ()
+renamePath opath npath = liftIO (D.renamePath opath npath)
+#endif
+
+-- | Lifted 'D.copyFile'.
+--
+-- @since 0.2.6.0
+{-# INLINE copyFile #-}
+copyFile :: MonadIO m => FilePath -> FilePath -> m ()
+copyFile fromFPath toFPath = liftIO (D.copyFile fromFPath toFPath)
+
+#if MIN_VERSION_directory(1,2,6)
+-- | Lifted 'D.copyFileWithMetadata'.
+--
+-- @since 0.2.6.0
+{-# INLINE copyFileWithMetadata #-}
+copyFileWithMetadata :: MonadIO m => FilePath -> FilePath -> m ()
+copyFileWithMetadata src dst = liftIO (D.copyFileWithMetadata src dst)
+#endif
+
+-- | Lifted 'D.canonicalizePath'.
+--
+-- @since 0.2.6.0
+{-# INLINE canonicalizePath #-}
+canonicalizePath :: MonadIO m => FilePath -> m FilePath
+canonicalizePath = liftIO . D.canonicalizePath
+
+#if MIN_VERSION_directory(1,2,2)
+-- | Lifted 'D.makeAbsolute'.
+--
+-- @since 0.2.6.0
+{-# INLINE makeAbsolute #-}
+makeAbsolute :: MonadIO m => FilePath -> m FilePath
+makeAbsolute = liftIO . D.makeAbsolute
+#endif
+
+-- | Lifted 'D.makeRelativeToCurrentDirectory'.
+--
+-- @since 0.2.6.0
+{-# INLINE makeRelativeToCurrentDirectory #-}
+makeRelativeToCurrentDirectory :: MonadIO m => FilePath -> m FilePath
+makeRelativeToCurrentDirectory = liftIO . D.makeRelativeToCurrentDirectory
+
+-- | Lifted 'D.findExecutable'.
+--
+-- @since 0.2.6.0
+{-# INLINE findExecutable #-}
+findExecutable :: MonadIO m => String -> m (Maybe FilePath)
+findExecutable = liftIO . D.findExecutable
+
+#if MIN_VERSION_directory(1,2,2)
+-- | Lifted 'D.findExecutables'.
+--
+-- @since 0.2.6.0
+{-# INLINE findExecutables #-}
+findExecutables :: MonadIO m => String -> m [FilePath]
+findExecutables = liftIO . D.findExecutables
+#endif
+
+#if MIN_VERSION_directory(1,2,4)
+-- | Lifted 'D.findExecutablesInDirectories'.
+--
+-- @since 0.2.6.0
+{-# INLINE findExecutablesInDirectories #-}
+findExecutablesInDirectories ::
+     MonadIO m => [FilePath] -> String -> m [FilePath]
+findExecutablesInDirectories path binary =
+  liftIO (D.findExecutablesInDirectories path binary)
+#endif
+
+-- | Lifted 'D.findFile'.
+--
+-- @since 0.2.6.0
+{-# INLINE findFile #-}
+findFile :: MonadIO m => [FilePath] -> String -> m (Maybe FilePath)
+findFile ds name = liftIO (D.findFile ds name)
+
+#if MIN_VERSION_directory(1,2,1)
+-- | Lifted 'D.findFiles'.
+--
+-- @since 0.2.6.0
+{-# INLINE findFiles #-}
+findFiles :: MonadIO m => [FilePath] -> String -> m [FilePath]
+findFiles ds name = liftIO (D.findFiles ds name)
+#endif
+
+#if MIN_VERSION_directory(1,2,6)
+-- | Unlifted 'D.findFileWith'.
+--
+-- @since 0.2.6.0
+{-# INLINE findFileWith #-}
+findFileWith ::
+     MonadUnliftIO m
+  => (FilePath -> m Bool)
+  -> [FilePath]
+  -> String
+  -> m (Maybe FilePath)
+findFileWith f ds name = withRunInIO (\u -> D.findFileWith (u . f) ds name)
+#endif
+
+#if MIN_VERSION_directory(1,2,1)
+-- | Unlifted 'D.findFilesWith'.
+--
+-- @since 0.2.6.0
+{-# INLINE findFilesWith #-}
+findFilesWith ::
+     MonadUnliftIO m
+  => (FilePath -> m Bool)
+  -> [FilePath]
+  -> String
+  -> m [FilePath]
+findFilesWith f ds name = withRunInIO (\u -> D.findFilesWith (u . f) ds name)
+#endif
+
+#if MIN_VERSION_directory(1,2,7)
+-- | Lifted 'D.getFileSize'.
+--
+-- @since 0.2.6.0
+{-# INLINE getFileSize #-}
+getFileSize :: MonadIO m => FilePath -> m Integer
+getFileSize = liftIO . D.getFileSize
+#endif
+
+#if MIN_VERSION_directory(1,2,7)
+-- | Lifted 'D.doesPathExist'.
+--
+-- @since 0.2.6.0
+{-# INLINE doesPathExist #-}
+doesPathExist :: MonadIO m => FilePath -> m Bool
+doesPathExist = liftIO . D.doesPathExist
+#endif
+
+-- | Lifted 'D.doesFileExist'.
+--
+-- @since 0.2.6.0
+{-# INLINE doesFileExist #-}
+doesFileExist :: MonadIO m => FilePath -> m Bool
+doesFileExist = liftIO . D.doesFileExist
+
+-- | Lifted 'D.doesDirectoryExist'.
+--
+-- @since 0.2.6.0
+{-# INLINE doesDirectoryExist #-}
+doesDirectoryExist :: MonadIO m => FilePath -> m Bool
+doesDirectoryExist = liftIO . D.doesDirectoryExist
+
+#if MIN_VERSION_directory(1,3,0)
+-- | Lifted 'D.pathIsSymbolicLink'.
+--
+-- @since 0.2.6.0
+{-# INLINE pathIsSymbolicLink #-}
+pathIsSymbolicLink :: MonadIO m => FilePath -> m Bool
+pathIsSymbolicLink = liftIO . D.pathIsSymbolicLink
+#endif
+
+-- | Lifted 'D.getPermissions'.
+--
+-- @since 0.2.6.0
+{-# INLINE getPermissions #-}
+getPermissions :: MonadIO m => FilePath -> m Permissions
+getPermissions = liftIO . D.getPermissions
+
+-- | Lifted 'D.setPermissions'.
+--
+-- @since 0.2.6.0
+{-# INLINE setPermissions #-}
+setPermissions :: MonadIO m => FilePath -> Permissions -> m ()
+setPermissions name p = liftIO (D.setPermissions name p)
+
+-- | Lifted 'D.copyPermissions'.
+--
+-- @since 0.2.6.0
+{-# INLINE copyPermissions #-}
+copyPermissions :: MonadIO m => FilePath -> FilePath -> m ()
+copyPermissions source dest = liftIO (D.copyPermissions source dest)
+
+#if MIN_VERSION_directory(1,2,3)
+-- | Lifted 'D.getAccessTime'.
+--
+-- @since 0.2.6.0
+{-# INLINE getAccessTime #-}
+getAccessTime :: MonadIO m => FilePath -> m UTCTime
+getAccessTime = liftIO . D.getAccessTime
+#endif
+
+-- | Lifted 'D.getModificationTime'.
+--
+-- @since 0.2.6.0
+{-# INLINE getModificationTime #-}
+getModificationTime :: MonadIO m => FilePath -> m UTCTime
+getModificationTime = liftIO . D.getModificationTime
+
+#if MIN_VERSION_directory(1,2,3)
+-- | Lifted 'D.setAccessTime'.
+--
+-- @since 0.2.6.0
+{-# INLINE setAccessTime #-}
+setAccessTime :: MonadIO m => FilePath -> UTCTime -> m ()
+setAccessTime path atime = liftIO (D.setAccessTime path atime)
+
+-- | Lifted 'D.setModificationTime'.
+--
+-- @since 0.2.6.0
+setModificationTime :: MonadIO m => FilePath -> UTCTime -> m ()
+setModificationTime path mtime = liftIO (D.setModificationTime path mtime)
+#endif
diff --git a/unliftio.cabal b/unliftio.cabal
--- a/unliftio.cabal
+++ b/unliftio.cabal
@@ -2,10 +2,10 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: 7eb86a47bfc4a1463d455dd356bf07f248d867021c31a7f0ab4382936315e0ac
+-- hash: e2e3224b8cb626ef2d88a40f99a5597a587c19a91b00dc69ec4cd6115c65ec1f
 
 name:           unliftio
-version:        0.2.5.0
+version:        0.2.6.0
 synopsis:       The MonadUnliftIO typeclass for unlifting monads to IO (batteries included)
 description:    Please see the documentation and README at <https://www.stackage.org/package/unliftio>
 category:       Control
@@ -33,6 +33,7 @@
     , filepath
     , process >=1.2.0.0
     , stm >=2.4.3
+    , time
     , transformers
     , unliftio-core >=0.1.1.0
   if !os(Windows)
@@ -53,6 +54,7 @@
       UnliftIO.Async
       UnliftIO.Chan
       UnliftIO.Concurrent
+      UnliftIO.Directory
       UnliftIO.Environment
       UnliftIO.Exception
       UnliftIO.Foreign
@@ -81,6 +83,7 @@
     , hspec
     , process >=1.2.0.0
     , stm >=2.4.3
+    , time
     , transformers
     , unliftio
     , unliftio-core >=0.1.1.0
