diff --git a/doctest.cabal b/doctest.cabal
--- a/doctest.cabal
+++ b/doctest.cabal
@@ -1,5 +1,5 @@
 name:             doctest
-version:          0.11.4
+version:          0.12.0
 synopsis:         Test interactive Haskell examples
 description:      The doctest program checks examples in source code comments.
                   It is modeled after doctest for Python
diff --git a/ghci-wrapper/src/Language/Haskell/GhciWrapper.hs b/ghci-wrapper/src/Language/Haskell/GhciWrapper.hs
--- a/ghci-wrapper/src/Language/Haskell/GhciWrapper.hs
+++ b/ghci-wrapper/src/Language/Haskell/GhciWrapper.hs
@@ -6,6 +6,7 @@
 , new
 , close
 , eval
+, evalIt
 , evalEcho
 ) where
 
@@ -38,6 +39,9 @@
 marker :: String
 marker = show "dcbd2a1e20ae519a1c7714df2859f1890581d57fac96ba3f499412b2f5c928a1"
 
+itMarker :: String
+itMarker = "d42472243a0e6fc481e7514cbc9eb08812ed48daa29ca815844d86010b1d113a"
+
 data Interpreter = Interpreter {
     hIn  :: Handle
   , hOut :: Handle
@@ -94,10 +98,12 @@
   when (e /= ExitSuccess) $ do
     throwIO (userError $ "Language.Haskell.GhciWrapper.close: Interpreter exited with an error (" ++ show e ++ ")")
 
-putExpression :: Interpreter -> String -> IO ()
-putExpression Interpreter{hIn = stdin} e = do
+putExpression :: Interpreter -> Bool -> String -> IO ()
+putExpression Interpreter{hIn = stdin} preserveIt e = do
   hPutStrLn stdin e
+  when preserveIt $ hPutStrLn stdin $ "let " ++ itMarker ++ " = it"
   hPutStrLn stdin marker
+  when preserveIt $ hPutStrLn stdin $ "let it = " ++ itMarker
   hFlush stdin
 
 getResult :: Bool -> Interpreter -> IO String
@@ -124,11 +130,17 @@
 -- | Evaluate an expression
 eval :: Interpreter -> String -> IO String
 eval repl expr = do
-  putExpression repl expr
+  putExpression repl False expr
   getResult False repl
 
+-- | Like 'eval', but try to preserve the @it@ variable
+evalIt :: Interpreter -> String -> IO String
+evalIt repl expr = do
+  putExpression repl True expr
+  getResult False repl
+
 -- | Evaluate an expression
 evalEcho :: Interpreter -> String -> IO String
 evalEcho repl expr = do
-  putExpression repl expr
+  putExpression repl True expr
   getResult True repl
diff --git a/src/Interpreter.hs b/src/Interpreter.hs
--- a/src/Interpreter.hs
+++ b/src/Interpreter.hs
@@ -3,6 +3,7 @@
 module Interpreter (
   Interpreter
 , safeEval
+, safeEvalIt
 , withInterpreter
 , ghc
 , interpreterSupported
@@ -59,6 +60,9 @@
 -- An exception may e.g. be caused on unterminated multiline expressions.
 safeEval :: Interpreter -> String -> IO (Either String String)
 safeEval repl = either (return . Left) (fmap Right . eval repl) . filterExpression
+
+safeEvalIt :: Interpreter -> String -> IO (Either String String)
+safeEvalIt repl = either (return . Left) (fmap Right . evalIt repl) . filterExpression
 
 filterExpression :: String -> Either String String
 filterExpression e =
diff --git a/src/Runner.hs b/src/Runner.hs
--- a/src/Runner.hs
+++ b/src/Runner.hs
@@ -131,12 +131,17 @@
         void $ Interpreter.safeEval repl ":reload"
       void $ Interpreter.safeEval repl $ ":m *" ++ module_
 
+      -- Evaluate a dumb expression to populate the 'it' variable NOTE: This is
+      -- one reason why we cannot have safeEval = safeEvalIt: 'it' isn't set in
+      -- a fresh GHCi session.
+      void $ Interpreter.safeEval repl $ "()"
+
     setup_ :: IO ()
     setup_ = do
       reload
       forM_ setup $ \l -> forM_ l $ \(Located _ x) -> case x of
         Property _  -> return ()
-        Example e _ -> void $ Interpreter.safeEval repl e
+        Example e _ -> void $ Interpreter.safeEvalIt repl e
 
 reportFailure :: Location -> Expression -> Report ()
 reportFailure loc expression = do
@@ -196,7 +201,7 @@
 runExampleGroup repl = go
   where
     go ((Located loc (expression, expected)) : xs) = do
-      r <- fmap lines <$> liftIO (Interpreter.safeEval repl expression)
+      r <- fmap lines <$> liftIO (Interpreter.safeEvalIt repl expression)
       case r of
         Left err -> do
           reportError loc expression err
