diff --git a/lib/Pipes/Cliff.hs b/lib/Pipes/Cliff.hs
--- a/lib/Pipes/Cliff.hs
+++ b/lib/Pipes/Cliff.hs
@@ -66,13 +66,17 @@
   , pipeOutputError
   , pipeInputOutputError
 
-  -- * Conveniences
+  -- * Background operations
 
-  -- | These make it a bit easier to write both simple and
-  -- complicated pipelines.
+  -- | Often it is necessary to run threads in the background; in
+  -- addition, all subprocesses run in the background.  These
+  -- functions allow you to launch threads in the background and to
+  -- wait on background threads and subprocesses.
 
   , conveyor
+  , background
   , waitForProcess
+  , waitForThread
 
   -- * Re-exports
   -- $reexports
@@ -85,7 +89,7 @@
 import System.IO
 import Pipes
 import Pipes.Concurrent
-import Control.Concurrent.Async (Async, async, cancel)
+import Control.Concurrent.Async (Async, async, cancel, wait)
 import Data.ByteString (ByteString)
 import qualified Data.ByteString as BS
 import qualified System.Process as Process
@@ -282,7 +286,7 @@
 -- while receiving data, the error is caught and production ceases.
 -- The exception is not re-thrown.
 produceFromHandle
-  :: (MonadIO m, Pipes.Safe.MonadCatch m)
+  :: (Pipes.Safe.MonadCatch m, MonadIO m)
   => Bool
   -- ^ Be quiet?
   -> Handle
@@ -303,7 +307,7 @@
 -- sending data, the error is caught and consumption ceases.  The
 -- exception is not re-thrown.
 consumeToHandle
-  :: (MonadIO m, Pipes.Safe.MonadCatch m)
+  :: (Pipes.Safe.MonadCatch m, MonadIO m)
   => Bool
   -- ^ Be quiet?
   -> Handle
@@ -325,7 +329,7 @@
 
 -- | Acquires a resource and registers a finalizer.
 initialize
-  :: (Pipes.Safe.MonadSafe m, MonadIO m)
+  :: Pipes.Safe.MonadSafe m
   => IO a
   -> (a -> IO ())
   -> m a
@@ -336,22 +340,23 @@
 
 -- | Creates a mailbox; seals it when done.
 newMailbox
-  :: (Pipes.Safe.MonadSafe m, MonadIO m)
+  :: Pipes.Safe.MonadSafe m
   => m (Output a, Input a, STM ())
 newMailbox =
   initialize (spawn' messageBuffer)
   (\(_, _, seal) -> atomically seal)
 
 -- | Runs a thread in the background.  Initializes a finalizer that
--- will cancel the thread.
-background :: (Pipes.Safe.MonadSafe m, MonadIO m) => IO a -> m (Async a)
+-- will cancel the thread if it is still running when the
+-- 'Pipes.Safe.MonadSafe' computation completes.
+background :: Pipes.Safe.MonadSafe m => IO a -> m (Async a)
 background action = initialize (async action) cancel
 
 -- | Creates a thread that will run in the background and pump
 -- messages from the given mailbox to the process via its handle.
 -- Closes the Handle when done.
 processPump
-  :: (MonadIO m, Pipes.Safe.MonadSafe m)
+  :: Pipes.Safe.MonadSafe m
   => Bool
   -- ^ Quiet?
   -> Handle
@@ -372,7 +377,7 @@
 -- messages from the process and place them into the given mailbox.
 -- Closes the handle when done.
 processPull
-  :: (Pipes.Safe.MonadSafe m, MonadIO m)
+  :: Pipes.Safe.MonadSafe m
   => Bool
   -- ^ Quiet?
   -> Handle
@@ -394,7 +399,7 @@
 -- | Creates a mailbox that sends messages to the given process, and
 -- sets up and runs threads to pump messages to the process.
 makeToProcess
-  :: (Pipes.Safe.MonadSafe mp, MonadIO mp, Pipes.Safe.MonadSafe m, MonadIO m)
+  :: (Pipes.Safe.MonadSafe mp, Pipes.Safe.MonadSafe m)
   => Bool
   -- ^ Quiet?
   -> Handle
@@ -408,7 +413,7 @@
 -- and sets up and runs threads to receive the messages and deliver
 -- them to the mailbox.
 makeFromProcess
-  :: (Pipes.Safe.MonadSafe m, MonadIO m, Pipes.Safe.MonadSafe mp, MonadIO mp)
+  :: (Pipes.Safe.MonadSafe m, Pipes.Safe.MonadSafe mp)
   => Bool
   -- ^ Quiet?
   -> Handle
@@ -451,7 +456,7 @@
 -- | Creates a subprocess.  Registers destroyers for each handle
 -- created, as well as for the ProcessHandle.
 createProcess
-  :: (MonadIO m, Pipes.Safe.MonadSafe m)
+  :: Pipes.Safe.MonadSafe m
   => Bool
   -- ^ Quiet?
   -> Process.CreateProcess
@@ -479,6 +484,13 @@
 waitForProcess :: MonadIO m => ProcessHandle -> m ExitCode
 waitForProcess h = liftIO $ Process.waitForProcess h
 
+-- | A version of 'Control.Concurrent.Async.wait' with an overloaded
+-- 'MonadIO' return type.  Allows you to wait for the return value of
+-- threads launched with 'background'.  If the thread throws an
+-- exception, 'waitForThread' will throw that same exception.
+waitForThread :: MonadIO m => Async a -> m a
+waitForThread = liftIO . wait
+
 {- $process
 
 Each of these functions creates a process.  The process begins
@@ -517,7 +529,7 @@
 
 -- | Do not create any 'Proxy' to or from the process.
 pipeNone
-  :: (MonadIO m, Pipes.Safe.MonadSafe m)
+  :: Pipes.Safe.MonadSafe m
   => NonPipe
   -- ^ Standard input
   -> NonPipe
@@ -535,7 +547,7 @@
 
 -- | Create a 'Consumer' for standard input.
 pipeInput
-  :: (MonadIO mi, Pipes.Safe.MonadSafe mi, MonadIO m, Pipes.Safe.MonadSafe m)
+  :: (Pipes.Safe.MonadSafe mi, Pipes.Safe.MonadSafe m)
   => NonPipe
   -- ^ Standard output
   -> NonPipe
@@ -553,7 +565,7 @@
 
 -- | Create a 'Producer' for standard output.
 pipeOutput
-  :: (MonadIO mi, Pipes.Safe.MonadSafe mi, MonadIO m, Pipes.Safe.MonadSafe m)
+  :: (Pipes.Safe.MonadSafe mi, Pipes.Safe.MonadSafe m)
   => NonPipe
   -- ^ Standard input
   -> NonPipe
@@ -570,7 +582,7 @@
 
 -- | Create a 'Producer' for standard error.
 pipeError
-  :: (MonadIO mi, Pipes.Safe.MonadSafe mi, MonadIO m, Pipes.Safe.MonadSafe m)
+  :: (Pipes.Safe.MonadSafe mi, Pipes.Safe.MonadSafe m)
   => NonPipe
   -- ^ Standard input
   -> NonPipe
@@ -588,8 +600,8 @@
 -- | Create a 'Consumer' for standard input and a 'Producer' for
 -- standard output.
 pipeInputOutput
-  :: ( MonadIO mi, Pipes.Safe.MonadSafe mi, MonadIO mo, Pipes.Safe.MonadSafe mo
-     , MonadIO m, Pipes.Safe.MonadSafe m)
+  :: ( Pipes.Safe.MonadSafe mi, Pipes.Safe.MonadSafe mo
+     , Pipes.Safe.MonadSafe m)
   => NonPipe
   -- ^ Standard error
   -> CreateProcess
@@ -610,8 +622,8 @@
 -- | Create a 'Consumer' for standard input and a 'Producer' for
 -- standard error.
 pipeInputError
-  :: ( MonadIO mi, Pipes.Safe.MonadSafe mi, MonadIO mo, Pipes.Safe.MonadSafe mo
-     , MonadIO m, Pipes.Safe.MonadSafe m)
+  :: ( Pipes.Safe.MonadSafe mi, Pipes.Safe.MonadSafe mo
+     , Pipes.Safe.MonadSafe m)
   => NonPipe
   -- ^ Standard output
   -> CreateProcess
@@ -632,8 +644,8 @@
 -- | Create a 'Producer' for standard output and a 'Producer' for
 -- standard error.
 pipeOutputError
-  :: ( MonadIO mi, Pipes.Safe.MonadSafe mi, MonadIO mo
-     , Pipes.Safe.MonadSafe mo, MonadIO m
+  :: ( Pipes.Safe.MonadSafe mi
+     , Pipes.Safe.MonadSafe mo
      , Pipes.Safe.MonadSafe m)
   => NonPipe
   -- ^ Standard input
@@ -655,8 +667,8 @@
 -- | Create a 'Consumer' for standard input, a 'Producer' for standard
 -- output, and a 'Producer' for standard error.
 pipeInputOutputError
-  :: ( MonadIO mi, Pipes.Safe.MonadSafe mi, MonadIO mo, Pipes.Safe.MonadSafe mo,
-       MonadIO me, Pipes.Safe.MonadSafe me, MonadIO m, Pipes.Safe.MonadSafe m)
+  :: ( Pipes.Safe.MonadSafe mi, Pipes.Safe.MonadSafe mo,
+       Pipes.Safe.MonadSafe me, Pipes.Safe.MonadSafe m)
   => CreateProcess
   -> m ( Consumer ByteString mi ()
        , Producer ByteString mo ()
diff --git a/lib/Pipes/Cliff/Examples.hs b/lib/Pipes/Cliff/Examples.hs
--- a/lib/Pipes/Cliff/Examples.hs
+++ b/lib/Pipes/Cliff/Examples.hs
@@ -58,6 +58,39 @@
     mkNumStr = flip BS8.snoc '\n' . BS8.pack . show
 
 
+-- | Produces an infinite stream of numbers, sends it to @tr@ for some
+-- mangling, and then to @sh@, which will copy each line both to
+-- standard output and to standard error.  From @sh@, standard output
+-- is then sent off to @less@, and standard error is sent to a
+-- separate thread which will collect the results and return them.
+--
+-- This example shows you how to write a pipeline that deals with
+-- both standard output and standard error.
+--
+-- It's also interesting to note here that because of the buffering
+-- that happens in various places throughout the pipeline, and because
+-- less itself also buffers its input, the output you will see from
+-- the @sh@ process's standard error will be much longer than the
+-- output the user actually viewed in @less@.
+standardOutputAndError :: IO BS8.ByteString
+standardOutputAndError = runSafeT $ do
+  (toTr, fromTr, _) <- pipeInputOutput Inherit
+    (procSpec "tr" ["[0-9]", "[a-z]"])
+  (toSh, fromShOut, fromShErr, _) <- pipeInputOutputError
+    (procSpec "sh" ["-c", script])
+  (toLess, _) <- pipeInput Inherit Inherit
+    (procSpec "less" [])
+  conveyor $ produceNumbers >-> toTr
+  conveyor $ fromTr >-> toSh
+  conveyor $ fromShOut >-> toLess
+  thread <- background
+    . runSafeT
+    . P.fold BS8.append BS8.empty id
+    $ fromShErr
+  waitForThread thread
+  where
+    script = "while read line; do echo $line; echo $line 1>&2; done"
+
 -- | Like 'alphaNumbers' but just sends a limited number
 -- of numbers to @cat@.  A useful test to make sure that pipelines
 -- shut down automatically.
@@ -94,3 +127,4 @@
     (procSpec "tr" ["[0-9]", "[a-z]"])
   conveyor $ produceNumbers >-> P.take 300 >-> toTr
   P.fold BS8.append BS8.empty id fromTr
+
diff --git a/pipes-cliff.cabal b/pipes-cliff.cabal
--- a/pipes-cliff.cabal
+++ b/pipes-cliff.cabal
@@ -3,11 +3,11 @@
 -- http://www.github.com/massysett/cartel
 --
 -- Script name used to generate: genCabal.hs
--- Generated on: 2015-03-20 09:28:58.76288 EDT
+-- Generated on: 2015-03-22 13:30:11.54764 EDT
 -- Cartel library version: 0.14.2.0
 
 name: pipes-cliff
-version: 0.2.0.0
+version: 0.4.0.0
 cabal-version: >= 1.16
 license: BSD3
 license-file: LICENSE
@@ -68,105 +68,131 @@
   main-is: numsToLess.hs
   if flag(tests)
     buildable: True
+    default-language: Haskell2010
+    ghc-options:
+      -Wall
+    hs-source-dirs:
+      lib
+      tests
+    other-modules:
+      Pipes.Cliff
+      Pipes.Cliff.Examples
+    build-depends:
+        base >= 4.6.0.0 && < 4.8
+      , pipes >= 4.1 && < 4.2
+      , pipes-safe >= 2.2 && < 2.3
+      , bytestring >= 0.10.4 && < 0.11
+      , process >= 1.2.0.0 && < 1.3
+      , async >= 2.0 && < 2.1
+      , pipes-concurrency >= 2.0 && < 2.1
+    ghc-options:
+      -threaded
   else
     buildable: False
-  default-language: Haskell2010
-  ghc-options:
-    -Wall
-  hs-source-dirs:
-    lib
-    tests
-  other-modules:
-    Pipes.Cliff
-    Pipes.Cliff.Examples
-  build-depends:
-      base >= 4.6.0.0 && < 4.8
-    , pipes >= 4.1 && < 4.2
-    , pipes-safe >= 2.2 && < 2.3
-    , bytestring >= 0.10.4 && < 0.11
-    , process >= 1.2.0.0 && < 1.3
-    , async >= 2.0 && < 2.1
-    , pipes-concurrency >= 2.0 && < 2.1
-  ghc-options:
-    -threaded
 
 Executable alphaNumbers
   main-is: alphaNumbers.hs
   if flag(tests)
     buildable: True
+    default-language: Haskell2010
+    ghc-options:
+      -Wall
+    hs-source-dirs:
+      lib
+      tests
+    other-modules:
+      Pipes.Cliff
+      Pipes.Cliff.Examples
+    build-depends:
+        base >= 4.6.0.0 && < 4.8
+      , pipes >= 4.1 && < 4.2
+      , pipes-safe >= 2.2 && < 2.3
+      , bytestring >= 0.10.4 && < 0.11
+      , process >= 1.2.0.0 && < 1.3
+      , async >= 2.0 && < 2.1
+      , pipes-concurrency >= 2.0 && < 2.1
+    ghc-options:
+      -threaded
   else
     buildable: False
-  default-language: Haskell2010
-  ghc-options:
-    -Wall
-  hs-source-dirs:
-    lib
-    tests
-  other-modules:
-    Pipes.Cliff
-    Pipes.Cliff.Examples
-  build-depends:
-      base >= 4.6.0.0 && < 4.8
-    , pipes >= 4.1 && < 4.2
-    , pipes-safe >= 2.2 && < 2.3
-    , bytestring >= 0.10.4 && < 0.11
-    , process >= 1.2.0.0 && < 1.3
-    , async >= 2.0 && < 2.1
-    , pipes-concurrency >= 2.0 && < 2.1
-  ghc-options:
-    -threaded
 
 Executable limitedAlphaNumbers
   main-is: limitedAlphaNumbers.hs
   if flag(tests)
     buildable: True
+    default-language: Haskell2010
+    ghc-options:
+      -Wall
+    hs-source-dirs:
+      lib
+      tests
+    other-modules:
+      Pipes.Cliff
+      Pipes.Cliff.Examples
+    build-depends:
+        base >= 4.6.0.0 && < 4.8
+      , pipes >= 4.1 && < 4.2
+      , pipes-safe >= 2.2 && < 2.3
+      , bytestring >= 0.10.4 && < 0.11
+      , process >= 1.2.0.0 && < 1.3
+      , async >= 2.0 && < 2.1
+      , pipes-concurrency >= 2.0 && < 2.1
+    ghc-options:
+      -threaded
   else
     buildable: False
-  default-language: Haskell2010
-  ghc-options:
-    -Wall
-  hs-source-dirs:
-    lib
-    tests
-  other-modules:
-    Pipes.Cliff
-    Pipes.Cliff.Examples
-  build-depends:
-      base >= 4.6.0.0 && < 4.8
-    , pipes >= 4.1 && < 4.2
-    , pipes-safe >= 2.2 && < 2.3
-    , bytestring >= 0.10.4 && < 0.11
-    , process >= 1.2.0.0 && < 1.3
-    , async >= 2.0 && < 2.1
-    , pipes-concurrency >= 2.0 && < 2.1
-  ghc-options:
-    -threaded
 
 Executable alphaNumbersByteString
   main-is: alphaNumbersByteString.hs
   if flag(tests)
     buildable: True
+    default-language: Haskell2010
+    ghc-options:
+      -Wall
+    hs-source-dirs:
+      lib
+      tests
+    other-modules:
+      Pipes.Cliff
+      Pipes.Cliff.Examples
+    build-depends:
+        base >= 4.6.0.0 && < 4.8
+      , pipes >= 4.1 && < 4.2
+      , pipes-safe >= 2.2 && < 2.3
+      , bytestring >= 0.10.4 && < 0.11
+      , process >= 1.2.0.0 && < 1.3
+      , async >= 2.0 && < 2.1
+      , pipes-concurrency >= 2.0 && < 2.1
+    ghc-options:
+      -threaded
   else
     buildable: False
-  default-language: Haskell2010
-  ghc-options:
-    -Wall
-  hs-source-dirs:
-    lib
-    tests
-  other-modules:
-    Pipes.Cliff
-    Pipes.Cliff.Examples
-  build-depends:
-      base >= 4.6.0.0 && < 4.8
-    , pipes >= 4.1 && < 4.2
-    , pipes-safe >= 2.2 && < 2.3
-    , bytestring >= 0.10.4 && < 0.11
-    , process >= 1.2.0.0 && < 1.3
-    , async >= 2.0 && < 2.1
-    , pipes-concurrency >= 2.0 && < 2.1
-  ghc-options:
-    -threaded
+
+Executable standardOutputAndError
+  main-is: standardOutputAndError.hs
+  if flag(tests)
+    buildable: True
+    default-language: Haskell2010
+    ghc-options:
+      -Wall
+    hs-source-dirs:
+      lib
+      tests
+    other-modules:
+      Pipes.Cliff
+      Pipes.Cliff.Examples
+    build-depends:
+        base >= 4.6.0.0 && < 4.8
+      , pipes >= 4.1 && < 4.2
+      , pipes-safe >= 2.2 && < 2.3
+      , bytestring >= 0.10.4 && < 0.11
+      , process >= 1.2.0.0 && < 1.3
+      , async >= 2.0 && < 2.1
+      , pipes-concurrency >= 2.0 && < 2.1
+    ghc-options:
+      -threaded
+  else
+    buildable: False
 
 Flag tests
   description: Build test executables
diff --git a/tests/standardOutputAndError.hs b/tests/standardOutputAndError.hs
new file mode 100644
--- /dev/null
+++ b/tests/standardOutputAndError.hs
@@ -0,0 +1,7 @@
+module Main where
+
+import Pipes.Cliff.Examples
+import qualified Data.ByteString.Char8 as BS8
+
+main :: IO ()
+main = standardOutputAndError >>= BS8.putStr
