diff --git a/Data/Conduit/Binary.hs b/Data/Conduit/Binary.hs
--- a/Data/Conduit/Binary.hs
+++ b/Data/Conduit/Binary.hs
@@ -140,7 +140,9 @@
 sinkHandle :: MonadIO m
            => IO.Handle
            -> Consumer S.ByteString m ()
-sinkHandle h = awaitForever $ liftIO . S.hPut h
+sinkHandle h = awaitForever $ \bs -> liftIO $ do
+    S.hPut h bs
+    IO.hFlush h
 
 -- | An alternative to 'sinkHandle'.
 -- Instead of taking a pre-opened 'IO.Handle', it takes an action that opens
diff --git a/Data/Conduit/Process.hs b/Data/Conduit/Process.hs
new file mode 100644
--- /dev/null
+++ b/Data/Conduit/Process.hs
@@ -0,0 +1,59 @@
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE RankNTypes #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+-- | A full tutorial for this module is available on FP School of Haskell:
+-- <https://www.fpcomplete.com/user/snoyberg/library-documentation/data-conduit-process>.
+--
+-- Note that this is a very thin layer around the @Data.Streaming.Process@ module. In particular, it:
+--
+-- * Provides orphan instances for conduit
+--
+-- * Provides some useful helper functions
+module Data.Conduit.Process
+    ( -- * Functions
+      sourceCmdWithConsumer
+    , sourceProcessWithConsumer
+      -- * Reexport
+    , module Data.Streaming.Process
+    ) where
+
+import Data.Streaming.Process
+import Data.Streaming.Process.Internal
+import System.Exit (ExitCode (..))
+import Control.Monad.IO.Class (MonadIO, liftIO)
+import System.IO (hClose)
+import Data.Conduit
+import Data.Conduit.Binary (sourceHandle, sinkHandle)
+import Data.ByteString (ByteString)
+
+instance (r ~ (), MonadIO m, i ~ ByteString) => InputSource (ConduitM i o m r) where
+    isStdStream = (\(Just h) -> return $ sinkHandle h, Just CreatePipe)
+instance (r ~ (), r' ~ (), MonadIO m, MonadIO n, i ~ ByteString) => InputSource (ConduitM i o m r, n r') where
+    isStdStream = (\(Just h) -> return (sinkHandle h, liftIO $ hClose h), Just CreatePipe)
+
+instance (r ~ (), MonadIO m, o ~ ByteString) => OutputSink (ConduitM i o m r) where
+    osStdStream = (\(Just h) -> return $ sourceHandle h, Just CreatePipe)
+instance (r ~ (), r' ~ (), MonadIO m, MonadIO n, o ~ ByteString) => OutputSink (ConduitM i o m r, n r') where
+    osStdStream = (\(Just h) -> return (sourceHandle h, liftIO $ hClose h), Just CreatePipe)
+
+-- | Given a @CreateProcess@, run the process, with its output being used as a
+-- @Source@ to feed the provided @Consumer@. Once the process has completed,
+-- return a tuple of the @ExitCode@ from the process and the output collected
+-- from the @Consumer@.
+--
+-- Since 1.1.2
+sourceProcessWithConsumer :: MonadIO m => CreateProcess -> Consumer ByteString m a -> m (ExitCode, a)
+sourceProcessWithConsumer cp consumer = do
+    (ClosedStream, (source, close), ClosedStream, cph) <- streamingProcess cp
+    res <- source $$ consumer
+    close
+    ec <- waitForStreamingProcess cph
+    return (ec, res)
+
+-- | Like @sourceProcessWithConsumer@ but providing the command to be run as
+-- a @String@.
+--
+-- Since 1.1.2
+sourceCmdWithConsumer :: MonadIO m => String -> Consumer ByteString m a -> m (ExitCode, a)
+sourceCmdWithConsumer cmd = sourceProcessWithConsumer (shell cmd)
diff --git a/conduit-extra.cabal b/conduit-extra.cabal
--- a/conduit-extra.cabal
+++ b/conduit-extra.cabal
@@ -1,5 +1,5 @@
 Name:                conduit-extra
-Version:             1.1.1
+Version:             1.1.2
 Synopsis:            Batteries included conduit: adapters for common libraries.
 Description:
     The conduit package itself maintains relative small dependencies. The purpose of this package is to collect commonly used utility functions wrapping other library dependencies, without depending on heavier-weight dependencies. The basic idea is that this package should only depend on haskell-platform packages and conduit.
@@ -24,6 +24,7 @@
                        Data.Conduit.Lazy
                        Data.Conduit.Network
                        Data.Conduit.Network.UDP
+                       Data.Conduit.Process
                        Data.Conduit.Text
                        Data.Conduit.Zlib
   if !os(windows)
@@ -46,8 +47,10 @@
                      , filepath
                      , network                  >= 2.3
                      , primitive                >= 0.5
+                     , process
                      , resourcet                >= 1.1
-                     , streaming-commons        >= 0.1.2
+                     , stm
+                     , streaming-commons        >= 0.1.4
 
   ghc-options:     -Wall
 
@@ -62,15 +65,20 @@
                    , base
                    , hspec >= 1.3
 
+                   , async
                    , attoparsec
                    , blaze-builder
                    , bytestring
                    , exceptions
+                   , process
                    , resourcet
+                   , stm
                    , text
                    , transformers
                    , transformers-base
     ghc-options:     -Wall
+    if os(windows)
+        cpp-options: -DWINDOWS
     other-modules:   Data.Conduit.AttoparsecSpec
                      Data.Conduit.BinarySpec
                      Data.Conduit.BlazeSpec
@@ -78,6 +86,7 @@
                      Data.Conduit.FilesystemSpec
                      Data.Conduit.LazySpec
                      Data.Conduit.NetworkSpec
+                     Data.Conduit.ProcessSpec
                      Data.Conduit.TextSpec
                      Data.Conduit.ZlibSpec
 
diff --git a/test/Data/Conduit/ProcessSpec.hs b/test/Data/Conduit/ProcessSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Data/Conduit/ProcessSpec.hs
@@ -0,0 +1,61 @@
+{-# LANGUAGE CPP #-}
+module Data.Conduit.ProcessSpec (spec, main) where
+
+import Test.Hspec
+import Test.Hspec.QuickCheck (prop)
+import Data.Conduit
+import qualified Data.Conduit.List as CL
+import Data.Conduit.Process
+import Control.Concurrent.Async (concurrently)
+import qualified Data.ByteString.Lazy as L
+import qualified Data.ByteString as S
+import System.Exit
+import Control.Concurrent (threadDelay)
+
+main :: IO ()
+main = hspec spec
+
+spec :: Spec
+spec = describe "Data.Conduit.Process" $ do
+#ifndef WINDOWS
+    prop "cat" $ \wss -> do
+        let lbs = L.fromChunks $ map S.pack wss
+        ((sink, closeStdin), source, Inherited, cph) <- streamingProcess (shell "cat")
+        ((), bss) <- concurrently
+            (do
+                mapM_ yield (L.toChunks lbs) $$ sink
+                closeStdin)
+            (source $$ CL.consume)
+        L.fromChunks bss `shouldBe` lbs
+        ec <- waitForStreamingProcess cph
+        ec `shouldBe` ExitSuccess
+
+    it "closed stream" $ do
+        (ClosedStream, source, Inherited, cph) <- streamingProcess (shell "cat")
+        bss <- source $$ CL.consume
+        bss `shouldBe` []
+
+        ec <- waitForStreamingProcess cph
+        ec `shouldBe` ExitSuccess
+
+    it "handles sub-process exit code" $ do
+        (sourceCmdWithConsumer "exit 0" CL.sinkNull)
+                `shouldReturn` (ExitSuccess, ())
+        (sourceCmdWithConsumer "exit 11" CL.sinkNull)
+                `shouldReturn` (ExitFailure 11, ())
+        (sourceCmdWithConsumer "exit 12" CL.sinkNull)
+                `shouldReturn` (ExitFailure 12, ())
+#endif
+    it "blocking vs non-blocking" $ do
+        (ClosedStream, ClosedStream, ClosedStream, cph) <- streamingProcess (shell "sleep 1")
+
+        mec1 <- getStreamingProcessExitCode cph
+        mec1 `shouldBe` Nothing
+
+        threadDelay 1500000
+
+        mec2 <- getStreamingProcessExitCode cph
+        mec2 `shouldBe` Just ExitSuccess
+
+        ec <- waitForStreamingProcess cph
+        ec `shouldBe` ExitSuccess
