diff --git a/shelly.cabal b/shelly.cabal
--- a/shelly.cabal
+++ b/shelly.cabal
@@ -1,6 +1,6 @@
 Name:       shelly
 
-Version:     1.4.4.2
+Version:     1.5
 Synopsis:    shell-like (systems) programming in Haskell
 
 Description: Shelly provides convenient systems programming in Haskell,
diff --git a/src/Shelly.hs b/src/Shelly.hs
--- a/src/Shelly.hs
+++ b/src/Shelly.hs
@@ -23,7 +23,7 @@
 module Shelly
        (
          -- * Entering Sh.
-         Sh, ShIO, shelly, shellyNoDir, asyncSh, sub
+         Sh, ShIO, shelly, shellyNoDir, shellyFailDir, asyncSh, sub
          , silently, verbosely, escaping, print_stdout, print_stderr, print_commands
          , tracing, errExit
 
@@ -834,27 +834,30 @@
   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 }
+defReadOnlyState :: ReadOnlyState
+defReadOnlyState = ReadOnlyState { rosFailToDir = False }
 
--- | Using this entry point does not create a @.shelly@ directory in the case
+-- | Deprecated now, just use 'shelly', whose default has been changed.
+-- 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 }
+shellyNoDir = shelly' ReadOnlyState { rosFailToDir = False }
+{-# DEPRECATED shellyNoDir "Just use shelly. The default settings have changed" #-}
 
+-- Using this entry point creates a @.shelly@ directory in the case
+-- of failure where errors are recorded.
+shellyFailDir :: MonadIO m => Sh a -> m a
+shellyFailDir = shelly' ReadOnlyState { rosFailToDir = True }
+
 -- | 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 = shelly' shellyOpts
+shelly = shelly' defReadOnlyState
 
-shelly' :: MonadIO m => ShellyOpts -> Sh a -> m a
-shelly' opts action = do
+shelly' :: MonadIO m => ReadOnlyState -> Sh a -> m a
+shelly' ros action = do
   environment <- liftIO getEnvironment
   dir <- liftIO getWorkingDirectory
   let def  = State { sCode = 0
@@ -870,6 +873,7 @@
                    , sDirectory = dir
                    , sPathExecutables = Nothing
                    , sErrExit = True
+                   , sReadOnly = ros
                    }
   stref <- liftIO $ newIORef def
   let caught =
@@ -887,8 +891,9 @@
   where
     throwExplainedException :: Exception exception => exception -> Sh a
     throwExplainedException ex = get >>= errorMsg >>= liftIO . throwIO . ReThrownException ex
+
     errorMsg st =
-      if not (failToDir opts) then ranCommands else do
+      if not (rosFailToDir $ sReadOnly st) then ranCommands else do
           d <- pwd
           sf <- shellyFile
           let logFile = d</>shelly_dir</>sf
diff --git a/src/Shelly/Base.hs b/src/Shelly/Base.hs
--- a/src/Shelly/Base.hs
+++ b/src/Shelly/Base.hs
@@ -6,7 +6,7 @@
 -- However, Shelly went back to exposing a single module
 module Shelly.Base
   (
-    Sh, ShIO, unSh, runSh, State(..), StdHandle(..), FilePath, Text,
+    Sh, ShIO, unSh, runSh, State(..), ReadOnlyState(..), StdHandle(..), FilePath, Text,
     relPath, path, absPath, canonic, canonicalize,
     test_d, test_s,
     unpack, gets, get, modify, trace,
@@ -59,6 +59,7 @@
 runSh :: Sh a -> IORef State -> IO a
 runSh = runReaderT . unSh
 
+data ReadOnlyState = ReadOnlyState { rosFailToDir :: Bool }
 data State = State 
    { sCode :: Int -- ^ exit code for command that ran
    , sStdin :: Maybe Text -- ^ stdin for the command to be run
@@ -73,6 +74,7 @@
    , sTracing :: Bool -- ^ should we trace command execution
    , sTrace :: Text -- ^ the trace of command execution
    , sErrExit :: Bool -- ^ should we exit immediately on any error
+   , sReadOnly :: ReadOnlyState
    }
 
 data StdHandle = InHandle StdStream
diff --git a/src/Shelly/Pipe.hs b/src/Shelly/Pipe.hs
--- a/src/Shelly/Pipe.hs
+++ b/src/Shelly/Pipe.hs
@@ -36,7 +36,7 @@
 module Shelly.Pipe
        (
          -- * Entering Sh.
-         Sh, shs, shelly,shellyNoDir, shsNoDir, sub, silently, verbosely, escaping, print_stdout, print_commands, tracing, errExit
+         Sh, shs, shelly, shellyFailDir, shsFailDir, sub, silently, verbosely, escaping, print_stdout, print_commands, tracing, errExit
          -- * List functions
          , roll, unroll, liftSh
          -- * Running external commands.
@@ -210,15 +210,15 @@
 
 -- | Performs 'shelly' and then an empty action @return ()@. 
 shs :: MonadIO m => Sh () -> m ()
-shs a = shelly a >> return ()
+shs = void . shelly
 
--- | see 'S.shellyNoDir'
-shellyNoDir :: MonadIO m => Sh a -> m [a]
-shellyNoDir = S.shellyNoDir . unSh
+-- | see 'S.shellyFailDir'
+shellyFailDir :: MonadIO m => Sh a -> m [a]
+shellyFailDir = S.shellyFailDir . unSh
 
--- | Performs 'shellyNoDir' and then an empty action @return ()@.
-shsNoDir :: MonadIO m => Sh () -> m ()
-shsNoDir a = shellyNoDir a >> return ()
+-- | Performs 'shellyFailDir' and then an empty action @return ()@.
+shsFailDir :: MonadIO m => Sh () -> m ()
+shsFailDir = void . shellyFailDir
 
 -- | see 'S.sub'
 sub :: Sh a -> Sh a
