diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,9 @@
 # Revision history for reflex-process
 
+## 0.2.0.0
+
+* Breaking change: Generalise input and output parameters of createRedirectedProcess. Existing programs should replace `Process t` with `Process t ByteString ByteString` and `ProcessConfig t` with `ProcessConfig t ByteString`.
+
 ## 0.1.0.1
 
 * Loosen reflex-vty version bounds
diff --git a/reflex-process.cabal b/reflex-process.cabal
--- a/reflex-process.cabal
+++ b/reflex-process.cabal
@@ -1,6 +1,6 @@
 cabal-version: >=1.10
 name: reflex-process
-version: 0.1.0.1
+version: 0.2.0.0
 synopsis: reflex-frp interface for running shell commands
 description: Run shell commands from within reflex applications and interact with them over a functional-reactive interface
 bug-reports: https://github.com/reflex-frp/reflex-process/issues
diff --git a/src/Reflex/Process.hs b/src/Reflex/Process.hs
--- a/src/Reflex/Process.hs
+++ b/src/Reflex/Process.hs
@@ -29,53 +29,56 @@
 import Reflex
 
 -- | The inputs to a process
-data ProcessConfig t = ProcessConfig
-  { _processConfig_stdin :: Event t ByteString
+data ProcessConfig t i = ProcessConfig
+  { _processConfig_stdin :: Event t i
   -- ^ "stdin" input to be fed to the process
   , _processConfig_signal :: Event t P.Signal
   -- ^ Signals to send to the process
   }
 
-instance Reflex t => Default (ProcessConfig t) where
+instance Reflex t => Default (ProcessConfig t i) where
   def = ProcessConfig never never
 
 -- | The output of a process
-data Process t = Process
+data Process t o e = Process
   { _process_handle :: P.ProcessHandle
-  , _process_stdout :: Event t ByteString
+  , _process_stdout :: Event t o
   -- ^ Fires whenever there's some new stdout output. Depending on the buffering strategy of the implementation, this could be anything from whole lines to individual characters.
-  , _process_stderr :: Event t ByteString
+  , _process_stderr :: Event t e
   -- ^ Fires whenever there's some new stderr output. See note on '_process_stdout'.
   , _process_exit :: Event t ExitCode
   , _process_signal :: Event t P.Signal
   -- ^ Fires when a signal has actually been sent to the process (via '_processConfig_signal').
   }
 
--- | Runs a process and uses the given input and output handler functions
--- to interact with the process. Used to implement 'createProcess'.
+-- | Runs a process and uses the given input and output handler functions to
+-- interact with the process via the standard streams. Used to implement
+-- 'createProcess'.
 --
 -- NB: The 'std_in', 'std_out', and 'std_err' parameters of the
 -- provided 'CreateProcess' are replaced with new pipes and all output is redirected
 -- to those pipes.
 createRedirectedProcess
   :: (MonadIO m, TriggerEvent t m, PerformEvent t m, MonadIO (Performable m))
-  => (Handle -> IO (ByteString -> IO ()))
-  -- ^ Builder for the stdin handler
-  -> (Handle -> (ByteString -> IO ()) -> IO (IO ()))
-  -- ^ Builder for the stdout and stderr handlers
+  => (Handle -> IO (i -> IO ()))
+  -- ^ Builder for the standard input handler
+  -> (Handle -> (o -> IO ()) -> IO (IO ()))
+  -- ^ Builder for the standard output handler
+  -> (Handle -> (e -> IO ()) -> IO (IO ()))
+  -- ^ Builder for the standard error handler
   -> CreateProcess
-  -> ProcessConfig t
-  -> m (Process t)
-createRedirectedProcess mkWriteInput mkReadOutput p (ProcessConfig input signal) = do
+  -> ProcessConfig t i
+  -> m (Process t o e)
+createRedirectedProcess mkWriteStdInput mkReadStdOutput mkReadStdError p (ProcessConfig input signal) = do
   let redirectedProc = p
         { std_in = CreatePipe
         , std_out = CreatePipe
         , std_err = CreatePipe
         }
-  po@(mi, mout, merr, ph) <- liftIO $ P.createProcess redirectedProc 
+  po@(mi, mout, merr, ph) <- liftIO $ P.createProcess redirectedProc
   case (mi, mout, merr) of
     (Just hIn, Just hOut, Just hErr) -> do
-      writeInput <- liftIO $ mkWriteInput hIn
+      writeInput <- liftIO $ mkWriteStdInput hIn
       performEvent_ $ liftIO . writeInput <$> input
       sigOut <- performEvent $ ffor signal $ \sig -> liftIO $ do
         mpid <- P.getPid ph
@@ -85,17 +88,23 @@
             P.signalProcess sig pid >> return (Just sig)
       let output h = do
             (e, trigger) <- newTriggerEvent
-            reader <- liftIO $ mkReadOutput h trigger
+            reader <- liftIO $ mkReadStdOutput h trigger
             t <- liftIO $ forkIO reader
             return (e, t)
+
+      let err_output h = do
+            (e, trigger) <- newTriggerEvent
+            reader <- liftIO $ mkReadStdError h trigger
+            t <- liftIO $ forkIO reader
+            return (e, t)
       (out, outThread) <- output hOut
-      (err, errThread) <- output hErr
+      (err, errThread) <- err_output hErr
       (ecOut, ecTrigger) <- newTriggerEvent
       void $ liftIO $ forkIO $ waitForProcess ph >>= \ec -> mask_ $ do
         ecTrigger ec
         P.cleanupProcess po
         killThread outThread
-        killThread errThread 
+        killThread errThread
       return $ Process
         { _process_exit = ecOut
         , _process_stdout = out
@@ -116,9 +125,9 @@
 createProcess
   :: (MonadIO m, TriggerEvent t m, PerformEvent t m, MonadIO (Performable m))
   => CreateProcess
-  -> ProcessConfig t
-  -> m (Process t)
-createProcess = createRedirectedProcess input output
+  -> ProcessConfig t ByteString
+  -> m (Process t ByteString ByteString)
+createProcess = createRedirectedProcess input output output
   where
     input h = do
       H.hSetBuffering h H.NoBuffering
