diff --git a/CabalSearch.cabal b/CabalSearch.cabal
new file mode 100644
--- /dev/null
+++ b/CabalSearch.cabal
@@ -0,0 +1,42 @@
+name:           CabalSearch
+version:        0.0.1
+license:        BSD3
+license-file:   LICENSE
+category:       Utils
+copyright:      Copyright 2011 Johan Brinch
+author:         Johan Brinch <brinchj@gmail.com>
+maintainer:     Johan Brinch <brinchj@gmail.com>
+stability:      experimental
+tested-with:    GHC == 6.12.3
+cabal-version:  >= 1.8
+homepage:       http://github.com/brinchj/cabalsearch
+bug-reports:    http://github.com/brinchj/cabalsearch/issues
+build-type:     Simple
+synopsis:
+        Search cabal packages by name
+description:
+
+        CabalSearch builds an index of cabal packages and search through them by
+        name. It acts as a 'cabal list' replacement. To get started, install the
+        package and run: @cabalsearch --rebuild@. Now try it out with a query:
+        @cabalsearch cabal@.
+
+executable cabalsearch
+    main-is: Main.hs
+
+    build-depends:
+        base == 4.*,
+        HDBC == 2.3.*,
+        HDBC-sqlite3 == 2.3.*,
+        bytestring,
+        directory,
+        filepath,
+        process,
+        unix
+
+    ghc-options: -Wall
+    ghc-prof-options: -auto-all
+
+source-repository head
+    type:     git
+    location: http://github.com/brinchj/cabalsearch
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c)2011, Johan Brinch
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Johan Brinch nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Main.hs b/Main.hs
new file mode 100644
--- /dev/null
+++ b/Main.hs
@@ -0,0 +1,54 @@
+module Main where
+
+import Control.Monad
+
+import System.Directory
+import System.Environment
+import System.Exit
+import System.FilePath ((</>))
+import System.Posix.User (getUserEntryForName, getEffectiveUserName, UserEntry(..))
+import Data.List
+
+import CabalIndex
+
+ensureIndex :: FilePath -> String -> Bool -> IO ()
+ensureIndex dir name force =
+  do -- Check directory
+     dirExists <- doesDirectoryExist dir
+     unless dirExists $
+       do putStrLn $ "Creating: " ++ dir
+          createDirectory dir
+     -- Check db file
+     dbExists <- doesFileExist name
+     when (force || not dbExists) $
+       do putStrLn $ "Building database: " ++ name
+          buildDatabase dir name
+
+main :: IO ()
+main = do
+  args    <- getArgs
+  homeDir <- homeDirectory `fmap` (getUserEntryForName =<< getEffectiveUserName)
+  let dbDir  = homeDir </> ".cabalsearch"
+      dbPath = dbDir   </> "packages.sqlite3"
+      arg    = head args
+  -- show info
+  when (length args /= 1 || "--help" `elem` args) $
+    do name <- getProgName
+       putStrLn $ "usage: " ++ name ++ " searchTerm"
+       putStrLn $ "   or: " ++ name ++ " --rebuild"
+       exitFailure
+  -- work
+  go (arg `isPrefixOf` "--rebuild") arg dbDir dbPath
+  where
+    go rebuild term dbDir dbPath =
+      do -- rebuild index
+        when rebuild $
+          do ensureIndex dbDir dbPath True
+             exitSuccess
+        -- run query
+        ensureIndex dbDir dbPath False
+        res <- queryPackages (dbDir </> dbPath) term
+        forM_ res $ \(name, meta) -> putStrLn $ concat
+                                     ["* ", name, "\n", meta, "\n"]
+
+
diff --git a/Setup.lhs b/Setup.lhs
new file mode 100644
--- /dev/null
+++ b/Setup.lhs
@@ -0,0 +1,3 @@
+#!/usr/bin/env runhaskell
+> import Distribution.Simple
+> main = defaultMain
