diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2013, Jonathan Fischoff
+
+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 Jonathan Fischoff 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/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/modulespection.cabal b/modulespection.cabal
new file mode 100644
--- /dev/null
+++ b/modulespection.cabal
@@ -0,0 +1,78 @@
+-- Initial modulespection.cabal generated by cabal init.  For further 
+-- documentation, see http://haskell.org/cabal/users-guide/
+
+name:                modulespection
+version:             0.1.0.0
+synopsis:            Template Haskell introspecting a modules declarations
+description: 
+ Collect all of the declarations in a module using Template Haskell (via the GHC API). 
+ . 
+ One can either get all the names, or just the declarations (only type declarations
+ are supported right now).
+ .
+ Here is a quick example
+ . 
+ > import Language.Haskell.TH.Module.Magic (names)
+ > 
+ > data Test = Test Int
+ > newtype OtherTest = OtherTest Test
+ > 
+ > someFunction :: String -> String
+ > someFunction = id
+ > 
+ > -- 'names' is Template Haskell function that will collect all of the 
+ > -- toplevel declaration names of the current file.
+ > names >>= runIO . print >> return []
+ .
+ Which will spew the following when compiling.
+ .
+ > [Test,OtherTest,someFunction]
+ . 
+ There is also 'declarations' which can be used, for example, to make sure that all
+ types have @ToJSON@/@FromJSON@ instances. 
+ .
+ > import Data.Aeson.TH (deriveJSON, defaultOptions)
+ > import MonadUtils (concatMapM)
+ > import Language.Haskell.TH.Module.Magic (names)
+ > 
+ > data Test = Test Int
+ > newtype OtherTest = OtherTest Test
+ >
+ > concatMapM (deriveJSON defaultOptions) =<< declarations
+ .
+ Which will makes the JSON instances for Test and OtherTest and any other types
+ added to the file.
+ .
+ You can also do the same thing for an existing module.
+ .
+ > import Data.Aeson.TH (deriveJSON, defaultOptions)
+ > import MonadUtils (concatMapM)
+ > import Language.Haskell.TH.Module.Magic (names)
+ > import Data.Monoid
+ > 
+ > concatMapM (deriveJSON defaultOptions) =<< moduleDeclarations "Data.Monoid"
+ .
+ Which will build instances for all the types in "Data.Monoid".
+
+license:             BSD3
+license-file:        LICENSE
+author:              Jonathan Fischoff
+maintainer:          jonathangfischoff@gmail.com
+homepage: https://github.com/jfischoff/modulespection
+-- copyright:           
+category:            Language
+build-type:          Simple
+-- extra-source-files:  
+cabal-version:       >=1.10
+
+library
+  exposed-modules:     Language.Haskell.TH.Module.Magic
+  -- other-modules:       
+  other-extensions: LambdaCase
+                  , FlexibleInstances
+  build-depends: base >=4.6 && <4.7
+               , template-haskell >=2.7 && <2.9
+               , ghc-paths >=0.1 && <0.2
+               , ghc
+  hs-source-dirs:      src
+  default-language:    Haskell2010
diff --git a/src/Language/Haskell/TH/Module/Magic.hs b/src/Language/Haskell/TH/Module/Magic.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Haskell/TH/Module/Magic.hs
@@ -0,0 +1,148 @@
+{-# LANGUAGE LambdaCase        #-}
+{-# LANGUAGE FlexibleInstances #-}
+module Language.Haskell.TH.Module.Magic 
+   ( -- * Name Introspection
+     names
+   , moduleNames
+     -- * Declaration Introspection
+   , declarations
+   , moduleDeclarations
+   ) where
+import Language.Haskell.TH as TH
+import Data.Maybe
+import GHC
+import Module
+import GHC.Paths ( libdir )
+import DynFlags 
+import Name as Name
+import RdrName 
+import MonadUtils
+import HsDecls as HsDecls
+import SrcLoc
+import Bag
+import Control.Monad
+import Data.Monoid
+
+-- | Get all the top level declarations of the current file.
+--   All names are returned whether they are exported or not.
+names :: Q [TH.Name]
+names = moduleNames . loc_filename =<< location
+
+-- | Get all the top level names of a given module. 
+--   If a file path is used, all names, exported and internal
+--   are returned. If a module name is used, only the exported
+--   names are returned.
+moduleNames :: String -> Q [TH.Name]
+moduleNames target = runIO $ 
+   defaultErrorHandler 
+      defaultFatalMessager 
+      defaultFlushOut 
+      $ do
+         runGhc (Just libdir) $ do
+           dflags <- getSessionDynFlags
+           setSessionDynFlags dflags
+           lookupModuleNames target
+
+-- | Look up a name, and get out the declaration 
+--   or return nothing
+nameToMaybeDec :: TH.Name -> Q (Maybe Dec)
+nameToMaybeDec name = do
+   info <- reify name
+   return $ case info of
+      TyConI dec -> Just dec
+      _          -> Nothing
+      
+-- | Get all the type declarations of the current file. 
+--   Function and pattern declarations are ignored ... for now.
+declarations :: Q [Dec]
+declarations = mapMaybeM nameToMaybeDec =<< names
+
+-- | Get all the top level names of a given module. 
+--   If a file path is used, all names, exported and internal
+--   are returned. If a module name is used, only the exported
+--   names are returned.
+--   Function and pattern declarations are ignored ... for now.
+moduleDeclarations :: String -> Q [Dec]
+moduleDeclarations = mapMaybeM nameToMaybeDec <=< moduleNames 
+
+-- | Either try to parse a source file or if the module is
+--   part of library, look it up and browse the contents
+lookupModuleNames :: GhcMonad m => String -> m [TH.Name]
+lookupModuleNames mName = do   
+   target <- targetId <$> guessTarget mName Nothing
+   case target of
+      TargetModule moduleName -> getExistingModuleNames 
+                             =<< lookupModule moduleName Nothing
+      TargetFile filePath _   -> parseFile filePath
+
+-- | Turn ErrorMessages into a String
+errString :: Show a => Bag a -> String     
+errString = unlines 
+          . map show 
+          . foldBag (<>) (:[]) []
+
+-- | Parse a file and collect all of the declarations names
+parseFile :: GhcMonad m => FilePath -> m [TH.Name]
+parseFile filePath = do
+   dflags <- getDynFlags
+   src    <- liftIO $ readFile filePath 
+   let (warns, L _ hsModule) = 
+         either (error . errString) id
+               $ parser src dflags filePath
+                                 
+       names = mapMaybe getNameMaybe $ hsmodDecls hsModule
+       
+   return $ map rdrNameToName names
+
+showModuleName :: Module -> String
+showModuleName = moduleNameString . moduleName
+
+getExistingModuleNames :: GhcMonad m => Module -> m [TH.Name]
+getExistingModuleNames modl = do
+  moduleInfo <- getModuleInfo modl
+  case moduleInfo of
+    Nothing -> error $ "modulespection: Failed to find module info for "
+                     <> showModuleName modl
+                     <> " in getExistingModuleNames"
+    Just mod_info -> fmap (map (occNameToName . nameOccName . getName))
+                  .  mapMaybeM lookupName 
+                  $  modInfoExports mod_info
+
+-- | Simple Class for getting the name of things
+class GetNameMaybe a where
+   getNameMaybe :: a -> Maybe RdrName
+
+instance GetNameMaybe (HsDecl RdrName) where
+   getNameMaybe = \case 
+      TyClD x -> getNameMaybe x
+      HsDecls.ValD  x -> getNameMaybe x
+      _           -> Nothing
+
+instance GetNameMaybe (TyClDecl RdrName) where
+   getNameMaybe = \case
+      ForeignType x _   -> getNameMaybe x
+      x@(TyFamily   {}) -> getNameMaybe $ tcdLName x
+      TyDecl    x _ _ _ -> getNameMaybe x
+      x@(ClassDecl {})  -> getNameMaybe $ tcdLName x
+
+instance GetNameMaybe (HsBindLR RdrName RdrName) where
+   getNameMaybe = \case 
+      x@(FunBind {}) -> getNameMaybe $ fun_id x 
+      _                  -> Nothing
+
+instance GetNameMaybe a => GetNameMaybe (GenLocated SrcSpan a) where
+   getNameMaybe (L _ x) = getNameMaybe x 
+
+instance GetNameMaybe RdrName where
+   getNameMaybe = Just
+
+-- Name Utils
+occNameToName :: OccName -> TH.Name
+occNameToName = mkName . occNameString 
+
+rdrNameToName :: RdrName -> TH.Name
+rdrNameToName = \case 
+   RdrName.Unqual x -> occNameToName x
+   RdrName.Qual _ x -> occNameToName x
+   RdrName.Orig _ x -> occNameToName x
+   RdrName.Exact  x -> occNameToName $ nameOccName x
