diff --git a/Data/Conduit/Filesystem.hs b/Data/Conduit/Filesystem.hs
new file mode 100644
--- /dev/null
+++ b/Data/Conduit/Filesystem.hs
@@ -0,0 +1,84 @@
+{-# LANGUAGE CPP #-}
+
+-- |
+-- Copyright: 2011 John Millikin
+--            2011 Michael Snoyman
+-- License: MIT
+--
+-- Maintainer: michael@snoyman.com
+-- Portability: portable
+--
+-- Conduit-based API for manipulating the filesystem.
+--
+-- Parts of this code were taken from filesystem-enumerator and adapted for
+-- conduits.
+module Data.Conduit.Filesystem
+    ( traverse
+    , sourceFile
+    , sinkFile
+    ) where
+
+import           Prelude hiding (FilePath)
+
+import           Control.Monad.IO.Class (MonadIO, liftIO)
+import qualified Data.Conduit as C
+import qualified Data.Conduit.Binary as CB
+import           Filesystem
+import           Filesystem.Path.CurrentOS (FilePath, encodeString)
+import qualified Data.ByteString as S
+
+#ifdef CABAL_OS_WINDOWS
+#else
+import qualified System.Posix as Posix
+#endif
+
+-- | Starting at some root directory, traverse the filesystem and enumerate
+-- every file (or symlink to a file) found.
+--
+-- Note: the option of whether to follow symlinks is currently only checked
+-- on POSIX platforms, as the @Win32@ package does not support querying
+-- symlink status. On Windows, symlinks will always be followed.
+traverse :: C.ResourceIO m
+         => Bool -- ^ Follow directory symlinks (only used on POSIX platforms)
+         -> FilePath -- ^ Root directory
+         -> C.Source m FilePath
+traverse followSymlinks root = C.Source $ do
+    seq0 <- liftIO $ listDirectory root
+    C.prepareSource $ C.sourceState seq0 pull
+  where
+    pull [] = return ([], C.Closed)
+    pull (p:ps) = do
+        isFile' <- liftIO $ isFile p
+        if isFile'
+            then return (ps, C.Open p)
+            else do
+                follow' <- liftIO $ follow p
+                if follow'
+                    then do
+                        ps' <- liftIO $ listDirectory p
+                        pull $ ps ++ ps'
+                    else pull ps
+
+    follow :: FilePath -> IO Bool
+#ifdef CABAL_OS_WINDOWS
+    follow = isDirectory
+#else
+    follow p = do
+        let path = encodeString p
+        stat <- if followSymlinks
+            then Posix.getFileStatus path
+            else Posix.getSymbolicLinkStatus path
+        return (Posix.isDirectory stat)
+#endif
+
+-- | Same as 'CB.sourceFile', but uses system-filepath\'s @FilePath@ type.
+sourceFile :: C.ResourceIO m
+           => FilePath
+           -> C.Source m S.ByteString
+sourceFile = CB.sourceFile . encodeString
+
+-- | Same as 'CB.sinkFile', but uses system-filepath\'s @FilePath@ type.
+sinkFile :: C.ResourceIO m
+         => FilePath
+         -> C.Sink S.ByteString m ()
+sinkFile = CB.sinkFile . encodeString
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c)2011, Michael Snoyman
+
+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 Michael Snoyman 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/Setup.lhs b/Setup.lhs
new file mode 100644
--- /dev/null
+++ b/Setup.lhs
@@ -0,0 +1,7 @@
+#!/usr/bin/env runhaskell
+
+> module Main where
+> import Distribution.Simple
+
+> main :: IO ()
+> main = defaultMain
diff --git a/filesystem-conduit.cabal b/filesystem-conduit.cabal
new file mode 100644
--- /dev/null
+++ b/filesystem-conduit.cabal
@@ -0,0 +1,51 @@
+Name:                filesystem-conduit
+Version:             0.0.0
+Synopsis:            Use system-filepath data types with conduits.
+Description:         Provides ability to traverse a folder structure efficiently, as well as convenience wrappers for reading from and writing to files.
+License:             BSD3
+License-file:        LICENSE
+Author:              Michael Snoyman
+Maintainer:          michael@snoyman.com
+Category:            Data, Conduit
+Build-type:          Simple
+Cabal-version:       >=1.8
+Homepage:            http://github.com/snoyberg/conduit
+extra-source-files:  test/main.hs
+
+Library
+  Exposed-modules:     Data.Conduit.Filesystem
+  Build-depends:       base                     >= 4            && < 5
+                     , containers
+                     , transformers             >= 0.2.2        && < 0.3
+                     , system-fileio            >= 0.3.3        && < 0.4
+                     , system-filepath          >= 0.4.3        && < 0.5
+                     , bytestring               >= 0.9
+                     , text                     >= 0.11
+                     , conduit                  >= 0.0          && < 0.1
+  ghc-options:     -Wall
+
+  if os(windows)
+    cpp-options: -DCABAL_OS_WINDOWS
+    build-depends: Win32
+  else
+    build-depends: unix
+
+test-suite test
+    hs-source-dirs: test
+    main-is: main.hs
+    type: exitcode-stdio-1.0
+    cpp-options:   -DTEST
+    build-depends:   conduit
+                   , base
+                   , hspec
+                   , HUnit
+                   , QuickCheck
+                   , bytestring
+                   , blaze-builder
+                   , transformers
+                   , text
+    ghc-options:     -Wall
+
+source-repository head
+  type:     git
+  location: git://github.com/snoyberg/conduit.git
diff --git a/test/main.hs b/test/main.hs
new file mode 100644
--- /dev/null
+++ b/test/main.hs
@@ -0,0 +1,35 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE CPP #-}
+import Test.Hspec.Monadic
+{-
+import Test.Hspec.HUnit ()
+import Test.Hspec.QuickCheck (prop)
+import Test.HUnit
+
+import qualified Data.Conduit as C
+import qualified Data.Conduit.List as CL
+import qualified Data.Conduit.Lazy as CLazy
+import qualified Data.Conduit.Binary as CB
+import qualified Data.Conduit.Text as CT
+import Data.Conduit (runResourceT)
+import Control.Monad.ST (runST)
+import Data.Monoid
+import qualified Data.ByteString as S
+import qualified Data.IORef as I
+import Blaze.ByteString.Builder (fromByteString, toLazyByteString, insertLazyByteString)
+import qualified Data.ByteString.Lazy as L
+import Data.ByteString.Lazy.Char8 ()
+import Data.Maybe (catMaybes)
+import Control.Monad.Trans.Writer (Writer)
+import qualified Data.Text as T
+import qualified Data.Text.Lazy as TL
+import qualified Data.Text.Lazy.Encoding as TLE
+import Control.Monad.Trans.Resource (runExceptionT_, withIO, resourceForkIO)
+import Control.Concurrent (threadDelay, killThread)
+import Control.Monad.IO.Class (liftIO)
+import Control.Applicative (pure, (<$>), (<*>))
+-}
+
+main :: IO ()
+main = hspecX $ do
+    return ()
