diff --git a/codex.cabal b/codex.cabal
--- a/codex.cabal
+++ b/codex.cabal
@@ -1,5 +1,5 @@
 name:                codex
-version:             0.1.0.0
+version:             0.1.0.1
 synopsis:            A ctags file generator for cabal project dependencies.
 description:         
   This tool download and cache the source code of packages in your local hackage,
@@ -27,23 +27,24 @@
     Codex
     Codex.Project
     Codex.Internal
+    Distribution.Utils
     Distribution.Hackage.Utils
   build-depends:       
-    base >=4.6 && <4.8
-    , bytestring
-    , Cabal >= 1.19
-    , containers
-    , directory
-    , download-curl
-    , either
-    , filepath
-    , hackage-db
-    , MissingH
-    , process
-    , tar
-    , text
-    , transformers
-    , zlib
+      base                >= 4.6.0.1    && < 5
+    , bytestring          >= 0.10.0.2   && < 0.11
+    , Cabal               >= 1.19       && < 1.21
+    , containers          >= 0.5.0.0    && < 0.6
+    , directory           >= 1.2.0.1    && < 1.3
+    , download-curl       >= 0.1.4      && < 0.2
+    , either              >= 4.3.0.1    && < 4.4
+    , filepath            >= 1.3.0.1    && < 1.4
+    , hackage-db          >= 1.6        && < 1.8
+    , MissingH            >= 1.2.1.0    && < 1.3
+    , process             >= 1.1.0.2    && < 1.3
+    , tar                 >= 0.4.0.1    && < 0.5
+    , text                >= 1.1.1.3    && < 1.2
+    , transformers        >= 0.3.0.0    && < 0.5
+    , zlib                >= 0.5.4.1    && < 0.6
 
 executable codex
   default-language:  Haskell2010
@@ -61,7 +62,7 @@
     , filepath
     , hackage-db
     , MissingH
-    , monad-loops
+    , monad-loops         >= 0.4.2      && < 0.5
     , transformers
-    , yaml
-    , codex 
+    , yaml                >= 0.8.8.3    && < 0.9
+    , codex               == 0.1.0.1
diff --git a/src/Codex/Project.hs b/src/Codex/Project.hs
--- a/src/Codex/Project.hs
+++ b/src/Codex/Project.hs
@@ -4,7 +4,6 @@
 import Data.Functor
 import Data.Function
 import Data.Maybe
-import Data.String.Utils
 import Data.Traversable (traverse)
 import Distribution.InstalledPackageInfo
 import Distribution.Hackage.DB (Hackage, readHackage)
@@ -16,6 +15,7 @@
 import Distribution.Simple.LocalBuildInfo
 import Distribution.Simple.PackageIndex
 import Distribution.Package
+import Distribution.Utils (identifier, findPackageDescription, findProjects, readProject)
 import Distribution.Verbosity
 import Distribution.Version
 import System.Directory
@@ -32,9 +32,6 @@
 
 type ProjectDependencies = (PackageIdentifier, [PackageIdentifier], [WorkspaceProject])
 
-identifier :: GenericPackageDescription -> PackageIdentifier
-identifier = package . packageDescription
-
 allDependencies :: GenericPackageDescription -> [Dependency]
 allDependencies pd = List.filter (not . isCurrent) $ concat [lds, eds, tds] where
   lds = condTreeConstraints =<< (maybeToList $ condLibrary pd)
@@ -42,11 +39,6 @@
   tds = (condTreeConstraints . snd) =<< condTestSuites pd
   isCurrent (Dependency n _) = n == (pkgName $ identifier pd)
 
-findPackageDescription :: FilePath -> IO (Maybe GenericPackageDescription)
-findPackageDescription root = do
-  files <- getDirectoryContents root
-  traverse (readPackageDescription silent) $ fmap (\x -> root </> x) $ List.find (endswith ".cabal") files
-
 resolveCurrentProjectDependencies :: IO ProjectDependencies
 resolveCurrentProjectDependencies = do
   ws <- getWorkspace ".."
@@ -118,19 +110,11 @@
     List.find (\(WorkspaceProject (PackageIdentifier n v) _) -> n == name && withinRange v versionRange) ws
 
 readWorkspaceProject :: FilePath -> IO (Maybe WorkspaceProject)
-readWorkspaceProject path = do
-  pd <- findPackageDescription path
-  return $ fmap (\x -> WorkspaceProject (identifier x) path) pd
+readWorkspaceProject fp = do
+  maybePrj <- readProject fp
+  return $ (\(path, id) -> WorkspaceProject id path) <$> maybePrj
 
 getWorkspace :: FilePath -> IO Workspace
-getWorkspace _root = do
-  root <- canonicalizePath _root
-  xs <- listDirectory root
-  ys <- traverse find xs
-  return . Workspace $ ys >>= maybeToList where
-    find path = do
-      isDirectory <- doesDirectoryExist path
-      if isDirectory then readWorkspaceProject path else return Nothing
-    listDirectory fp = do
-      xs <- getDirectoryContents fp
-      return . fmap (fp </>) $ filter (not . startswith ".") xs
+getWorkspace fp = do
+  prjs <- findProjects fp
+  return $ Workspace $ (\(path, id) -> WorkspaceProject id path) <$> prjs
diff --git a/src/Distribution/Utils.hs b/src/Distribution/Utils.hs
new file mode 100644
--- /dev/null
+++ b/src/Distribution/Utils.hs
@@ -0,0 +1,40 @@
+module Distribution.Utils where
+
+import Data.List (isPrefixOf, isSuffixOf)
+import Data.Maybe (maybeToList)
+import Data.Traversable (traverse)
+import Distribution.Package
+import Distribution.PackageDescription
+import Distribution.PackageDescription.Parse (readPackageDescription)
+import Distribution.Verbosity (silent)
+import System.Directory
+import System.FilePath
+
+import qualified Data.List as List
+
+identifier :: GenericPackageDescription -> PackageIdentifier
+identifier = package . packageDescription
+
+findPackageDescription :: FilePath -> IO (Maybe GenericPackageDescription)
+findPackageDescription root = do
+  files <- getDirectoryContents root
+  traverse (readPackageDescription silent) $ fmap (\x -> root </> x) $ List.find (isSuffixOf ".cabal") files
+
+findProjects :: FilePath -> IO [(FilePath, PackageIdentifier)]
+findProjects fp = do
+  root <- canonicalizePath fp
+  xs <- listDirectory root
+  ys <- traverse find xs
+  return $ ys >>= maybeToList where
+    find path = do
+      isDirectory <- doesDirectoryExist path
+      if isDirectory then readProject path else return Nothing
+    listDirectory fp = do
+      xs <- getDirectoryContents fp
+      return . fmap (fp </>) $ filter (not . isPrefixOf ".") xs
+
+readProject :: FilePath -> IO (Maybe (FilePath, PackageIdentifier))
+readProject path = do
+  pd <- findPackageDescription path
+  return $ fmap (\x -> (path, identifier x)) pd
+
