diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
 # Revision history for coquina
 
+## 0.2.0.0
+
+* `shellCreateProcessWithEnv` now takes an additional argument for stdin
+
 ## 0.1.0.1
 
 * Loosen version bounds
diff --git a/README.lhs b/README.lhs
--- a/README.lhs
+++ b/README.lhs
@@ -1,6 +1,3 @@
-# MOVED TO [GITHUB](https://github.com/obsidiansystems/coquina)
-
-
 # coquina
 [![Haskell](https://img.shields.io/badge/language-Haskell-orange.svg)](https://haskell.org) [![Hackage](https://img.shields.io/hackage/v/coquina.svg)](https://hackage.haskell.org/package/coquina) [![Hackage CI](https://matrix.hackage.haskell.org/api/v2/packages/coquina/badge)](https://matrix.hackage.haskell.org/#/package/coquina) [![Github CI](https://github.com/obsidiansystems/coquina/workflows/github-action/badge.svg)](https://github.com/obsidiansystems/coquina/actions) [![BSD3 License](https://img.shields.io/badge/license-BSD3-blue.svg)](https://github.com/obsidiansystems/coquina/blob/master/LICENSE)
 
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,6 +1,3 @@
-# MOVED TO [GITHUB](https://github.com/obsidiansystems/coquina)
-
-
 # coquina
 [![Haskell](https://img.shields.io/badge/language-Haskell-orange.svg)](https://haskell.org) [![Hackage](https://img.shields.io/hackage/v/coquina.svg)](https://hackage.haskell.org/package/coquina) [![Hackage CI](https://matrix.hackage.haskell.org/api/v2/packages/coquina/badge)](https://matrix.hackage.haskell.org/#/package/coquina) [![Github CI](https://github.com/obsidiansystems/coquina/workflows/github-action/badge.svg)](https://github.com/obsidiansystems/coquina/actions) [![BSD3 License](https://img.shields.io/badge/license-BSD3-blue.svg)](https://github.com/obsidiansystems/coquina/blob/master/LICENSE)
 
diff --git a/coquina.cabal b/coquina.cabal
--- a/coquina.cabal
+++ b/coquina.cabal
@@ -1,6 +1,6 @@
 cabal-version:      >=1.10
 name:               coquina
-version:            0.1.0.1
+version:            0.2.0.0
 synopsis:           Yet another shell monad.
 description:        A simple monad for shelling out from Haskell programs.
 bug-reports:        https://github.com/obsidiansystems/coquina/issues
diff --git a/src/Coquina.hs b/src/Coquina.hs
--- a/src/Coquina.hs
+++ b/src/Coquina.hs
@@ -158,7 +158,7 @@
 
 -- | Run a 'CreateProcess' in a 'Shell'
 shellCreateProcess :: MonadIO m => CreateProcess -> Shell m ()
-shellCreateProcess = shellCreateProcessWithEnv mempty
+shellCreateProcess p = shellCreateProcessWithEnv mempty p ""
 
 -- | Run a 'CreateProcess' in a 'Shell'
 run :: MonadIO m => CreateProcess -> Shell m ()
@@ -269,18 +269,19 @@
   :: MonadIO m
   => Map String String
   -> CreateProcess
+  -> Text -- ^ stdin
   -> Shell m ()
-shellCreateProcessWithEnv envOverrides = shellCreateProcessWith f
+shellCreateProcessWithEnv envOverrides cmd' stdin = shellCreateProcessWith f cmd'
   where
     f cmd = do
       envWithOverrides <- liftIO $ if Map.null envOverrides
         then return $ env cmd
         else Just . Map.toList . Map.union envOverrides . Map.fromList <$> getEnvironment
-      readAndDecodeCreateProcess $ cmd { env = envWithOverrides }
+      readAndDecodeCreateProcess (cmd { env = envWithOverrides }) stdin
 
 -- | Execute a shell process with environment variables
 runCreateProcessWithEnv :: Map String String -> CreateProcess -> IO (ExitCode, Text, Text)
-runCreateProcessWithEnv menv p = execShell $ shellCreateProcessWithEnv menv p
+runCreateProcessWithEnv menv p = execShell $ shellCreateProcessWithEnv menv p ""
 
 -- | Execute a shell process
 runCreateProcess :: CreateProcess -> IO (ExitCode, Text, Text)
diff --git a/src/Coquina/Internal.hs b/src/Coquina/Internal.hs
--- a/src/Coquina/Internal.hs
+++ b/src/Coquina/Internal.hs
@@ -1,29 +1,31 @@
 module Coquina.Internal where
 
-import Control.Concurrent (MVar, newEmptyMVar, forkIO, putMVar, takeMVar, killThread)
+import Control.Concurrent (MVar, forkIO, killThread, newEmptyMVar, putMVar, takeMVar)
 import Control.DeepSeq (rnf)
-import Control.Exception (SomeException, evaluate, mask, try, throwIO, onException)
+import Control.Exception (SomeException, evaluate, mask, onException, throwIO, try)
+import qualified Control.Exception as C
+import Control.Monad
 import Data.ByteString (hGetContents)
 import Data.Text (Text)
+import qualified Data.Text as T
 import Data.Text.Encoding (decodeUtf8)
-import System.Process
+import qualified Data.Text.IO as T
+import Foreign.C.Error (Errno(..), ePIPE)
+import GHC.IO.Exception (IOErrorType(..), IOException(..))
 import System.Exit
 import System.IO (hClose)
-
--- | The code below is taken from System.Process which unfortunately does not export this function
-withForkWait :: IO () -> (IO () ->  IO a) -> IO a
-withForkWait async body = do
-  waitVar <- newEmptyMVar :: IO (MVar (Either SomeException ()))
-  mask $ \restore -> do
-    tid <- forkIO $ try (restore async) >>= putMVar waitVar
-    let wait = takeMVar waitVar >>= either throwIO return
-    restore (body wait) `onException` killThread tid
+import System.Process
 
--- | Like readCreateProcess, but ignores stdin and decodes bytes, assuming utf-8
-readAndDecodeCreateProcess :: CreateProcess -> IO (ExitCode, Text, Text)
-readAndDecodeCreateProcess cp =
-  withCreateProcess (cp { std_out = CreatePipe, std_err = CreatePipe }) $ \_ mouth merrh ph -> case (mouth, merrh) of
-    (Just outh, Just errh) -> do
+-- | Like readCreateProcess
+readAndDecodeCreateProcess :: CreateProcess -> Text -> IO (ExitCode, Text, Text)
+readAndDecodeCreateProcess cp input =
+  withCreateProcess (cp { std_in = CreatePipe, std_out = CreatePipe, std_err = CreatePipe }) $ \mstdin mouth merrh ph -> case (mstdin, mouth, merrh) of
+    (Just inh, Just outh, Just errh) -> do
+      -- Write stdin
+      unless (T.null input) $ do
+        ignoreSigPipe $ T.hPutStr inh input
+      -- hClose performs implicit hFlush, and thus may trigger a SIGPIPE
+      ignoreSigPipe $ hClose inh
       out <- fmap decodeUtf8 $ hGetContents outh
       err <- fmap decodeUtf8 $ hGetContents errh
       withForkWait (evaluate $ rnf out) $ \waitOut ->
@@ -34,5 +36,23 @@
           hClose errh
       exitCode <- waitForProcess ph
       return (exitCode, out, err)
-    (Nothing, _) -> error "readAndDecodeCreateProcess: Failed to get std_out handle"
-    (Just _, Nothing) -> error "readAndDecodeCreateProcess: Failed to get std_err handle"
+    (Nothing, _, _) -> error "readAndDecodeCreateProcess: Failed to get std_in handle"
+    (_, Nothing, _) -> error "readAndDecodeCreateProcess: Failed to get std_out handle"
+    (_, _, Nothing) -> error "readAndDecodeCreateProcess: Failed to get std_err handle"
+
+-- * The code below is taken from System.Process which unfortunately does not export these functions
+
+-- | From System.Process
+withForkWait :: IO () -> (IO () ->  IO a) -> IO a
+withForkWait async body = do
+  waitVar <- newEmptyMVar :: IO (MVar (Either SomeException ()))
+  mask $ \restore -> do
+    tid <- forkIO $ try (restore async) >>= putMVar waitVar
+    let wait = takeMVar waitVar >>= either throwIO return
+    restore (body wait) `onException` killThread tid
+
+-- | From System.Process
+ignoreSigPipe :: IO () -> IO ()
+ignoreSigPipe = C.handle $ \e -> case e of
+  IOError { ioe_type  = ResourceVanished, ioe_errno = Just ioe } | Errno ioe == ePIPE -> return ()
+  _ -> throwIO e
