diff --git a/hspec-discover/example/Spec.hs b/hspec-discover/example/Spec.hs
new file mode 100644
--- /dev/null
+++ b/hspec-discover/example/Spec.hs
@@ -0,0 +1,1 @@
+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
diff --git a/hspec-discover/integration-test/empty/Spec.hs b/hspec-discover/integration-test/empty/Spec.hs
new file mode 100644
--- /dev/null
+++ b/hspec-discover/integration-test/empty/Spec.hs
@@ -0,0 +1,1 @@
+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
diff --git a/hspec-discover/src/Main.hs b/hspec-discover/src/Main.hs
new file mode 100644
--- /dev/null
+++ b/hspec-discover/src/Main.hs
@@ -0,0 +1,8 @@
+module Main (main) where
+
+import           System.Environment
+
+import           Run (run)
+
+main :: IO ()
+main = getArgs >>= run
diff --git a/hspec-discover/src/Run.hs b/hspec-discover/src/Run.hs
new file mode 100644
--- /dev/null
+++ b/hspec-discover/src/Run.hs
@@ -0,0 +1,161 @@
+{-# LANGUAGE TypeSynonymInstances, FlexibleInstances, OverloadedStrings #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+-- | A preprocessor that finds and combines specs.
+module Run where
+import           Control.Monad
+import           Control.Applicative
+import           Data.List
+import           Data.String
+import           Data.Function
+import           System.Environment
+import           System.Exit
+import           System.IO
+import           System.Directory
+import           System.FilePath hiding (combine)
+
+instance IsString ShowS where
+  fromString = showString
+
+run :: [String] -> IO ()
+run args_ = case args_ of
+  src : _ : dst : args -> do
+    nested <- case args of
+      []           -> return False
+      ["--nested"] -> return True
+      _            -> exit
+    specs <- findSpecs src
+    writeFile dst (mkSpecModule src nested specs)
+  _ -> exit
+  where
+    exit = do
+      name <- getProgName
+      hPutStrLn stderr ("usage: " ++ name ++ " SRC CUR DST [--nested]")
+      exitFailure
+
+mkSpecModule :: FilePath -> Bool -> [SpecNode] -> String
+mkSpecModule src nested nodes =
+  ( "{-# LINE 1 " . shows src . " #-}"
+  . showString "module Main where\n"
+  . showString "import Test.Hspec\n"
+  . importList nodes
+  . showString "main :: IO ()\n"
+  . showString "main = hspec $ "
+  . format nodes
+  ) "\n"
+  where
+    format
+      | nested    = formatSpecsNested
+      | otherwise = formatSpecs
+
+-- | Generate imports for a list of specs.
+importList :: [SpecNode] -> ShowS
+importList = go ""
+  where
+    go :: ShowS -> [SpecNode] -> ShowS
+    go current = foldr (.) "" . map (f current)
+    f current (SpecNode name inhabited children) = this . go (current . showString name . ".") children
+      where
+        this
+          | inhabited = "import qualified " . current . showString name . "Spec\n"
+          | otherwise = id
+
+-- | Combine a list of strings with (>>).
+sequenceS :: [ShowS] -> ShowS
+sequenceS = foldr (.) "" . intersperse " >> "
+
+-- | Convert a list of specs to code.
+formatSpecs :: [SpecNode] -> ShowS
+formatSpecs xs
+  | null xs   = "return ()"
+  | otherwise = sequenceS (map formatSpec xs)
+
+-- | Convert a spec to code.
+formatSpec :: SpecNode -> ShowS
+formatSpec = sequenceS . go ""
+  where
+    go :: String -> SpecNode -> [ShowS]
+    go current (SpecNode name inhabited children) = addThis $ concatMap (go (current ++ name ++ ".")) children
+      where
+        addThis :: [ShowS] -> [ShowS]
+        addThis
+          | inhabited = ("describe " . shows (current ++ name) . " " . showString (current ++ name ++ "Spec.spec") :)
+          | otherwise = id
+
+-- | Convert a list of specs to code.
+--
+-- Hierarchical modules are mapped to nested specs.
+formatSpecsNested :: [SpecNode] -> ShowS
+formatSpecsNested xs
+  | null xs   = "return ()"
+  | otherwise = sequenceS (map formatSpecNested xs)
+
+-- | Convert a spec to code.
+--
+-- Hierarchical modules are mapped to nested specs.
+formatSpecNested :: SpecNode -> ShowS
+formatSpecNested = go ""
+  where
+    go current (SpecNode name inhabited children) = "describe " . shows name . " (" . specs . ")"
+      where
+        specs :: ShowS
+        specs = (sequenceS . addThis . map (go (current . showString name . "."))) children
+        addThis
+          | inhabited = ((current . showString name . "Spec.spec") :)
+          | otherwise = id
+
+data SpecNode = SpecNode String Bool [SpecNode]
+  deriving (Eq, Show)
+
+specNodeName :: SpecNode -> String
+specNodeName (SpecNode name _ _) = name
+
+specNodeInhabited :: SpecNode -> Bool
+specNodeInhabited (SpecNode _ inhabited _) = inhabited
+
+specNodeChildren :: SpecNode -> [SpecNode]
+specNodeChildren (SpecNode _ _ children) = children
+
+getFilesAndDirectories :: FilePath -> IO ([FilePath], [FilePath])
+getFilesAndDirectories dir = do
+  c <- filter (`notElem` ["..", "."]) <$> getDirectoryContents dir
+  dirs <- filterM (doesDirectoryExist . (dir </>)) c
+  files <- filterM (doesFileExist . (dir </>)) c
+  return (dirs, files)
+
+-- | Find specs relative to given source file.
+--
+-- The source file itself is not considered.
+findSpecs :: FilePath -> IO [SpecNode]
+findSpecs src = do
+  let (dir, file) = splitFileName src
+  (dirs, files) <- getFilesAndDirectories dir
+  go dir (dirs, filter (/= file) files)
+  where
+    go :: FilePath -> ([FilePath], [FilePath]) -> IO [SpecNode]
+    go base (dirs, files) = do
+      nestedSpecs <- forM dirs $ \d -> do
+        let dir = base </> d
+        SpecNode d False <$> (getFilesAndDirectories dir >>= go dir)
+      (return . filterSpecs . combineSpecs) (specsFromFiles files ++ nestedSpecs)
+      where
+        specsFromFiles = map (\x -> SpecNode (stripSuffix x) True []) . filter (isSuffixOf suffix)
+          where
+            suffix = "Spec.hs"
+            stripSuffix = reverse . drop (length suffix) . reverse
+
+        -- remove empty leafs
+        filterSpecs :: [SpecNode] -> [SpecNode]
+        filterSpecs = filter (\x -> specNodeInhabited x || (not . null . specNodeChildren) x)
+
+        -- sort specs, and merge nodes with the same name
+        combineSpecs :: [SpecNode] -> [SpecNode]
+        combineSpecs = foldr f [] . sortBy (compare `on` specNodeName)
+          where
+            f x@(SpecNode n1 _ _) (y@(SpecNode n2 _ _):acc) | n1 == n2 = x `combine` y : acc
+            f x acc = x : acc
+
+            x `combine` y = SpecNode name inhabited children
+              where
+                name      = specNodeName x
+                inhabited = specNodeInhabited x || specNodeInhabited y
+                children  = specNodeChildren x ++ specNodeChildren y
diff --git a/hspec-discover/test/Spec.hs b/hspec-discover/test/Spec.hs
new file mode 100644
--- /dev/null
+++ b/hspec-discover/test/Spec.hs
@@ -0,0 +1,1 @@
+{-# OPTIONS_GHC -F -pgmF hspec-meta-discover #-}
diff --git a/hspec.cabal b/hspec.cabal
--- a/hspec.cabal
+++ b/hspec.cabal
@@ -1,10 +1,9 @@
 name:             hspec
-version:          1.2.0.1
+version:          1.3.0
 license:          BSD3
 license-file:     LICENSE
-copyright:        (c) 2011 Trystan Spangler
-author:           Trystan Spangler
-maintainer:       trystan.s@comcast.net
+copyright:        (c) 2011-2012 Trystan Spangler, (c) 2011-2012 Simon Hengel, (c) 2011 Greg Weber
+maintainer:       Simon Hengel <sol@typeful.net>
 build-type:       Simple
 cabal-version:    >= 1.8
 category:         Testing
@@ -39,14 +38,15 @@
     , transformers >= 0.2.0 && < 0.4.0
     , HUnit >= 1 && <= 2
     , QuickCheck >= 2.4.0.1 && <= 2.5
+    , hspec-expectations
   exposed-modules:
       Test.Hspec
-    , Test.Hspec.Core
-    , Test.Hspec.Monadic
-    , Test.Hspec.Runner
-    , Test.Hspec.Formatters
-    , Test.Hspec.HUnit
-    , Test.Hspec.QuickCheck
+      Test.Hspec.Core
+      Test.Hspec.Monadic
+      Test.Hspec.Runner
+      Test.Hspec.Formatters
+      Test.Hspec.HUnit
+      Test.Hspec.QuickCheck
   other-modules:
       Test.Hspec.Pending
       Test.Hspec.Internal
@@ -69,8 +69,8 @@
     , transformers >= 0.2.0 && < 0.4.0
     , HUnit >= 1 && <= 2
     , QuickCheck >= 2.4.0.1 && <= 2.5
-    , hspec-shouldbe
-    , hspec-discover
+    , hspec-expectations
+    , hspec-meta
 
 test-suite doctests
   main-is:
@@ -112,3 +112,61 @@
       base
     , hspec
     , HUnit
+
+-- hspec-discover
+executable hspec-discover
+  ghc-options:
+      -Wall
+  hs-source-dirs:
+      hspec-discover/src
+  main-is:
+      Main.hs
+  other-modules:
+      Run
+  build-depends:
+      base >= 4 && <= 5
+    , filepath
+    , directory
+
+test-suite hspec-discover-spec
+  type:
+      exitcode-stdio-1.0
+  ghc-options:
+      -Wall -Werror
+  hs-source-dirs:
+      hspec-discover/src
+    , hspec-discover/test
+  main-is:
+      Spec.hs
+  build-depends:
+      base >= 4 && <= 5
+    , filepath
+    , directory
+    , hspec-meta
+
+test-suite hspec-discover-example
+  type:
+      exitcode-stdio-1.0
+  ghc-options:
+      -Wall -Werror
+  hs-source-dirs:
+      hspec-discover/example
+  main-is:
+      Spec.hs
+  build-depends:
+      base >= 4 && <= 5
+    , hspec
+    , QuickCheck
+
+test-suite hspec-discover-integration-test-empty
+  type:
+      exitcode-stdio-1.0
+  ghc-options:
+      -Wall -Werror
+  hs-source-dirs:
+      hspec-discover/integration-test/empty
+  main-is:
+      Spec.hs
+  build-depends:
+      base >= 4 && <= 5
+    , hspec
diff --git a/src/Test/Hspec.hs b/src/Test/Hspec.hs
--- a/src/Test/Hspec.hs
+++ b/src/Test/Hspec.hs
@@ -1,59 +1,42 @@
 {-# OPTIONS_HADDOCK prune #-}
 -- |
--- Hspec is a Behaviour-Driven Development tool for Haskell programmers. BDD is
--- an approach to software development that combines Test-Driven Development,
--- Domain Driven Design, and Acceptance Test-Driven Planning. Hspec helps you
--- do the TDD part of that equation, focusing on the documentation and design
--- aspects of TDD.
+-- Hspec is a framework for /Behavior-Driven Development (BDD)/ in Haskell. BDD
+-- is an approach to software development that combines Test-Driven
+-- Development, Domain-Driven Design, and Acceptance Test-Driven Planning.
+-- Hspec helps you do the TDD part of that equation, focusing on the
+-- documentation and design aspects of TDD.
 --
 -- Hspec (and the preceding intro) are based on the Ruby library RSpec. Much of
 -- what applies to RSpec also applies to Hspec. Hspec ties together
 -- /descriptions/ of behavior and /examples/ of that behavior. The examples can
--- also be run as tests and the output summarises what needs to be implemented.
---
--- NOTE: There is a monadic and a non-monadic API.  This is the documentation
--- for the non-monadic API.  The monadic API is more stable, so you may prefer
--- it over this one.  For documentation on the monadic API look at
--- "Test.Hspec.Monadic".
-
-module Test.Hspec {-# WARNING "This module will re-export Test.Hspec.Monadic in the future.  Either use Test.Hspec.Core as a drop-in replacement, or migrate your code to the monadic API!" #-} (
+-- also be run as tests and the output summarizes what needs to be implemented.
+module Test.Hspec (
 
 -- * Introduction
 -- $intro
 
 -- * Types
   Spec
-, Specs
 , Example
 , Pending
 
+-- * Setting expectations
+, module Test.Hspec.Expectations
+
 -- * Defining a spec
 , describe
+, context
 , it
 , pending
 
 -- * Running a spec
 , hspec
-, hspecB
-, hHspec
-, Summary (..)
-
-
-
-
-
--- deprecated functions
-, descriptions
-, hspecX
-
-
-
 ) where
 
-import           Test.Hspec.Core
-
-
-
+import           Test.Hspec.Monadic
+import           Test.Hspec.HUnit ()
+import           Test.Hspec.QuickCheck ()
+import           Test.Hspec.Expectations
 
 -- $intro
 --
@@ -62,12 +45,11 @@
 -- the specs for them.
 --
 -- > import Test.Hspec
--- > import Test.Hspec.QuickCheck
--- > import Test.Hspec.HUnit ()
 -- > import Test.QuickCheck
 -- > import Test.HUnit
 -- >
--- > main = hspec mySpecs
+-- > main :: IO ()
+-- > main = hspec spec
 --
 -- Since the specs are often used to tell you what to implement, it's best to
 -- start with undefined functions. Once we have some specs, then you can
@@ -75,53 +57,42 @@
 -- and there is no undocumented behavior.
 --
 -- > unformatPhoneNumber :: String -> String
--- > unformatPhoneNumber number = undefined
+-- > unformatPhoneNumber = undefined
 -- >
 -- > formatPhoneNumber :: String -> String
--- > formatPhoneNumber number = undefined
+-- > formatPhoneNumber = undefined
 --
 -- The 'describe' function takes a list of behaviors and examples bound
 -- together with the 'it' function
 --
--- > mySpecs = [describe "unformatPhoneNumber" [
+-- > spec :: Spec
+-- > spec = do
+-- >   describe "unformatPhoneNumber" $ do
 --
--- A boolean expression can act as a behavior's example.
+-- A `Bool` can be used as an example.
 --
--- >   it "removes dashes, spaces, and parenthesies" $
--- >     unformatPhoneNumber "(555) 555-1234" == "5555551234"
--- >   ,
+-- >     it "removes dashes, spaces, and parenthesies" $
+-- >       unformatPhoneNumber "(555) 555-1234" == "5555551234"
 --
+--
 -- The 'pending' function marks a behavior as pending an example. The example
 -- doesn't count as failing.
 --
--- >   it "handles non-US phone numbers" $
--- >     pending "need to look up how other cultures format phone numbers"
--- >   ,
+-- >     it "handles non-US phone numbers" $
+-- >       pending "need to look up how other cultures format phone numbers"
 --
--- An HUnit 'Test.HUnit.Test' can act as a behavior's example. (must import
--- "Test.Hspec.HUnit")
+-- An HUnit 'Test.HUnit.Lang.Assertion' can be used as an example.
 --
--- >   it "removes the \"ext\" prefix of the extension" $ TestCase $ do
--- >     let expected = "5555551234135"
--- >         actual   = unformatPhoneNumber "(555) 555-1234 ext 135"
--- >     expected @?= actual
--- >   ,
+-- >     it "converts letters to numbers" $ do
+-- >       let expected = "6862377"
+-- >           actual   = unformatPhoneNumber "NUMBERS"
+-- >       actual @?= expected
 --
--- An @IO()@ action is treated like an HUnit 'TestCase'. (must import
--- "Test.Hspec.HUnit")
 --
--- >   it "converts letters to numbers" $ do
--- >     let expected = "6862377"
--- >         actual   = unformatPhoneNumber "NUMBERS"
--- >     actual @?= expected
--- >   ,
---
--- The 'property' function allows a QuickCheck property to act as an example.
--- (must import "Test.Hspec.QuickCheck")
+-- A QuickCheck 'Test.QuickCheck.Property' can be used as an example.
 --
--- >   it "can add and remove formatting without changing the number" $ property $
--- >     forAll phoneNumber $ \n -> unformatPhoneNumber (formatPhoneNumber n) == n
--- >   ]]
+-- >     it "can add and remove formatting without changing the number" $ property $
+-- >       forAll phoneNumber $ \n -> unformatPhoneNumber (formatPhoneNumber n) == n
 -- >
 -- > phoneNumber :: Gen String
 -- > phoneNumber = do
diff --git a/src/Test/Hspec/Core.hs b/src/Test/Hspec/Core.hs
--- a/src/Test/Hspec/Core.hs
+++ b/src/Test/Hspec/Core.hs
@@ -1,21 +1,9 @@
 {-# OPTIONS_HADDOCK prune #-}
 -- |
--- Hspec is a Behaviour-Driven Development tool for Haskell programmers. BDD is
--- an approach to software development that combines Test-Driven Development,
--- Domain Driven Design, and Acceptance Test-Driven Planning. Hspec helps you
--- do the TDD part of that equation, focusing on the documentation and design
--- aspects of TDD.
---
--- Hspec (and the preceding intro) are based on the Ruby library RSpec. Much of
--- what applies to RSpec also applies to Hspec. Hspec ties together
--- /descriptions/ of behavior and /examples/ of that behavior. The examples can
--- also be run as tests and the output summarises what needs to be implemented.
---
 -- NOTE: There is a monadic and a non-monadic API.  This is the documentation
 -- for the non-monadic API.  The monadic API is more stable, so you may prefer
 -- it over this one.  For documentation on the monadic API look at
--- "Test.Hspec.Monadic".
-
+-- "Test.Hspec".
 module Test.Hspec.Core (
 
 
@@ -68,7 +56,8 @@
 -- > import Test.QuickCheck
 -- > import Test.HUnit
 -- >
--- > main = hspec mySpecs
+-- > main :: IO ()
+-- > main = hspec spec
 --
 -- Since the specs are often used to tell you what to implement, it's best to
 -- start with undefined functions. Once we have some specs, then you can
@@ -84,7 +73,7 @@
 -- The 'describe' function takes a list of behaviors and examples bound
 -- together with the 'it' function
 --
--- > mySpecs = [describe "unformatPhoneNumber" [
+-- > spec = [describe "unformatPhoneNumber" [
 --
 -- A boolean expression can act as a behavior's example.
 --
diff --git a/src/Test/Hspec/Internal.hs b/src/Test/Hspec/Internal.hs
--- a/src/Test/Hspec/Internal.hs
+++ b/src/Test/Hspec/Internal.hs
@@ -54,12 +54,6 @@
 it requirement = SpecExample requirement . evaluateExample
 
 -- | A type class for examples.
---
--- To use an HUnit `Test.HUnit.Test` or an `Test.HUnit.Assertion` as an example
--- you need to import "Test.Hspec.HUnit".
---
--- To use a QuickCheck `Test.QuickCheck.Property` as an example you need to
--- import "Test.Hspec.QuickCheck".
 class Example a where
   evaluateExample :: a -> IO Result
 
diff --git a/src/Test/Hspec/Monadic.hs b/src/Test/Hspec/Monadic.hs
--- a/src/Test/Hspec/Monadic.hs
+++ b/src/Test/Hspec/Monadic.hs
@@ -1,20 +1,7 @@
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 {-# OPTIONS_HADDOCK prune #-}
 {-# OPTIONS_GHC -fno-warn-deprecations #-}
--- |
--- Hspec is a Behaviour-Driven Development tool for Haskell programmers. BDD is
--- an approach to software development that combines Test-Driven Development,
--- Domain Driven Design, and Acceptance Test-Driven Planning. Hspec helps you
--- do the TDD part of that equation, focusing on the documentation and design
--- aspects of TDD.
---
--- Hspec (and the preceding intro) are based on the Ruby library RSpec. Much of
--- what applies to RSpec also applies to Hspec. Hspec ties together
--- /descriptions/ of behavior and /examples/ of that behavior. The examples can
--- also be run as tests and the output summarises what needs to be implemented.
 module Test.Hspec.Monadic (
--- * Introduction
--- $intro
 -- * Types
   Spec
 , Example
@@ -52,78 +39,6 @@
 
 import           Control.Monad.Trans.Writer (Writer, execWriter, tell)
 
--- $intro
---
--- The three functions you'll use the most are 'hspec', 'describe', and 'it'.
--- Here is an example of functions that format and unformat phone numbers and
--- the specs for them.
---
--- > import Test.Hspec.Monadic
--- > import Test.Hspec.QuickCheck
--- > import Test.Hspec.HUnit ()
--- > import Test.QuickCheck
--- > import Test.HUnit
--- >
--- > main = hspec mySpecs
---
--- Since the specs are often used to tell you what to implement, it's best to
--- start with undefined functions. Once we have some specs, then you can
--- implement each behavior one at a time, ensuring that each behavior is met
--- and there is no undocumented behavior.
---
--- > unformatPhoneNumber :: String -> String
--- > unformatPhoneNumber number = undefined
--- >
--- > formatPhoneNumber :: String -> String
--- > formatPhoneNumber number = undefined
---
--- The 'describe' function takes a list of behaviors and examples bound
--- together with the 'it' function
---
--- > mySpecs = describe "unformatPhoneNumber" $ do
---
--- A boolean expression can act as a behavior's example.
---
--- >   it "removes dashes, spaces, and parenthesies" $
--- >     unformatPhoneNumber "(555) 555-1234" == "5555551234"
---
---
--- The 'pending' function marks a behavior as pending an example. The example
--- doesn't count as failing.
---
--- >   it "handles non-US phone numbers" $
--- >     pending "need to look up how other cultures format phone numbers"
---
---
--- An HUnit 'Test.HUnit.Test' can act as a behavior's example. (must import
--- "Test.Hspec.HUnit")
---
--- >   it "removes the \"ext\" prefix of the extension" $ TestCase $ do
--- >     let expected = "5555551234135"
--- >         actual   = unformatPhoneNumber "(555) 555-1234 ext 135"
--- >     expected @?= actual
---
---
--- An @IO()@ action is treated like an HUnit 'TestCase'. (must import
--- "Test.Hspec.HUnit")
---
--- >   it "converts letters to numbers" $ do
--- >     let expected = "6862377"
--- >         actual   = unformatPhoneNumber "NUMBERS"
--- >     actual @?= expected
---
---
--- The 'property' function allows a QuickCheck property to act as an example.
--- (must import "Test.Hspec.QuickCheck")
---
--- >   it "can add and remove formatting without changing the number" $ property $
--- >     forAll phoneNumber $ \n -> unformatPhoneNumber (formatPhoneNumber n) == n
--- >
--- > phoneNumber :: Gen String
--- > phoneNumber = do
--- >   n <- elements [7,10,11,12,13,14,15]
--- >   vectorOf n (elements "0123456789")
---
 
 type Spec = SpecM ()
 
diff --git a/test/Spec.hs b/test/Spec.hs
--- a/test/Spec.hs
+++ b/test/Spec.hs
@@ -1,1 +1,1 @@
-{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
+{-# OPTIONS_GHC -F -pgmF hspec-meta-discover #-}
