diff --git a/shelly.cabal b/shelly.cabal
--- a/shelly.cabal
+++ b/shelly.cabal
@@ -1,6 +1,6 @@
 Name:       shelly
 
-Version:     1.6.1.2
+Version:     1.6.2
 Synopsis:    shell-like (systems) programming in Haskell
 
 Description: Shelly provides convenient systems programming in Haskell,
@@ -72,3 +72,95 @@
 source-repository head
   type:     git
   location: https://github.com/yesodweb/Shelly.hs
+
+Flag lifted
+   Description: run the tests against Shelly.Lifted
+   Default: False
+
+Test-Suite shelly-testsuite
+  type: exitcode-stdio-1.0
+  hs-source-dirs: src test/src
+  main-is: TestMain.hs
+  ghc-options: -O2 -Wall -fhpc -fwarn-tabs -funbox-strict-fields -threaded
+               -fno-warn-unused-do-bind -fno-warn-type-defaults
+
+  extensions: OverloadedStrings, ExtendedDefaultRules
+
+  if flag(lifted)
+     cpp-options: -DLIFTED
+
+  build-depends:
+    base                      >= 4.6,
+    text                      >= 0.11,
+    async,
+    bytestring                >= 0.10,
+    containers                >= 0.5.0.0,
+    directory                 >= 1.1.0.0 && < 1.3.0.0,
+    process                   >= 1.1.0,
+    unix-compat               < 0.5,
+    system-filepath           >= 0.4.7 && < 0.5,
+    system-fileio             < 0.4,
+    time                      >= 1.3 && < 1.6,
+    mtl                       >= 2,
+    HUnit                     >= 1.2,
+    hspec                     >= 1.5,
+    transformers,
+    transformers-base,
+    monad-control,
+    lifted-base,
+    lifted-async,
+    enclosed-exceptions,
+    exceptions                == 0.6.*
+
+  extensions:
+    CPP
+
+Flag build-examples
+   Description: build some example programs
+   Default: False
+   Manual: True
+
+-- demonstarated that command output in Shellish was not shown until after the command finished
+-- not necessary anymore
+Executable drain
+  hs-source-dirs: test/examples
+  main-is: drain.hs
+  if flag(build-examples)
+    buildable: True
+
+    build-depends: base                      >= 4.6
+                 , shelly
+                 , text
+
+    extensions:
+      CPP
+  else
+    buildable: False
+
+Executable run-handles
+  hs-source-dirs: test/examples
+  main-is: run-handles.hs
+  if flag(build-examples)
+    buildable: True
+
+    build-depends: base                      >= 4.6
+                 , shelly
+                 , text
+
+    extensions:
+      CPP
+  else
+    buildable: False
+
+Executable Color
+  hs-source-dirs: test/examples
+  main-is: color.hs
+  if flag(build-examples)
+    buildable: True
+
+    build-depends: base                      >= 4.6
+                 , process
+                 , shelly
+                 , text
+  else
+    buildable: False
diff --git a/src/Shelly.hs b/src/Shelly.hs
--- a/src/Shelly.hs
+++ b/src/Shelly.hs
@@ -25,6 +25,7 @@
          -- * Entering Sh.
          Sh, ShIO, shelly, shellyNoDir, shellyFailDir, asyncSh, sub
          , silently, verbosely, escaping, print_stdout, print_stderr, print_commands
+         , onCommandHandles
          , tracing, errExit
          , log_stdout_with, log_stderr_with
 
@@ -39,6 +40,8 @@
          , runHandle, runHandles, transferLinesAndCombine, transferFoldHandleLines
          , StdHandle(..), StdStream(..)
 
+         -- * Handle manipulation
+         , HandleInitializer, StdInit(..), initOutputHandles, initAllHandles
 
          -- * Modifying and querying environment.
          , setenv, get_env, get_env_text, getenv, get_env_def, get_env_all, get_environment, appendToPath
@@ -753,7 +756,22 @@
 get_env_def d = get_env >=> return . fromMaybe d
 {-# DEPRECATED get_env_def "use fromMaybe DEFAULT get_env" #-}
 
+-- | Apply a single initializer to the two output process handles (stdout and stderr)
+initOutputHandles :: HandleInitializer -> StdInit
+initOutputHandles f = StdInit (const $ return ()) f f
 
+-- | Apply a single initializer to all three standard process handles (stdin, stdout and stderr)
+initAllHandles :: HandleInitializer -> StdInit
+initAllHandles f = StdInit f f f
+
+-- | When running an external command, apply the given initializers to
+-- the specified handles for that command.
+-- This can for example be used to change the encoding of the
+-- handles or set them into binary mode.
+onCommandHandles :: StdInit -> Sh a -> Sh a
+onCommandHandles initHandles a =
+    sub $ modify (\x -> x { sInitCommandHandles = initHandles }) >> a
+
 -- | Create a sub-Sh in which external command outputs are not echoed and
 -- commands are not printed.
 -- See 'sub'.
@@ -839,9 +857,7 @@
 -- see the 'run' documentation.
 escaping :: Bool -> Sh a -> Sh a
 escaping shouldEscape action = sub $ do
-  modify $ \st -> st { sRun =
-      if shouldEscape then runCommand else runCommandNoEscape
-    }
+  modify $ \st -> st { sCommandEscaping = shouldEscape }
   action
 
 -- | named after bash -e errexit. Defaults to @True@.
@@ -887,7 +903,8 @@
                    , sPrintStdout = True
                    , sPrintStderr = True
                    , sPrintCommands = False
-                   , sRun = runCommand
+                   , sInitCommandHandles = initAllHandles (const $ return ())
+                   , sCommandEscaping = True
                    , sEnvironment = environment
                    , sTracing = True
                    , sTrace = T.empty
@@ -1119,10 +1136,18 @@
     when (sPrintCommands state) $ echo cmdString
     trace cmdString
 
+    let doRun = if sCommandEscaping state then runCommand else runCommandNoEscape
+
     bracket_sh
-      ((sRun state) reusedHandles state exe args)
+      (doRun reusedHandles state exe args)
       (\(_,_,_,procH) -> (liftIO $ terminateProcess procH))
       (\(inH,outH,errH,procH) -> do
+
+        liftIO $ do
+          inInit (sInitCommandHandles state) inH
+          outInit (sInitCommandHandles state) outH
+          errInit (sInitCommandHandles state) errH
+
         liftIO $ case mStdin of
           Just input -> TIO.hPutStr inH input
           Nothing -> return ()
@@ -1251,7 +1276,7 @@
   mkdir p
   act p `finally_sh` rm_rf p
 
--- | Write a Lazy Text to a file.
+-- | Write a Text to a file.
 writefile :: FilePath -> Text -> Sh ()
 writefile f' bits = do
   f <- traceAbsPath ("writefile " <>) f'
@@ -1261,7 +1286,7 @@
 touchfile :: FilePath -> Sh ()
 touchfile = traceAbsPath ("touch " <>) >=> flip appendfile ""
 
--- | Append a Lazy Text to a file.
+-- | Append a Text to a file.
 appendfile :: FilePath -> Text -> Sh ()
 appendfile f' bits = do
   f <- traceAbsPath ("appendfile " <>) f'
diff --git a/src/Shelly/Base.hs b/src/Shelly/Base.hs
--- a/src/Shelly/Base.hs
+++ b/src/Shelly/Base.hs
@@ -12,7 +12,9 @@
 -- However, Shelly went back to exposing a single module
 module Shelly.Base
   (
-    Sh(..), ShIO, runSh, State(..), ReadOnlyState(..), StdHandle(..), FilePath, Text,
+    Sh(..), ShIO, runSh, State(..), ReadOnlyState(..), StdHandle(..),
+    HandleInitializer, StdInit(..),
+    FilePath, Text,
     relPath, path, absPath, canonic, canonicalize,
     test_d, test_s,
     unpack, gets, get, modify, trace,
@@ -113,7 +115,10 @@
    , sPutStderr :: Text -> IO ()   -- ^ by default, hPutStrLn stderr
    , sPrintStderr :: Bool   -- ^ print stderr of command that is executed
    , sPrintCommands :: Bool -- ^ print command that is executed
-   , sRun :: [StdHandle] -> State -> FilePath -> [Text] -> Sh (Handle, Handle, Handle, ProcessHandle) -- ^ command runner, a different runner is used when escaping, probably better to just hold the escaping flag
+   , sInitCommandHandles :: StdInit -- ^ initializers for the standard process handles
+                                    -- when running a command
+   , sCommandEscaping :: Bool -- ^ when running a command, escape shell characters such as '*' rather
+                              -- than passing to the shell for expansion
    , sEnvironment :: [(String, String)]
    , sPathExecutables :: Maybe [(FilePath, S.Set FilePath)] -- ^ cache of executables in the PATH
    , sTracing :: Bool -- ^ should we trace command execution
@@ -125,6 +130,17 @@
 data StdHandle = InHandle StdStream
                | OutHandle StdStream
                | ErrorHandle StdStream
+
+-- | Initialize a handle before using it
+type HandleInitializer = Handle -> IO ()
+
+-- | A collection of initializers for the three standard process handles
+data StdInit =
+    StdInit {
+      inInit :: HandleInitializer,
+      outInit :: HandleInitializer,
+      errInit :: HandleInitializer
+    }
 
 -- | A monadic-conditional version of the "when" guard.
 whenM :: Monad m => m Bool -> m () -> m ()
diff --git a/test/examples/color.hs b/test/examples/color.hs
new file mode 100644
--- /dev/null
+++ b/test/examples/color.hs
@@ -0,0 +1,12 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE ExtendedDefaultRules #-}
+import Shelly
+import System.Process (rawSystem)
+import Control.Monad (void)
+import Data.Text (Text)
+
+default (Text)
+
+main = shelly $ do
+  void $ liftIO $ rawSystem "ls" ["--color=auto", "../dist"]
+  run_ "ls" ["--color=auto", "../dist"]
diff --git a/test/examples/drain.hs b/test/examples/drain.hs
new file mode 100644
--- /dev/null
+++ b/test/examples/drain.hs
@@ -0,0 +1,19 @@
+{-# Language OverloadedStrings, ExtendedDefaultRules #-}
+import Prelude hiding (FilePath)
+import Shelly
+import Control.Monad (void)
+import Data.Text (Text)
+
+default (Text)
+
+main :: IO ()
+main = do
+  let exDir = "examples"
+  void $ shelly $ do
+    let strs = ["a", "b"] :: [String]
+    let texts = ["a", "b"] :: [Text]
+    let inferred = ["a", "b"]
+    res <- cmd (exDir </> "drain.sh") strs texts inferred
+    echo "haskell done"
+    echo res
+    cmd $ exDir </> "printer.sh"
diff --git a/test/examples/run-handles.hs b/test/examples/run-handles.hs
new file mode 100644
--- /dev/null
+++ b/test/examples/run-handles.hs
@@ -0,0 +1,8 @@
+{-# Language OverloadedStrings, ExtendedDefaultRules #-}
+import Shelly
+-- This test runs, but causes this error to show up:
+-- Exception: cannot access an inherited pipe
+main = shelly $
+  runHandles "bash" ["examples/test.sh"] handles doNothing
+  where handles = [InHandle Inherit, OutHandle Inherit, ErrorHandle Inherit]
+        doNothing _ _ _ = return ""
diff --git a/test/src/TestMain.hs b/test/src/TestMain.hs
new file mode 100644
--- /dev/null
+++ b/test/src/TestMain.hs
@@ -0,0 +1,31 @@
+
+module Main where
+
+import ReadFileSpec
+import WhichSpec
+import WriteSpec
+import MoveSpec
+import RmSpec
+import FindSpec
+import EnvSpec
+import FailureSpec
+import CopySpec
+import LiftedSpec
+import RunSpec
+
+import Test.Hspec
+
+main :: IO ()
+main = hspec $ do
+    readFileSpec
+    whichSpec
+    writeSpec
+    moveSpec
+    rmSpec
+    findSpec
+    envSpec
+    failureSpec
+    copySpec
+    liftedSpec
+    runSpec
+
