diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2012 Roman Cheplyaka
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
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/hs-gen-iface.cabal b/hs-gen-iface.cabal
new file mode 100644
--- /dev/null
+++ b/hs-gen-iface.cabal
@@ -0,0 +1,32 @@
+Name:                   hs-gen-iface
+Version:                0.2
+License:                MIT
+License-file:           LICENSE
+Author:                 Roman Cheplyaka
+Maintainer:             Roman Cheplyaka <roma@ro-che.info>
+Description:            Compiler which generates module interfaces for haskell-names
+Category:               Language
+Synopsis:               Utility to generate haskell-names interface files
+Stability:              Experimental
+Build-Type:             Simple
+Cabal-Version:          >= 1.10
+
+Executable hs-gen-iface
+  Default-Language: Haskell2010
+  ghc-options: -Wall -fno-warn-name-shadowing
+  hs-source-dirs: src
+  Main-is:
+    hs-gen-iface.hs
+  Other-modules:
+    Paths_hs_gen_iface
+  Build-depends:
+    base == 4.*,
+    containers,
+    haskell-src-exts,
+    haskell-names,
+    haskell-packages,
+    filepath,
+    mtl,
+    Cabal,
+    hse-cpp,
+    tagged
diff --git a/src/hs-gen-iface.hs b/src/hs-gen-iface.hs
new file mode 100644
--- /dev/null
+++ b/src/hs-gen-iface.hs
@@ -0,0 +1,104 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+module Main where
+
+import qualified Language.Haskell.Exts.Annotated as HSE
+import qualified Language.Haskell.Exts as UnAnn
+import Language.Haskell.Exts (defaultParseMode, ParseMode(..))
+import Language.Haskell.Names
+import Language.Haskell.Names.Interfaces
+import Language.Haskell.Exts.Extension
+import Language.Haskell.Exts.SrcLoc
+import Control.Monad
+import Control.Exception
+import Data.Typeable
+import Data.Proxy
+import Data.Maybe
+import qualified Data.Foldable as F
+import System.FilePath
+import Text.Printf
+
+import Distribution.HaskellSuite
+import qualified Distribution.HaskellSuite.Compiler as Compiler
+
+import Distribution.ModuleName hiding (main)
+import Distribution.Simple.Utils
+import Distribution.Verbosity
+
+import Language.Haskell.Exts.Annotated.CPP
+import Paths_hs_gen_iface
+import Language.Haskell.Names.SyntaxUtils
+
+data GenIfaceException
+  = ParseError HSE.SrcLoc String
+  | ScopeErrors (Error HSE.SrcSpan)
+  deriving Typeable
+
+instance Show GenIfaceException where
+  show (ParseError (SrcLoc file line col) msg) =
+    printf "%s:%d:%d:\n  %s" file line col msg
+  show ScopeErrors {} = "scope errors (show not implemented yet)"
+
+instance Exception GenIfaceException
+
+fromParseResult :: HSE.ParseResult a -> IO a
+fromParseResult (HSE.ParseOk x) = return x
+fromParseResult (HSE.ParseFailed loc msg) = throwIO $ ParseError loc msg
+
+main :: IO ()
+main =
+  Compiler.main theTool
+
+suffix :: String
+suffix = "names"
+
+theTool :: Compiler.Simple NamesDB
+theTool =
+  Compiler.simple
+    "haskell-names"
+    version
+    knownLanguages
+    knownExtensions
+    compile
+    [suffix]
+
+fixCppOpts :: CpphsOptions -> CpphsOptions
+fixCppOpts opts =
+  opts {
+    defines = ("__GLASGOW_HASKELL__", "706") : defines opts -- FIXME
+  }
+
+parse :: Language -> [Extension] -> CpphsOptions -> FilePath -> IO (HSE.Module HSE.SrcSpan)
+parse lang exts cppOpts file = do
+    x <- return . fmap HSE.srcInfoSpan . fst
+            =<< fromParseResult
+            =<< parseFileWithCommentsAndCPP (fixCppOpts cppOpts) mode file
+    return x
+  where
+    mode = defaultParseMode
+             { UnAnn.parseFilename   = file
+             , baseLanguage          = lang
+             , extensions            = exts
+             , ignoreLanguagePragmas = False
+             , ignoreLinePragmas     = False
+             }
+
+compile :: Compiler.CompileFn
+compile buildDir mbLang exts cppOpts pkgName pkgdbs deps files = do
+  let lang = fromMaybe Haskell98 mbLang
+
+  moduleSet <- mapM (parse lang exts cppOpts) files
+
+  packages <- readPackagesInfo (Proxy :: Proxy NamesDB) pkgdbs deps
+
+  (ifaces, errors) <- evalModuleT (getInterfaces lang exts moduleSet) packages "names" readInterface
+
+  F.for_ errors $ \e -> printf "Warning: %s" (ppError e)
+
+  forM_ (zip moduleSet ifaces) $ \(mod, syms) -> do
+
+    let HSE.ModuleName _ modname = getModuleName mod
+        ifaceFile = buildDir </> toFilePath (fromString modname) <.> suffix
+
+    createDirectoryIfMissingVerbose silent True (dropFileName ifaceFile)
+
+    writeInterface ifaceFile $ qualifySymbols pkgName syms
