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
diff --git a/TODO b/TODO
new file mode 100644
--- /dev/null
+++ b/TODO
@@ -0,0 +1,7 @@
+TODO: In order of importance
+- Allow it to work with cabal files?
+- Allow it to parse module names for tagging.
+- Give an option to work with search strings (like exuberant C tags)
+- Allow it to work with qualified modules local to a file? (Check out the info
+  on extended syntax)
+- Get a haskell extended parser to work with.
diff --git a/htags.cabal b/htags.cabal
new file mode 100644
--- /dev/null
+++ b/htags.cabal
@@ -0,0 +1,22 @@
+Author:         David Sankel
+Maintainer:     david@sankelsoftware.com
+Name:           htags
+Version:        1.0
+Cabal-Version:  >= 1.2
+License:        BSD3
+Category:       Development, Source-tools, Utils
+Copyright:      (c) 2008 by David Sankel
+Synopsis:       A Haskell98 parsing tags program similar to ctags.
+Description:
+  htags is a tag file generator to enable extra functionality in editors like
+  vim. It expands upon 'hasktags' by using a full Haskell 98 parser and options
+  for recursion.
+  .
+  &#169; 2008 by David Sankel; BSD3 license.
+Build-Type:     Simple
+extra-source-files: readme.txt TODO
+
+Executable htags
+  Build-Depends:  base, filepath, directory, mtl, haskell-src
+  Main-Is:        htags.hs
+  Hs-Source-Dirs: src
diff --git a/readme.txt b/readme.txt
new file mode 100644
--- /dev/null
+++ b/readme.txt
@@ -0,0 +1,1 @@
+Test.hs is the latest version and it is working, just like the older Working.hs
diff --git a/src/htags.hs b/src/htags.hs
new file mode 100644
--- /dev/null
+++ b/src/htags.hs
@@ -0,0 +1,143 @@
+{-# OPTIONS_GHC -Wall #-}
+module Main(main) where
+import Language.Haskell.Syntax
+import Language.Haskell.Parser
+import Control.Applicative
+import System.Environment
+import Tag
+import GenTags
+import Data.Maybe
+import System.Console.GetOpt
+import Control.Monad.Error
+import System.Directory
+import System.FilePath
+import Control.Arrow( first, second )
+
+--
+-- Options datatype
+--
+data Options = Options { optRecurse :: Bool
+                       , optShowHelp :: Bool
+                       }
+  deriving Show
+
+defaultOptions ::  Options
+defaultOptions = Options False False
+
+setRecurse :: Bool -> Options -> Options
+setRecurse b o = o { optRecurse = b }
+
+showHelp :: Options -> Options
+showHelp o = o { optShowHelp = True }
+
+--
+-- Special Yes/No Option
+--
+
+ynb :: (Monad m) => String -> m Bool
+ynb "yes" = return True
+ynb "no" = return False
+ynb _ = error "Invalid (yes|no) thing"
+
+
+yesNoArg :: (Monad m) => (Bool -> a -> b) -> Bool -> ArgDescr (a -> m b)
+yesNoArg z def = OptArg f "yes|no"
+  where
+    f = maybe (return . z def) (\a opt -> ynb a >>= return . flip z opt)
+
+--
+-- Our options list
+--
+
+options ::  [OptDescr (Options -> Either String Options)]
+options = [ Option "R" ["recurse"] (yesNoArg setRecurse True)
+                "Recurse into directories supplied on command line [no]."
+          , Option "" ["help"] (NoArg (fmap return showHelp))
+                "Print this option summary."
+          ]
+
+parseOpts ::  [String] -> -- command line arguments
+              Either 
+                 String -- Error message
+                 ( Options   -- Options
+                 , [String] ) -- List of files
+parseOpts s = errM >> optsM >>= return . flip (,) nonopts
+  where (args, nonopts, errors) = getOpt Permute options s
+        optsM = foldM (flip ($)) defaultOptions args
+        errM = sequence_ (fmap error errors)
+ 
+prgName :: String
+prgName = "htags"
+
+outputUsage ::  IO ()
+outputUsage = putStr (usageInfo prgName options)
+
+--
+-- File Path utilities
+--
+getLeavesL :: [String] -> IO [String]
+getLeavesL = fmap concat . mapM getLeaves
+
+-- Like getDirectoryContents, but returns relative paths
+childPaths ::  FilePath -> IO [FilePath]
+childPaths s = do contents <- getDirectoryContents s
+                  return (fmap (combine s) (filter (flip notElem [".",".."]) contents))
+         
+getLeaves :: String -> IO [String]
+getLeaves s = do isDir <- doesDirectoryExist s
+                 if isDir then childPaths s >>= getLeavesL
+                          else (pure.pure) s
+                      
+-- Given a list of directories and files, returns a list of haskell source
+-- files optionally recursing.
+getHsFiles :: Bool -> [String] -> IO [String]
+getHsFiles False files = return (filterHs files)
+getHsFiles True files = fmap filterHs (getLeavesL files)
+
+filterHs :: [String] -> [String]
+filterHs = filter isHaskellFile
+
+isHaskellFile :: String -> Bool
+isHaskellFile = flip elem haskellExtensions . takeExtension
+
+haskellExtensions ::  [String]
+haskellExtensions = [".hs", ".lhs"]
+
+run :: Options -> [String] -> IO ()
+run os files = do when (optShowHelp os) outputUsage
+                  fs <- getHsFiles (optRecurse os) files
+                  (errors, tags) <- fmap pullout (mapM yar fs)
+                  mapM_ (putStrLn . (++) "Parse Error: " . show) errors
+                  writeFile "tags" (tagsToTagfile (concat tags))
+  where
+    yar ::  String -> IO (Either (SrcLoc, String) [Tag])
+    yar = (fmap.fmap.fmap) modToTags parseFile
+
+main ::  IO ()
+main = fmap parseOpts getArgs >>= either print (uncurry run)
+
+--
+-- Utility Functions
+--
+
+parseFile :: String -> IO (Either (SrcLoc, String) HsModule)
+parseFile = (fmap.fmap) prToEither pf
+  where
+    pf :: String -> IO (ParseResult HsModule)
+    pf = liftA2 fmap (parseModuleWithMode . ParseMode) readFile
+    -- Convert ParseResult to an Either
+    prToEither :: ParseResult HsModule -> Either (SrcLoc, String) HsModule
+    prToEither s = case s of ParseFailed loc str -> Left (loc,str)
+                             ParseOk m           -> Right m
+
+pullout :: [Either a b] -> ([a], [b])
+pullout [] = ([], [])
+pullout (Left a:z) = first (a:) (pullout z)
+pullout (Right a:z) = second (a:) (pullout z)
+
+-- TODO: In order of importance
+-- - Allow it to work with cabal files?
+-- - Allow it to parse module names for tagging.
+-- - Make it work with search strings (like exuberant C tags)
+-- - Allow it to work with qualified modules local to a file? (Check out the info on extended syntax)
+-- - Allow it to take many command line arguments for names.
