diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,9 @@
 # Revision history for staversion
 
+## 0.1.2.0  -- 2016-11-10
+
+* New option `--hackage`, which searches hackage for the latest version number.
+
 ## 0.1.1.0  -- 2016-11-03
 
 * Now staversion fetches build plan YAML files over network, if necessary.
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
 
 ![travis status](https://api.travis-ci.org/debug-ito/staversion.png)
 
-staversion is a command-line tool to look for version numbers for Haskell packages in specific stackage resolvers. It answers to questions like "What version is the package X in stackage lts-Y.ZZ?" It aims to make it easier to write `build-depends` section in YOUR_PACKAGE.cabal.
+staversion is a command-line tool to look for version numbers of Haskell packages. It mainly focuses on package versions in stackage, i.e. it answers to questions like "What version is the package X in stackage lts-Y.ZZ?" It aims to make it easier to write `build-depends` section in YOUR_PACKAGE.cabal.
 
     $ staversion --resolver lts-4.2 conduit
     ------ lts-4.2
@@ -15,21 +15,29 @@
     ------ lts-7.0
     conduit ==1.2.7
     
-    $ staversion --resolver lts-4.2 --resolver lts-7.0 conduit base
+    $ staversion --resolver lts-4.2 --resolver lts-6 conduit base
     ------ lts-4.2
     conduit ==1.2.6.1,
     base ==4.8.2.0
     
-    ------ lts-7.0
-    conduit ==1.2.7,
-    base ==4.9.0.0
+    ------ lts-6
+    conduit ==1.2.8,
+    base ==4.8.2.0
 
 staversion first reads build plan YAML files that are stored locally in your computer, then it tries to fetch them over network.
 
+You can also look up the latest version numbers hosted on hackage.
 
+    $ staversion --hackage conduit base
+    ------ latest in hackage
+    conduit ==1.2.8,
+    base ==4.9.0.0
+
+See `--help` message for detail.
+
+
 ## TODO
 
-- Search for the latest version numbers hosted in hackage.
 - Read `build-depends` sections .cabal files for package name queries.
 - Show version number ranges supported by the given resolvers.
 - Cache build plans in some local storage (SQLite?)
diff --git a/src/Staversion/Internal/BuildPlan.hs b/src/Staversion/Internal/BuildPlan.hs
--- a/src/Staversion/Internal/BuildPlan.hs
+++ b/src/Staversion/Internal/BuildPlan.hs
@@ -4,6 +4,7 @@
 -- Maintainer: Toshio Ito <debug.ito@gmail.com>
 --
 -- __This is an internal module. End-users should not use it.__
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
 module Staversion.Internal.BuildPlan
        ( -- * Entry APIs
          BuildPlan,
@@ -13,7 +14,6 @@
          loadBuildPlan,
          -- * Low-level APIs
          loadBuildPlanYAML,
-         parseVersionText,
          -- * For tests
          _setDisambiguator
        ) where
@@ -22,22 +22,21 @@
 import Control.Exception (throwIO, catchJust, IOException, catch)
 import Control.Monad.Trans.Except (runExceptT, ExceptT(..))
 import Control.Monad.IO.Class (liftIO)
+import Control.Monad (mapM)
 import Data.Aeson (FromJSON(..), (.:), Value(..), Object)
 import Data.ByteString (ByteString)
 import qualified Data.ByteString as BS
 import qualified Data.ByteString.Lazy as BSL
 import qualified Data.HashMap.Strict as HM
 import Data.IORef (IORef, newIORef, readIORef, writeIORef)
-import Data.Maybe (listToMaybe)
-import Data.Monoid ((<>))
+import Data.Monoid (Monoid, (<>), mconcat)
 import Data.Text (Text, unpack)
 import Data.Traversable (Traversable(traverse))
-import Data.Version (Version, parseVersion)
+import Data.Version (Version)
 import qualified Data.Yaml as Yaml
 import System.FilePath ((</>), (<.>))
 import qualified System.IO.Error as IOE
 import Text.Read (readMaybe)
-import Text.ParserCombinators.ReadP (readP_to_S)
 
 import Staversion.Internal.Log
   ( Logger, logDebug, logWarn
@@ -47,6 +46,10 @@
  ( PackageName, PackageSource(..),
    ErrorMsg, Resolver
  )
+import Staversion.Internal.BuildPlan.Hackage
+  ( RegisteredVersions, latestVersion,
+    fetchPreferredVersions
+  )
 import Staversion.Internal.BuildPlan.Stackage
   ( Disambiguator,
     fetchDisambiguator,
@@ -55,25 +58,25 @@
     PartialResolver(..), ExactResolver,
     fetchBuildPlanYAML
   )
+import Staversion.Internal.BuildPlan.Version (unVersionJSON)
 
 -- | A data structure that keeps a map between package names and their
 -- versions.
-newtype BuildPlan = BuildPlan (HM.HashMap PackageName Version)
+newtype BuildPlan = BuildPlan (HM.HashMap PackageName Version) deriving (Monoid)
 
 instance FromJSON BuildPlan where
   parseJSON (Object object) = (\p1 p2 -> BuildPlan $ p1 <> p2) <$> core_packages <*> other_packages where
     core_packages = parseSysInfo =<< (object .: "system-info")
     parseSysInfo (Object o) = parseCorePackages =<< (o .: "core-packages")
     parseSysInfo _ = empty
-    parseCorePackages (Object o) = traverse (\v -> versionParser =<< parseJSON v) o
+    parseCorePackages (Object o) = traverse (\v -> unVersionJSON <$> parseJSON v) o
     parseCorePackages _ = empty
 
     other_packages = parsePackages =<< (object .: "packages")
     parsePackages (Object o) = traverse parsePackageObject o
     parsePackages _ = empty
-    parsePackageObject (Object o) = versionParser =<< (o .: "version")
+    parsePackageObject (Object o) = unVersionJSON <$> (o .: "version")
     parsePackageObject _ = empty
-    versionParser = maybe empty return . parseVersionText
   parseJSON _ = empty
 
 -- | Stateful manager for 'BuildPlan's.
@@ -117,18 +120,31 @@
 maybeToLoadM :: ErrorMsg -> Maybe a -> LoadM a
 maybeToLoadM msg = ExceptT . return . maybe (Left msg) Right
 
+httpManagerM :: BuildPlanManager -> LoadM Manager
+httpManagerM = maybeToLoadM "It is not allowed to access network." . manHttpManager
+
 httpExceptionToLoadM :: String -> LoadM a -> LoadM a
 httpExceptionToLoadM context action = ExceptT $ (runExceptT action) `catch` handler where
   handler :: OurHttpException -> IO (Either ErrorMsg a)
   handler e = return $ Left (context ++ ": " ++ show e)
 
-loadBuildPlan :: BuildPlanManager -> PackageSource -> IO (Either ErrorMsg BuildPlan)
-loadBuildPlan man (SourceStackage resolver) = runExceptT impl where
+loadBuildPlan :: BuildPlanManager
+              -> [PackageName] -- ^ package names whose versions the user is interested in.
+              -> PackageSource -> IO (Either ErrorMsg BuildPlan)
+loadBuildPlan man _ (SourceStackage resolver) = runExceptT impl where
   impl = loadBuildPlan_stackageLocalFile man resolver `loggedElse'` do
     e_resolver <- tryDisambiguate man =<< getPresolver
     loadBuildPlan_stackageLocalFile man (formatResolverString $ PartialExact e_resolver) `loggedElse'` loadBuildPlan_stackageNetwork man e_resolver
   getPresolver = maybeToLoadM ("Invalid resolver format for stackage.org: " ++ resolver) $ parseResolverString resolver
   loggedElse' = loggedElse $ manLogger man
+loadBuildPlan man names SourceHackage = runExceptT impl where
+  impl = do
+    http_man <- httpManagerM man
+    (mconcat . zipWith registeredVersionToBuildPlan names) <$> mapM (doFetch http_man) names
+  logDebug' msg = liftIO $ logDebug (manLogger man) msg
+  doFetch http_man name = do
+    logDebug' ("Ask hackage for the latest version of " ++ unpack name)
+    ExceptT $ fetchPreferredVersions http_man name
 
 loadBuildPlan_stackageLocalFile :: BuildPlanManager -> Resolver -> LoadM BuildPlan
 loadBuildPlan_stackageLocalFile man resolver = ExceptT $ catchJust handleIOError doLoad (return . Left) where
@@ -153,7 +169,7 @@
     case m_disam of
      Just d -> return d
      Nothing -> do
-       http_man <- maybeToLoadM "It is not allowed to access network." $ manHttpManager bp_man
+       http_man <- httpManagerM bp_man
        logDebug' "Fetch resolver disambiguator from network..."
        got_d <- ExceptT $ fetchDisambiguator http_man
        logDebug' "Successfully fetched resolver disambiguator."
@@ -163,7 +179,7 @@
   
 loadBuildPlan_stackageNetwork :: BuildPlanManager -> ExactResolver -> LoadM BuildPlan
 loadBuildPlan_stackageNetwork man e_resolver = do
-  http_man <- maybeToLoadM "It is not allowed to access network." $ manHttpManager man
+  http_man <- httpManagerM man
   liftIO $ logDebug (manLogger man) ("Fetch build plan from network: resolver = " ++ show e_resolver)
   yaml_data <- httpExceptionToLoadM ("Downloading build plan failed: " ++ show e_resolver) $ liftIO $ fetchBuildPlanYAML http_man e_resolver
   ExceptT $ return $ parseBuildPlanYAML $ BSL.toStrict yaml_data
@@ -179,11 +195,11 @@
 packageVersion :: BuildPlan -> PackageName -> Maybe Version
 packageVersion (BuildPlan bp_map) name = HM.lookup name bp_map
 
--- | Parse a version text. There must not be any trailing characters
--- after a valid version text.
-parseVersionText :: Text -> Maybe Version
-parseVersionText = extractResult . (readP_to_S parseVersion) . unpack where
-  extractResult = listToMaybe . map fst . filter (\pair -> snd pair == "")
-
 _setDisambiguator :: BuildPlanManager -> Maybe Disambiguator -> IO ()
 _setDisambiguator bp_man = writeIORef (manDisambiguator bp_man)
+
+registeredVersionToBuildPlan :: PackageName -> RegisteredVersions -> BuildPlan
+registeredVersionToBuildPlan name rvers = BuildPlan $ HM.fromList $ pairs where
+  pairs = case latestVersion rvers of
+    Nothing -> []
+    Just v -> [(name, v)]
diff --git a/src/Staversion/Internal/BuildPlan/Hackage.hs b/src/Staversion/Internal/BuildPlan/Hackage.hs
new file mode 100644
--- /dev/null
+++ b/src/Staversion/Internal/BuildPlan/Hackage.hs
@@ -0,0 +1,51 @@
+-- |
+-- Module: Staversion.Internal.BuildPlan.Hackage
+-- Description: (virtual) BuildPlan expressing the latest Hackage
+-- Maintainer: Toshio Ito <debug.ito@gmail.com>
+--
+-- __This is an internal module. End-users should not use it.__
+module Staversion.Internal.BuildPlan.Hackage
+       ( -- * entry API
+         RegisteredVersions,
+         fetchPreferredVersions,
+         latestVersion,
+         -- * low-level API
+         parsePreferredVersionsJSON
+       ) where
+
+import Control.Applicative ((<$>), empty)
+import qualified Control.Exception as Exception
+import Data.Aeson (FromJSON(..), Value(..), (.:), eitherDecode)
+import qualified Data.ByteString.Lazy as BSL
+import Data.List (sort, reverse)
+import Data.Text (unpack)
+import Data.Version (Version)
+
+import Staversion.Internal.BuildPlan.Version (unVersionJSON)
+import Staversion.Internal.Query (ErrorMsg, PackageName)
+import Staversion.Internal.HTTP (Manager, fetchURL, OurHttpException)
+
+data RegisteredVersions = RegisteredVersions { regPreferredVersions :: [Version]
+                                               -- ^ Sorted list of preferred versions of the package.
+                                               -- The head is the latest.
+                                             }
+                          deriving (Show,Eq,Ord)
+
+instance FromJSON RegisteredVersions where
+  parseJSON (Object o) = (RegisteredVersions . reverse . sort . map unVersionJSON) <$> (o .: "normal-version")
+  parseJSON _ = empty
+
+parsePreferredVersionsJSON :: BSL.ByteString -> Either ErrorMsg RegisteredVersions
+parsePreferredVersionsJSON = either (\e -> Left ("Decoding preferred versions error: " ++ e)) Right . eitherDecode
+
+latestVersion :: RegisteredVersions -> Maybe Version
+latestVersion rvers = case regPreferredVersions rvers of
+  [] -> Nothing
+  (v : _) -> Just v
+
+fetchPreferredVersions :: Manager -> PackageName -> IO (Either ErrorMsg RegisteredVersions)
+fetchPreferredVersions man text_name = Exception.handle handler $ parsePreferredVersionsJSON <$> fetchURL man url where
+  name = unpack text_name
+  url = "http://hackage.haskell.org/package/" ++ name ++ "/preferred.json"
+  handler :: OurHttpException -> IO (Either ErrorMsg a)
+  handler e = return $ Left ("HTTP error while fetching versions of " ++ name ++ " in hackage: " ++ show e)
diff --git a/src/Staversion/Internal/BuildPlan/Version.hs b/src/Staversion/Internal/BuildPlan/Version.hs
new file mode 100644
--- /dev/null
+++ b/src/Staversion/Internal/BuildPlan/Version.hs
@@ -0,0 +1,30 @@
+-- |
+-- Module: Staversion.Internal.BuildPlan.Version
+-- Description: parsing Version
+-- Maintainer: Toshio Ito <debug.ito@gmail.com>
+--
+-- __This is an internal module. End-users should not use it.__
+module Staversion.Internal.BuildPlan.Version
+       ( parseVersionText,
+         VersionJSON(..)
+       ) where
+
+import Control.Applicative (empty, pure)
+import Data.Aeson (FromJSON(..), Value(..))
+import Data.Maybe (listToMaybe)
+import Data.Text (Text, unpack)
+import Data.Version (Version, parseVersion)
+import Text.ParserCombinators.ReadP (readP_to_S)
+
+-- | Parse a version text. There must not be any trailing characters
+-- after a valid version text.
+parseVersionText :: Text -> Maybe Version
+parseVersionText = extractResult . (readP_to_S parseVersion) . unpack where
+  extractResult = listToMaybe . map fst . filter (\pair -> snd pair == "")
+
+-- | a wrapper around 'Version' for JSON I/F
+newtype VersionJSON = VersionJSON { unVersionJSON :: Version } deriving (Show,Eq,Ord)
+
+instance FromJSON VersionJSON where
+  parseJSON (String t) = maybe empty pure $ fmap VersionJSON $ parseVersionText t
+  parseJSON _ = empty
diff --git a/src/Staversion/Internal/Command.hs b/src/Staversion/Internal/Command.hs
--- a/src/Staversion/Internal/Command.hs
+++ b/src/Staversion/Internal/Command.hs
@@ -9,7 +9,7 @@
          parseCommandArgs
        ) where
 
-import Control.Applicative ((<$>), (<*>), optional, some)
+import Control.Applicative ((<$>), (<*>), optional, some, (<|>))
 import Data.Monoid (mconcat)
 import Data.Text (pack)
 import Data.Version (showVersion)
@@ -64,19 +64,23 @@
                                     ]
   build_plan_dir = Opt.strOption
                    $ mconcat [ Opt.long "build-plan-dir",
-                               Opt.help ( "Directory where build plan YAML files are stored. Default: "
-                                          ++ defBuildPlanDir def_comm
-                                        ),
+                               Opt.help "Directory where build plan YAML files are stored.",
                                Opt.metavar "DIR",
-                               Opt.value (defBuildPlanDir def_comm)
+                               Opt.value (defBuildPlanDir def_comm),
+                               Opt.showDefault
                              ]
-  sources = some $ SourceStackage <$> resolver
-  resolver = Opt.strOption
+  sources = some $ resolver <|> hackage
+  resolver = fmap SourceStackage $ Opt.strOption
              $ mconcat [ Opt.long "resolver",
                          Opt.short 'r',
                          Opt.help "Stackage resolver to search. e.g. \"lts-6.15\"",
                          Opt.metavar "RESOLVER_NAME"
                        ]
+  hackage = Opt.flag' SourceHackage
+            $ mconcat [ Opt.long "hackage",
+                        Opt.short 'H',
+                        Opt.help "Search hackage.org for the latest version."
+                      ]
   queries = some $ QueryName <$> package
   package = fmap pack $ Opt.strArgument
             $ mconcat [ Opt.help "Name of package whose version you want to check.",
diff --git a/src/Staversion/Internal/Exec.hs b/src/Staversion/Internal/Exec.hs
--- a/src/Staversion/Internal/Exec.hs
+++ b/src/Staversion/Internal/Exec.hs
@@ -11,7 +11,7 @@
 
 import Control.Applicative ((<$>))
 import Data.Function (on)
-import Data.List (groupBy)
+import Data.List (groupBy, nub)
 import Data.Text (unpack)
 import qualified Data.Text.Lazy.IO as TLIO
 
@@ -25,7 +25,7 @@
 import Staversion.Internal.Format (formatResultsCabal)
 import Staversion.Internal.Log (logDebug, logError)
 import Staversion.Internal.Query
-  ( Query(..), Result(..), PackageSource(..),
+  ( Query(..), Result(..), PackageSource(..), PackageName,
     resultVersionsFromList, ResultVersions,
     ErrorMsg
   )
@@ -42,8 +42,9 @@
     fmap concat $ mapM (processQueriesIn bp_man) $ commSources comm
   logger = commLogger comm
   processQueriesIn bp_man source = do
+    queried_names <- fmap (nub . concat) $ mapM getQueriedPackageNames $ commQueries comm
     logDebug logger ("Retrieve package source " ++ show source)
-    e_build_plan <- loadBuildPlan bp_man source
+    e_build_plan <- loadBuildPlan bp_man queried_names source
     logBuildPlanResult e_build_plan
     return $ map (makeResult source e_build_plan) $ commQueries comm
   makeResult source e_build_plan query = case e_build_plan of
@@ -57,3 +58,6 @@
 searchVersions :: BuildPlan -> Query -> ResultVersions
 searchVersions build_plan (QueryName package_name) =
   resultVersionsFromList [(package_name, packageVersion build_plan package_name)]
+
+getQueriedPackageNames :: Query -> IO [PackageName]
+getQueriedPackageNames (QueryName n) = return [n]
diff --git a/src/Staversion/Internal/Query.hs b/src/Staversion/Internal/Query.hs
--- a/src/Staversion/Internal/Query.hs
+++ b/src/Staversion/Internal/Query.hs
@@ -28,6 +28,7 @@
 
 -- | Source of packages.
 data PackageSource = SourceStackage Resolver -- ^ stackage.
+                   | SourceHackage -- ^ hackage (latest)
                    deriving (Show,Eq,Ord)
 
 -- | Query for package version(s).
@@ -56,3 +57,4 @@
 -- | description of a 'PackageSource'.
 sourceDesc :: PackageSource -> Text
 sourceDesc (SourceStackage r) = pack r
+sourceDesc SourceHackage = "latest in hackage"
diff --git a/staversion.cabal b/staversion.cabal
--- a/staversion.cabal
+++ b/staversion.cabal
@@ -1,5 +1,5 @@
 name:                   staversion
-version:                0.1.1.0
+version:                0.1.2.0
 author:                 Toshio Ito <debug.ito@gmail.com>
 maintainer:             Toshio Ito <debug.ito@gmail.com>
 license:                BSD3
@@ -15,7 +15,8 @@
                         test/data/lts-7.0_conpact.yaml,
                         test/data/lts-4.2.yaml,
                         test/data/lts-2.22_conpact.yaml,
-                        test/data/snapshots.json
+                        test/data/snapshots.json,
+                        test/data/aeson_preferred.json
                         
 homepage:               https://github.com/debug-ito/staversion
 bug-reports:            https://github.com/debug-ito/staversion/issues
@@ -25,9 +26,11 @@
   hs-source-dirs:       src
   ghc-options:          -Wall -fno-warn-unused-imports
   default-extensions:   OverloadedStrings
-  other-extensions:     CPP, DeriveDataTypeable
+  other-extensions:     CPP, DeriveDataTypeable, GeneralizedNewtypeDeriving
   exposed-modules:      Staversion.Internal.BuildPlan,
                         Staversion.Internal.BuildPlan.Stackage,
+                        Staversion.Internal.BuildPlan.Hackage,
+                        Staversion.Internal.BuildPlan.Version,
                         Staversion.Internal.Query,
                         Staversion.Internal.Command,
                         Staversion.Internal.Log,
@@ -71,6 +74,8 @@
   -- other-extensions:     
   other-modules:        Staversion.Internal.BuildPlanSpec,
                         Staversion.Internal.BuildPlan.StackageSpec,
+                        Staversion.Internal.BuildPlan.HackageSpec,
+                        Staversion.Internal.BuildPlan.VersionSpec,
                         Staversion.Internal.ExecSpec,
                         Staversion.Internal.FormatSpec,
                         Staversion.Internal.TestUtil
diff --git a/test/NetworkTest.hs b/test/NetworkTest.hs
--- a/test/NetworkTest.hs
+++ b/test/NetworkTest.hs
@@ -1,5 +1,6 @@
 module Main (main,spec) where
 
+import Control.Applicative ((<$>))
 import qualified Data.ByteString.Lazy as BSL
 import Network.HTTP.Client (newManager, Manager)
 import Network.HTTP.Client.TLS (tlsManagerSettings)
@@ -13,13 +14,19 @@
     loadBuildPlan,
     packageVersion
   )
+import Staversion.Internal.BuildPlan.Hackage (fetchPreferredVersions, latestVersion)
 import Staversion.Internal.BuildPlan.Stackage
   ( fetchDisambiguator,
     fetchBuildPlanYAML,
     PartialResolver(..), ExactResolver(..)
   )
+import Staversion.Internal.Command (Command(..))
+import Staversion.Internal.Exec (processCommand)
 import Staversion.Internal.Log (defaultLogger, Logger(loggerThreshold))
-import Staversion.Internal.Query (PackageSource(..))
+import Staversion.Internal.Query
+ ( PackageSource(..), ErrorMsg, Query(..), Result(..),
+   resultVersionsToList
+ )
 
 main :: IO ()
 main = hspec spec
@@ -28,6 +35,8 @@
 spec = do
   spec_Stackage
   spec_BuildPlan
+  spec_Hackage
+  spec_Exec
 
 spec_Stackage:: Spec
 spec_Stackage = describe "BuildPlan.Stackage" $ beforeAll makeManager $ do
@@ -48,15 +57,56 @@
 makeManager :: IO Manager
 makeManager = newManager tlsManagerSettings
 
+quietLogger :: Logger
+quietLogger = defaultLogger { loggerThreshold = Nothing }
+
+expectRight :: String -> Either ErrorMsg a -> IO a
+expectRight msg_head = either (\err -> error $ msg_head ++ err) return
+
+isJustAnd :: Maybe a -> (a -> Bool) -> Bool
+isJustAnd m p = maybe False p m
+
 spec_BuildPlan :: Spec
 spec_BuildPlan = describe "BuildPlan" $ do
   describe "loadBuildPlan from Stackage" $ do
     it "disambiguates LTS version and fetches a valid BuildPlan" $ do
-      let logger = defaultLogger { loggerThreshold = Nothing }
-      bp_man <- newBuildPlanManager "." logger True
-      bp <- loadBuildPlan bp_man (SourceStackage "lts-5") >>= \ret -> case ret of
-        Right bp -> return bp
-        Left error_msg -> error ("loadBuildPlan failed: " ++ error_msg)
+      bp_man <- newBuildPlanManager "." quietLogger True
+      bp <- expectRight "loadBuildPlan failed: " =<< loadBuildPlan bp_man [] (SourceStackage "lts-5")
       packageVersion bp "base" `shouldBe` Just (ver [4,8,2,0])
       packageVersion bp "bytestring" `shouldBe` Just (ver [0,10,6,0])
       packageVersion bp "conduit" `shouldBe` Just (ver [1,2,6,6])
+  describe "loadBuildPlan from Hackage" $ do
+    it "fetches BuildPlan for queried packages" $ do
+      bp_man <- newBuildPlanManager "." quietLogger True
+      bp <- expectRight "loadBuildPlan failed: " =<< loadBuildPlan bp_man ["base", "lens", "transformers"] SourceHackage
+      packageVersion bp "base" `shouldSatisfy` (`isJustAnd` (>= ver [4,9,0,0]))
+      packageVersion bp "lens" `shouldSatisfy` (`isJustAnd` (>= ver [4,15,1]))
+      packageVersion bp "transformers" `shouldSatisfy` (`isJustAnd` (>= ver [0,5,2,0]))
+
+spec_Hackage :: Spec
+spec_Hackage = describe "BuildPlan.Hackage" $ do
+  describe "fetchPreferredVersions" $ do
+    it "fetches a non-empty latestVersion" $ do
+      man <- makeManager
+      ret <- fmap latestVersion <$> fetchPreferredVersions man "http-client"
+      case ret of
+       Right (Just v) -> v `shouldSatisfy` (>= ver [0,5,3,3])
+       _ -> expectationFailure ("Unexpected return: " ++ show ret)
+
+spec_Exec :: Spec
+spec_Exec = describe "Exec" $ describe "processCommand" $ do
+  specify "search hackage" $ do
+    let comm = Command { commBuildPlanDir = ".",
+                         commLogger = quietLogger,
+                         commSources = [SourceHackage],
+                         commQueries = [QueryName "base"],
+                         commAllowNetwork = True
+                       }
+    [ret] <- processCommand comm
+    resultIn ret `shouldBe` SourceHackage
+    resultFor ret `shouldBe` QueryName "base"
+    [(got_name, Just got_version)] <- resultVersionsToList <$> expectRight "processCommand error" (resultVersions ret)
+    got_name `shouldBe` "base"
+    got_version `shouldSatisfy` (>= ver [4,9,0,0]) 
+    
+    
diff --git a/test/Staversion/Internal/BuildPlan/HackageSpec.hs b/test/Staversion/Internal/BuildPlan/HackageSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Staversion/Internal/BuildPlan/HackageSpec.hs
@@ -0,0 +1,22 @@
+module Staversion.Internal.BuildPlan.HackageSpec (main,spec) where
+
+import qualified Data.ByteString.Lazy as BSL
+import System.FilePath ((</>))
+import Test.Hspec
+
+import Staversion.Internal.TestUtil (ver)
+
+import Staversion.Internal.BuildPlan.Hackage
+  ( parsePreferredVersionsJSON,
+    latestVersion
+  )
+
+main :: IO ()
+main = hspec spec
+
+spec :: Spec
+spec = describe "parsePreferredVersionsJSON" $ do
+  it "should parse aeson_preferred.json" $ do
+    yaml_data <- BSL.readFile ("test" </> "data" </> "aeson_preferred.json")
+    rvers <- either (\e -> error ("parse error: " ++ e)) return $ parsePreferredVersionsJSON yaml_data
+    latestVersion rvers `shouldBe` Just (ver [1,0,2,1])
diff --git a/test/Staversion/Internal/BuildPlan/VersionSpec.hs b/test/Staversion/Internal/BuildPlan/VersionSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Staversion/Internal/BuildPlan/VersionSpec.hs
@@ -0,0 +1,21 @@
+module Staversion.Internal.BuildPlan.VersionSpec (main,spec) where
+
+import Data.Text (pack)
+import Data.Version (Version(..))
+import Test.Hspec
+
+import Staversion.Internal.BuildPlan.Version (parseVersionText)
+
+main :: IO ()
+main = hspec spec
+
+spec :: Spec
+spec = parseVersionText_spec
+
+parseVersionText_spec :: Spec
+parseVersionText_spec = describe "parseVersionText" $ do
+  spec_v "0.1.0.6" $ Just (Version [0,1,0,6] [])
+  spec_v "10.11" $ Just (Version [10,11] [])
+  where
+    spec_v input_v expected = specify input_v $ do
+      parseVersionText (pack input_v) `shouldBe` expected
diff --git a/test/Staversion/Internal/BuildPlanSpec.hs b/test/Staversion/Internal/BuildPlanSpec.hs
--- a/test/Staversion/Internal/BuildPlanSpec.hs
+++ b/test/Staversion/Internal/BuildPlanSpec.hs
@@ -11,7 +11,6 @@
   ( BuildPlan, 
     loadBuildPlanYAML, 
     packageVersion,
-    parseVersionText,
     BuildPlanManager,
     newBuildPlanManager,
     _setDisambiguator,
@@ -27,18 +26,9 @@
 
 spec :: Spec
 spec = do
-  parseVersionText_spec
   packageVersion_spec
   loadBuildPlan_spec
 
-parseVersionText_spec :: Spec
-parseVersionText_spec = describe "parseVersionText" $ do
-  spec_v "0.1.0.6" $ Just (Version [0,1,0,6] [])
-  spec_v "10.11" $ Just (Version [10,11] [])
-  where
-    spec_v input_v expected = specify input_v $ do
-      parseVersionText (pack input_v) `shouldBe` expected
-
 packageVersion_spec :: Spec
 packageVersion_spec = describe "packageVersion" $ do
   forBuildPlan "conpact_build_plan" $ \loader -> do
@@ -83,5 +73,5 @@
     let disam (PartialLTSLatest) = Just $ ExactLTS 4 2
         disam _ = Nothing
     bp_man <- mockBuildPlanManager disam
-    bp <- either (\e -> error ("Error: " ++ e)) return =<< loadBuildPlan bp_man (SourceStackage "lts")
+    bp <- either (\e -> error ("Error: " ++ e)) return =<< loadBuildPlan bp_man [] (SourceStackage "lts")
     packageVersion bp "base" `shouldBe` (Just $ Version [4,8,2,0] [])
diff --git a/test/data/aeson_preferred.json b/test/data/aeson_preferred.json
new file mode 100644
--- /dev/null
+++ b/test/data/aeson_preferred.json
@@ -0,0 +1,1 @@
+{"normal-version":["1.0.2.1","1.0.2.0","1.0.1.0","1.0.0.0","0.11.2.1","0.11.2.0","0.11.1.4","0.11.1.3","0.11.1.2","0.11.1.1","0.11.1.0","0.11.0.0","0.9.0.1","0.9.0.0","0.8.1.1","0.8.1.0","0.8.0.2","0.7.0.6","0.7.0.4","0.6.2.1","0.6.2.0","0.6.1.0","0.6.0.2","0.6.0.1","0.6.0.0","0.5.0.0","0.4.0.1","0.4.0.0","0.3.2.14","0.3.2.13","0.3.2.12","0.3.2.11","0.3.2.10","0.3.2.9","0.3.2.8","0.3.2.7","0.3.2.6","0.3.2.5","0.3.2.4","0.3.2.3","0.3.2.2","0.3.2.1","0.3.2.0","0.3.1.1","0.3.1.0","0.3.0.0","0.2.0.0","0.1.0.0"],"deprecated-version":["0.10.0.0","0.8.0.1","0.8.0.0","0.7.0.5","0.7.0.3","0.7.0.2","0.7.0.1","0.7.0.0"]}
