diff --git a/Shelly.hs b/Shelly.hs
--- a/Shelly.hs
+++ b/Shelly.hs
@@ -25,7 +25,7 @@
 module Shelly
        (
          -- * Entering Sh.
-         Sh, ShIO, shelly, sub, silently, verbosely, escaping, print_stdout, print_commands, tracing, errExit
+         Sh, ShIO, shelly, shellyNoDir, sub, silently, verbosely, escaping, print_stdout, print_commands, tracing, errExit
 
          -- * Running external commands.
          , run, run_, runFoldLines, cmd, (-|-), lastStderr, setStdin, lastExitCode
@@ -212,8 +212,10 @@
 printGetContent rH wH =
     fmap B.toLazyText $ printFoldHandleLines (B.fromText "") foldBuilder rH wH
 
+{-
 getContent :: Handle -> IO Text
 getContent h = fmap B.toLazyText $ foldHandleLines (B.fromText "") foldBuilder h
+-}
 
 type FoldCallback a = ((a, Text) -> a)
 
@@ -329,7 +331,7 @@
       where
         tdir = toTextIgnore dir
 
--- | "cd", execute a Sh action in the new directory and then pop back to the original directory
+-- | 'cd', execute a Sh action in the new directory and then pop back to the original directory
 chdir :: FilePath -> Sh a -> Sh a
 chdir dir action = do
   d <- gets sDirectory
@@ -354,8 +356,8 @@
 pack :: String -> FilePath
 pack = decodeString
 
--- | Currently a "renameFile" wrapper. TODO: Support cross-filesystem
--- move. TODO: Support directory paths in the second parameter, like in "cp".
+-- | Currently a 'renameFile' wrapper. TODO: Support cross-filesystem
+-- move. TODO: Support directory paths in the second parameter, like in 'cp'.
 mv :: FilePath -> FilePath -> Sh ()
 mv a b = do a' <- absPath a
             b' <- absPath b
@@ -410,7 +412,7 @@
   (trace . mappend "which " . toTextIgnore) fp
   (liftIO . findExecutable . unpack >=> return . fmap pack) fp
 
--- | A monadic-conditional version of the "unless" guard.
+-- | A monadic-conditional version of the 'unless' guard.
 unlessM :: Monad m => m Bool -> m () -> m ()
 unlessM c a = c >>= \res -> unless res a
 
@@ -470,6 +472,7 @@
 
 -- | add the filepath onto the PATH env variable
 -- FIXME: only effects the PATH once the process is ran, as per comments in 'which'
+-- TODO: use cross-platform searchPathSeparator
 appendToPath :: FilePath -> Sh ()
 appendToPath = absPath >=> \filepath -> do
   tp <- toTextWarn filepath
@@ -501,6 +504,7 @@
 -- non-existent variables give the default Text value as a result
 get_env_def :: Text -> Text -> Sh Text
 get_env_def d = get_env >=> return . fromMaybe d
+{-# DEPRECATED get_env_def "use fromMaybe DEFAULT get_env" #-}
 
 
 -- | Create a sub-Sh in which external command outputs are not echoed and
@@ -537,7 +541,15 @@
   where
     restoreState oldState = do
       newState <- get
-      put oldState { sTrace = sTrace oldState `mappend` sTrace newState  }
+      put oldState {
+         -- avoid losing the log
+         sTrace  = sTrace oldState `mappend` sTrace newState 
+         -- latest command execution: not make sense to restore these to old settings
+       , sCode   = sCode newState
+       , sStderr = sStderr newState
+         -- it is questionable what the behavior of stdin should be
+       , sStdin  = sStdin newState
+       }
 
 -- | Create a sub-Sh where commands are not traced
 -- Defaults to True.
@@ -559,20 +571,36 @@
     }
   action
 
--- | named after bash -e errexit. Defaults to True.
--- When True, throw an exception on a non-zero exit code.
--- Not recommended to set to False unless you are specifically checking the error code with 'lastExitCode'.
+-- | named after bash -e errexit. Defaults to @True@.
+-- When @True@, throw an exception on a non-zero exit code.
+-- When @False@, ignore a non-zero exit code.
+-- Not recommended to set to @False@ unless you are specifically checking the error code with 'lastExitCode'.
 errExit :: Bool -> Sh a -> Sh a
 errExit shouldExit action = sub $ do
   modify $ \st -> st { sErrExit = shouldExit }
   action
 
+data ShellyOpts = ShellyOpts { failToDir :: Bool }
+
+-- avoid data-default dependency for now
+-- instance Default ShellyOpts where 
+shellyOpts :: ShellyOpts
+shellyOpts = ShellyOpts { failToDir = True }
+
+-- | Using this entry point does not create a @.shelly@ directory in the case
+-- of failure. Instead it logs directly into the standard error stream (@stderr@).
+shellyNoDir :: MonadIO m => Sh a -> m a
+shellyNoDir = shelly' shellyOpts { failToDir = False }
+
 -- | Enter a Sh from (Monad)IO. The environment and working directories are
 -- inherited from the current process-wide values. Any subsequent changes in
 -- processwide working directory or environment are not reflected in the
 -- running Sh.
 shelly :: MonadIO m => Sh a -> m a
-shelly action = do
+shelly = shelly' shellyOpts
+
+shelly' :: MonadIO m => ShellyOpts -> Sh a -> m a
+shelly' opts action = do
   environment <- liftIO getEnvironment
   dir <- liftIO getWorkingDirectory
   let def  = State { sCode = 0
@@ -603,14 +631,18 @@
   where
     throwExplainedException :: Exception exception => exception -> Sh a
     throwExplainedException ex = get >>= errorMsg >>= liftIO . throwIO . ReThrownException ex
-    errorMsg st = do
-      let trc = B.toLazyText . sTrace $ st
-      d <- pwd
-      sf <- shellyFile
-      let f = d</>shelly_dir</>sf
-      (writefile f trc >> return ("log of commands saved to: " `mappend` encodeString f))
-        `catchany_sh` (\_ -> return $ "Ran commands: \n" `mappend` LT.unpack trc)
+    errorMsg st =
+      if not (failToDir opts) then ranCommands else do
+          d <- pwd
+          sf <- shellyFile
+          let logFile = d</>shelly_dir</>sf
+          (writefile logFile trc >> return ("log of commands saved to: " `mappend` encodeString logFile))
+            `catchany_sh` (\_ -> ranCommands)
 
+      where
+        trc = B.toLazyText . sTrace $ st
+        ranCommands = return . mappend "Ran commands: \n" . LT.unpack $ trc
+
     shelly_dir = ".shelly"
     shellyFile = chdir_p shelly_dir $ do
       fs <- ls "."
@@ -666,7 +698,7 @@
 -- This interface is crude, but it works for now.
 --
 -- Please note this sets 'escaping' to False: the commands will not be shell escaped.
--- Internally the list of commands are combined with the string " && " before given to ssh.
+-- Internally the list of commands are combined with the string @&&@ before given to ssh.
 sshPairs :: Text -> [(FilePath, [Text])] -> Sh Text
 sshPairs _ [] = return ""
 sshPairs server cmds = sshPairs' run server cmds
@@ -694,13 +726,13 @@
 -- just a name of something that can be found via @PATH@; FIXME: setenv'd
 -- @PATH@ is not taken into account when finding the exe name)
 --
--- "stdout" and "stderr" are collected. The "stdout" is returned as
--- a result of "run", and complete stderr output is available after the fact using
--- "lastStderr"
+-- 'stdout' and 'stderr' are collected. The 'stdout' is returned as
+-- a result of 'run', and complete stderr output is available after the fact using
+-- 'lastStderr'
 --
 -- All of the stdout output will be loaded into memory
--- You can avoid this but still consume the result by using "run_",
--- If you want to avoid the memory and need to process the output then use "runFoldLines".
+-- You can avoid this but still consume the result by using 'run_',
+-- If you want to avoid the memory and need to process the output then use 'runFoldLines'.
 run :: FilePath -> [Text] -> Sh Text
 run exe args = fmap B.toLazyText $ runFoldLines (B.fromText "") foldBuilder exe args
 
@@ -708,27 +740,31 @@
 foldBuilder (b, line) = b `mappend` B.fromLazyText line `mappend` B.singleton '\n'
 
 
--- | bind some arguments to run for re-use
--- Example: @monit = command "monit" ["-c", "monitrc"]@
+-- | bind some arguments to run for re-use. Example:
+--
+-- > monit = command "monit" ["-c", "monitrc"]
 command :: FilePath -> [Text] -> [Text] -> Sh Text
 command com args more_args = run com (args ++ more_args)
 
--- | bind some arguments to "run_" for re-use
--- Example: @monit_ = command_ "monit" ["-c", "monitrc"]@
+-- | bind some arguments to 'run_' for re-use. Example:
+--
+-- > monit_ = command_ "monit" ["-c", "monitrc"]
 command_ :: FilePath -> [Text] -> [Text] -> Sh ()
 command_ com args more_args = run_ com (args ++ more_args)
 
--- | bind some arguments to run for re-use, and expect 1 argument
--- Example: @git = command1 "git" []; git "pull" ["origin", "master"]@
+-- | bind some arguments to run for re-use, and expect 1 argument. Example:
+--
+-- > git = command1 "git" []; git "pull" ["origin", "master"]
 command1 :: FilePath -> [Text] -> Text -> [Text] -> Sh Text
 command1 com args one_arg more_args = run com ([one_arg] ++ args ++ more_args)
 
--- | bind some arguments to run for re-use, and expect 1 argument
--- Example: @git_ = command1_ "git" []; git+ "pull" ["origin", "master"]@
+-- | bind some arguments to run for re-use, and expect 1 argument. Example:
+--
+-- > git_ = command1_ "git" []; git+ "pull" ["origin", "master"]
 command1_ :: FilePath -> [Text] -> Text -> [Text] -> Sh ()
 command1_ com args one_arg more_args = run_ com ([one_arg] ++ args ++ more_args)
 
--- | the same as "run", but return () instead of the stdout content
+-- | the same as 'run', but return @()@ instead of the stdout content
 -- stdout will be read and discarded line-by-line
 run_ :: FilePath -> [Text] -> Sh ()
 run_ = runFoldLines () (\(_, _) -> ())
@@ -736,7 +772,7 @@
 liftIO_ :: IO a -> Sh ()
 liftIO_ action = liftIO action >> return ()
 
--- | used by "run". fold over stdout line-by-line as it is read to avoid keeping it in memory
+-- | used by 'run'. fold over stdout line-by-line as it is read to avoid keeping it in memory
 -- stderr is still being placed in memory under the assumption it is always relatively small
 runFoldLines :: a -> FoldCallback a -> FilePath -> [Text] -> Sh a
 runFoldLines start cb exe args = do
@@ -760,12 +796,13 @@
 
     errV <- liftIO newEmptyMVar
     outV <- liftIO newEmptyMVar
+
+    liftIO_ $ forkIO $ printGetContent errH stderr >>= putMVar errV
+    -- liftIO_ $ forkIO $ getContent errH >>= putMVar errV
     if sPrintStdout state
-      then do
-        liftIO_ $ forkIO $ printGetContent errH stderr >>= putMVar errV
+      then
         liftIO_ $ forkIO $ printFoldHandleLines start cb outH stdout >>= putMVar outV
-      else do
-        liftIO_ $ forkIO $ getContent errH >>= putMVar errV
+      else
         liftIO_ $ forkIO $ foldHandleLines start cb outH >>= putMVar outV
 
     errs <- liftIO $ takeMVar errV
@@ -781,7 +818,7 @@
       (True,  ExitFailure n) -> throwIO $ RunFailed exe args n errs
       _                      -> takeMVar outV
 
--- | The output of last external command. See "run".
+-- | The output of last external command. See 'run'.
 lastStderr :: Sh Text
 lastStderr = gets sStderr
 
@@ -790,11 +827,13 @@
 lastExitCode :: Sh Int
 lastExitCode = gets sCode
 
--- | set the stdin to be used and cleared by the next "run".
+-- | set the stdin to be used and cleared by the next 'run'.
 setStdin :: Text -> Sh ()
 setStdin input = modify $ \st -> st { sStdin = Just input }
 
 -- | Pipe operator. set the stdout the first command as the stdin of the second.
+-- This does not create a shell-level pipe, but hopefully it will in the future.
+-- To create a shell level pipe you can always set @escaping False@ and use a pipe @|@ character in a command.
 (-|-) :: Sh Text -> Sh b -> Sh b
 one -|- two = do
   res <- print_stdout False one
diff --git a/Shelly/Base.hs b/Shelly/Base.hs
--- a/Shelly/Base.hs
+++ b/Shelly/Base.hs
@@ -15,7 +15,7 @@
     liftIO, (>=>),
     eitherRelativeTo, relativeTo, maybeRelativeTo,
     whenM
-    -- * utitlities not yet exported
+    -- * utilities not yet exported
     , addTrailingSlash
   ) where
 
@@ -25,13 +25,12 @@
 import System.IO ( Handle, hFlush, stderr, stdout )
 
 import Control.Monad (when, (>=>) )
-import Control.Applicative(Applicative)
+import Control.Applicative (Applicative, (<$>))
 import Filesystem (isDirectory, listDirectory)
 import System.PosixCompat.Files( getSymbolicLinkStatus, isSymbolicLink )
 import Filesystem.Path.CurrentOS (FilePath, encodeString, relative)
 import qualified Filesystem.Path.CurrentOS as FP
 import qualified Filesystem as FS
-import Control.Applicative ((<$>))
 import Data.IORef (readIORef, modifyIORef, IORef)
 import Data.Monoid (mappend)
 import qualified Data.Text.Lazy as LT
@@ -128,7 +127,7 @@
     p FP.</> FP.empty
 
 -- | makes an absolute path.
--- Like 'canonicalize', but on an exception returns 'path'
+-- Like 'canonicalize', but on an exception returns 'absPath'
 canonic :: FilePath -> Sh FilePath
 canonic fp = do
   p <- absPath fp
@@ -147,11 +146,12 @@
 
 -- | Make a relative path absolute by combining with the working directory.
 -- An absolute path is returned as is.
--- To create a relative path, use 'path'.
+-- To create a relative path, use 'relPath'.
 absPath :: FilePath -> Sh FilePath
 absPath p | relative p = (FP.</> p) <$> gets sDirectory
           | otherwise = return p
 
+-- | deprecated
 path :: FilePath -> Sh FilePath
 path = absPath
 {-# DEPRECATED path "use absPath, canonic, or relPath instead" #-}
@@ -182,7 +182,7 @@
   state <- ask 
   liftIO (modifyIORef state f)
 
--- | internally log what occured.
+-- | internally log what occurred.
 -- Log will be re-played on failure.
 trace :: Text -> Sh ()
 trace msg =
diff --git a/shelly.cabal b/shelly.cabal
--- a/shelly.cabal
+++ b/shelly.cabal
@@ -1,6 +1,6 @@
 Name:       shelly
 
-Version:     0.14.0.1
+Version:     0.14.1
 Synopsis:    shell-like (systems) programming in Haskell
 
 Description: Shelly provides convenient systems programming in Haskell,
@@ -57,7 +57,7 @@
                  , system-fileio < 0.4
                  , bytestring
                  , hspec-discover
-                 , hspec >= 1.1
+                 , hspec >= 1.3
                  , HUnit
 
 -- demonstarated that command output in Shellish was not shown until after the command finished
diff --git a/test/main.hs b/test/main.hs
--- a/test/main.hs
+++ b/test/main.hs
@@ -1,5 +1,5 @@
-{-# OPTIONS_GHC -F -pgmF hspec-discover -optF --nested #-}
+{- # OPTIONS_GHC -F -pgmF hspec-discover -optF --nested #-}
 {-import qualified CopySpec-}
 {-main = CopySpec.main-}
--- import qualified FindSpec
--- main = FindSpec.main
+import qualified FailureSpec
+main = FailureSpec.main
