diff --git a/shell-conduit.cabal b/shell-conduit.cabal
--- a/shell-conduit.cabal
+++ b/shell-conduit.cabal
@@ -1,5 +1,5 @@
 name:                shell-conduit
-version:             2.0
+version:             3.0
 synopsis:            Write shell scripts with Conduit
 description:         Write shell scripts with Conduit. See "Data.Conduit.Shell" for documentation.
 license:             BSD3
diff --git a/src/Data/Conduit/Shell.hs b/src/Data/Conduit/Shell.hs
--- a/src/Data/Conduit/Shell.hs
+++ b/src/Data/Conduit/Shell.hs
@@ -90,6 +90,8 @@
   ,shell
   ,proc
   -- * I/O chunks
+  ,bytes
+  ,unbytes
   ,withRights
   ,redirect
   ,quiet
@@ -100,12 +102,10 @@
   ,module Data.Conduit.Shell.PATH
   ,module Data.Conduit.Shell.Types
   ,module Data.Conduit.Shell.Variadic
-  ,module Data.Conduit.Filesystem
   ,module Data.Conduit)
   where
 
 import Data.Conduit
-import Data.Conduit.Filesystem
 import qualified Data.Conduit.Shell.PATH
 import Data.Conduit.Shell.PATH
 import Data.Conduit.Shell.Process
diff --git a/src/Data/Conduit/Shell/Process.hs b/src/Data/Conduit/Shell/Process.hs
--- a/src/Data/Conduit/Shell/Process.hs
+++ b/src/Data/Conduit/Shell/Process.hs
@@ -10,6 +10,8 @@
   ,Data.Conduit.Shell.Process.shell
   ,Data.Conduit.Shell.Process.proc
    -- * I/O chunks
+  ,bytes
+  ,unbytes
   ,withRights
   ,redirect
   ,quiet
@@ -42,6 +44,14 @@
 import           System.IO
 import qualified System.Process
 
+-- | Extract the stdout values from the stream, discarding any errors.
+bytes :: Monad m => Conduit Chunk m ByteString
+bytes = CL.mapMaybe (either (const Nothing) Just)
+
+-- | Extract the stdout values from the stream, discarding any errors.
+unbytes :: Monad m => Conduit ByteString m Chunk
+unbytes = CL.map Right
+
 -- | Run a shell command.
 shell :: (MonadResource m) => String -> Conduit Chunk m Chunk
 shell = conduitProcess . System.Process.shell
@@ -161,10 +171,13 @@
                            proxyInterleaved
 startProxy _ = error "startProxy: unexpected arguments"
 
+-- | Concurrently yield eithers downstream.
+remainders :: MonadIO m
+           => Handle -> Handle -> ConduitM i (Either ByteString ByteString) m ()
 remainders cout cerr =
   do chan <- liftIO newChan
-     void (liftIO (forkIO (remainder "stdout" chan cout Right)))
-     void (liftIO (forkIO (remainder "stderr" chan cerr Left)))
+     void (liftIO (forkIO (remainder chan cout Right)))
+     void (liftIO (forkIO (remainder chan cerr Left)))
      fix (\loop done ->
             case done of
               Just (These () ()) -> return ()
@@ -190,17 +203,16 @@
          (Nothing :: Maybe (These () ()))
 
 -- | Proxy final results from the handle and yield them.
-remainder :: String
-          -> Chan (Either (Maybe ByteString) (Maybe ByteString))
+remainder :: Chan (Either (Maybe ByteString) (Maybe ByteString))
           -> Handle
           -> (Maybe ByteString -> Either (Maybe ByteString) (Maybe ByteString))
           -> IO ()
-remainder l chan h cons =
+remainder chan h cons =
   do bytes <- S.hGetSome h bufSize
      if S.null bytes
         then writeChan chan (cons Nothing)
         else do writeChan chan (cons (Just bytes))
-                remainder l chan h cons
+                remainder chan h cons
 
 -- | Proxy live results from the given handle and yield them.
 proxy :: MonadIO m
