diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,31 @@
+Copyright (c) 2013, Chris Done
+Copyright (c) 2013, Philipp Balzarek
+
+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 Chris Done 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/files/Main.hs b/files/Main.hs
new file mode 100644
--- /dev/null
+++ b/files/Main.hs
@@ -0,0 +1,9 @@
+-- | Main entry point to $name.
+--
+-- $desc
+
+module Main where
+
+-- | Main entry point.
+main :: IO ()
+main = return ()
diff --git a/files/Package.hs b/files/Package.hs
new file mode 100644
--- /dev/null
+++ b/files/Package.hs
@@ -0,0 +1,3 @@
+-- | $desc
+
+module $exposed where
diff --git a/files/README.md b/files/README.md
new file mode 100644
--- /dev/null
+++ b/files/README.md
@@ -0,0 +1,4 @@
+$name
+=====
+
+$desc
diff --git a/files/Setup.hs b/files/Setup.hs
new file mode 100644
--- /dev/null
+++ b/files/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/files/dot-gitignore b/files/dot-gitignore
new file mode 100644
--- /dev/null
+++ b/files/dot-gitignore
@@ -0,0 +1,9 @@
+*.o
+*.hi
+*~
+dist/
+cabal-dev/
+.hsenv
+TAGS
+tags
+*.tag
diff --git a/files/licenses/BSD3.license b/files/licenses/BSD3.license
new file mode 100644
--- /dev/null
+++ b/files/licenses/BSD3.license
@@ -0,0 +1,24 @@
+Copyright (c) $year, $name
+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 $name nor the
+      names of its 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 <COPYRIGHT HOLDER> 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/files/licenses/MIT.license b/files/licenses/MIT.license
new file mode 100644
--- /dev/null
+++ b/files/licenses/MIT.license
@@ -0,0 +1,19 @@
+Copyright (c) $year $name
+
+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/files/package.cabal b/files/package.cabal
new file mode 100644
--- /dev/null
+++ b/files/package.cabal
@@ -0,0 +1,24 @@
+name:                $name
+version:             0.0.0
+synopsis:            $desc
+description:         $desc
+license:             BSD3
+license-file:        LICENSE
+author:              $author
+maintainer:          $email
+copyright:           $year $author
+category:            $category
+build-type:          Simple
+cabal-version:       >=1.8
+
+library
+  hs-source-dirs:    src/
+  ghc-options:       -Wall -O2
+  exposed-modules:   $exposed
+  build-depends:     base >= 4 && <5
+
+executable $name
+  hs-source-dirs:    src/
+  ghc-options:       -Wall -O2
+  main-is:           Main.hs
+  build-depends:     base >= 4 && < 5
diff --git a/make-package.cabal b/make-package.cabal
new file mode 100644
--- /dev/null
+++ b/make-package.cabal
@@ -0,0 +1,44 @@
+name:                make-package
+version:             1.0.0
+synopsis:            Make a cabalized package
+description:         Create a cabalized haskell project
+license:             BSD3
+license-file:        LICENSE
+copyright:           Chris Done, Philipp Balzarek
+author:              Philipp Balzarek
+maintainer:          p.balzarek@googlemail.com
+category:            Development, Utils
+homepage:            https://github.com/Philonous/make-package
+Bug-Reports:         https://github.com/Philonous/make-package/issues/
+build-type:          Simple
+cabal-version:       >=1.8
+data-files:          files/package.cabal
+                     files/licenses/*.license
+                     files/Setup.hs
+                     files/dot-gitignore
+                     files/Main.hs
+                     files/README.md
+                     files/Package.hs
+extra-source-files:  make-package.conf
+
+executable make-package
+  hs-source-dirs:    src
+  main-is:           Main.hs
+  other-modules:     Github
+                   , IO
+                   , Options
+  build-depends:     base >= 4 && < 5,
+                     async,
+                     bytestring,
+                     configurator,
+                     containers,
+                     directory,
+                     filepath,
+                     github,
+                     haskeline,
+                     mtl,
+                     process,
+                     text,
+                     time,
+                     time-lens
+  ghc-options:        -Wall
diff --git a/make-package.conf b/make-package.conf
new file mode 100644
--- /dev/null
+++ b/make-package.conf
@@ -0,0 +1,49 @@
+# Hashes turn the rest of the line into a comment
+## lines after double hashes describe the following field
+
+defaults{
+## Default license
+#  license = "MIT"
+
+## Name of the author. Will be taken from git or prompted for if unset
+#  author = "Igor Schmaltzhering"
+
+## Email of the author. Will be taken from git or prompted for if unset
+#  email = "no@spam.please"
+}
+
+git{
+  enable = true
+
+## Commit after copying templates
+  do-commit = true
+
+## Message to use for the initial commit (default is "initial commit")
+#  initial-commit-message = "initial commit"
+}
+
+github{
+## Enable Github interaction (Default = true)
+#  enable = true
+
+## Github username
+#  username = "ISchmaltz"
+
+## Time to wait before aborting github interactions (default is 5 seconds)
+#  timeout = 5 # seconds
+
+## Never try to clone an existing repository (default is false)
+#  never-clone = false
+
+## Never try to create github repository (default is false)
+#  never-create = false
+
+  auth {
+## Github oauth string. Will be used when both the oauth string and the password
+## are set
+#    oauth = "<secret>"
+
+# Github password
+#    password = "<secret>"
+  }
+}
diff --git a/src/Github.hs b/src/Github.hs
new file mode 100644
--- /dev/null
+++ b/src/Github.hs
@@ -0,0 +1,82 @@
+{-# LANGUAGE DoAndIfThenElse #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE LambdaCase #-}
+
+module Github where
+
+import           Control.Applicative ((<$>))
+import           Control.Monad
+import           Control.Monad.Trans
+import qualified Data.Text as T
+import qualified Data.Text.Encoding as T
+import           Github.Repos
+import           System.Exit (exitSuccess)
+import           System.Timeout
+
+import           IO
+
+-- | Check whether a repository with the given name exists on the users github
+-- accoutn and suggest cloning it
+maybeClone :: T.Text -> T.Text -> MakePackage ()
+maybeClone repo dir = unlessConf "github.enable" (== False) $
+                      unlessConf "github.never-clone" (== True) $ do
+    uname <- confOrPrompt "github.username" "Github Username" ""
+    liftIO $ putStrLn "Checking github for preexisting repos"
+    timeoutDelay <- toSeconds <$> confLookup "github.timeout"
+    mbRepoUrl <- liftIO . timeout timeoutDelay $ getRepo uname
+    case mbRepoUrl of
+        Nothing -> return ()
+        Just (Left _) -> return ()
+        Just (Right rUrl) ->
+            do cloneP <- promptYesNo "clone"
+                                     "A repository with this name already exists\
+                                     \in your github account. Clone it instead?"
+               when cloneP $ do run "git" ["clone", rUrl, T.unpack dir]
+                                liftIO exitSuccess
+  where
+    toSeconds Nothing = 5 * 10^(6::Int)
+    toSeconds (Just t) = t * 10^(6::Int)
+    getRepo uname = fmap repoSshUrl <$> userRepo (T.unpack uname) (T.unpack repo)
+
+-- | Create a github repository in the users account and set it as origin if
+-- permitted by configuration
+handleGithub :: T.Text -> T.Text -> MakePackage ()
+handleGithub repo description = unlessConf "github.enable" (== False) $
+                                unlessConf "github.never-create" (== True) $
+                                unlessEmptyPrompt "repository" $ \rName ->  do
+    auth <- confLookup "github.auth.oauth" >>= \case
+        Just oauth -> return $ GithubOAuth oauth
+        Nothing -> do uname <- confOrPrompt "github.username" "Github Username" ""
+                      pwd <- confOrPrompt "github.auth.password"
+                                          "Github Password"
+                                          ""
+                      return $ GithubBasicAuth (T.encodeUtf8 uname)
+                                               (T.encodeUtf8 pwd)
+    let nRepo = NewRepo { newRepoName         = T.unpack rName
+                        , newRepoDescription  = Just (T.unpack description)
+                        , newRepoHomepage     = Nothing
+                        , newRepoPrivate      = Nothing
+                        , newRepoHasIssues    = Nothing
+                        , newRepoHasWiki      = Nothing
+                        , newRepoAutoInit     = Nothing }
+    liftIO $ putStrLn "Creating github repository"
+    mbRepo <- liftIO $ createRepo auth nRepo
+    case mbRepo of
+        Left e -> do liftIO $ putStrLn $ "An Error occured while trying to create the repository:" ++ show e
+        Right r -> do liftIO $ putStrLn "Done."
+                      liftIO $ putStrLn "Configuring git to track the new repository"
+                      run "git" ["remote", "add", "origin", repoSshUrl r]
+                      run "git" ["config", "branch.master.remote", "origin"]
+                      run "git" [ "config"
+                                , "branch.master.merge"
+                                , "refs/heads/master"]
+                      liftIO $ putStrLn "Done."
+                      whenConf "git.do-commit" (== True) $ run "git" [ "push"
+                                                                     , "origin"
+                                                                     , "master"]
+  where
+    unlessEmptyPrompt c f =
+        do line <- prompt c "Repo Name (blank to skip)> " repo
+           if T.null line
+           then return ()
+           else f line
diff --git a/src/IO.hs b/src/IO.hs
new file mode 100644
--- /dev/null
+++ b/src/IO.hs
@@ -0,0 +1,203 @@
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE PatternGuards #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE MultiWayIf #-}
+{-# LANGUAGE LambdaCase #-}
+
+module IO where
+
+import           Control.Applicative ((<$>))
+import           Control.Monad.Reader
+import           Control.Monad.State
+import           Data.Char (isSpace)
+import qualified Data.Configurator as Conf
+import qualified Data.Configurator.Types as Conf
+import           Data.List (isPrefixOf, isSuffixOf)
+import           Data.Map (Map)
+import qualified Data.Map as Map
+import           Data.Maybe (fromMaybe)
+import           Data.Monoid
+import           Data.Text (Text)
+import qualified Data.Text as T
+import qualified Data.Text.IO as T
+import           System.Console.Haskeline as HL
+import           System.Console.Haskeline.MonadException()
+import           System.Directory
+import           System.Exit
+import           System.FilePath
+import           System.Process
+
+import           Paths_make_package
+
+newtype MakePackage a = MP {unConf :: StateT (Map Text Text)
+                                      (ReaderT Conf.Config IO)
+                                      a}
+                        deriving (Monad, MonadIO, Functor)
+
+withConfig :: MakePackage a -> IO a
+withConfig (MP f) = do conf <- loadConfig
+                       fst <$> (runReaderT (runStateT f (Map.empty)) conf)
+
+
+stored :: Conf.Configured a =>
+          Text
+       -> MakePackage (Maybe a)
+stored c =
+  do cache <- MP get
+     return $ Conf.convert . Conf.String =<< Map.lookup c cache
+
+optionDefault :: Conf.Configured b => Text -> b -> MakePackage b
+optionDefault o d = fromMaybe d `fmap` stored o
+
+confLookup :: Conf.Configured a => Conf.Name -> MakePackage (Maybe a)
+confLookup c = stored c >>= \case
+    Just x -> return $ Just x
+    Nothing -> liftIO . (`Conf.lookup` c) =<< MP ask
+
+confLookupDefault :: Conf.Configured a => Conf.Name -> a -> MakePackage a
+confLookupDefault c d = maybe d id <$> confLookup c
+
+-- | Prompt user
+prompt :: T.Text -> T.Text -> Text -> MakePackage T.Text
+prompt c p il = stored c >>= \case
+    Just x -> return x
+    Nothing ->
+      do ln <- liftIO $ runInputT defaultSettings $
+                   HL.getInputLineWithInitial (T.unpack $ p <> "> ")
+                                              (T.unpack il, "")
+         case ln of
+             Nothing -> liftIO exitFailure
+             Just line ->
+                 do setOption c (T.pack line)
+                    return (T.pack line)
+
+promptYesNo :: T.Text -> T.Text -> MakePackage Bool
+promptYesNo c p = stored c >>= \case
+    Just x -> return x
+    Nothing -> do liftIO $ T.putStrLn p
+                  res <- liftIO $ runInputT defaultSettings go
+                  setOption c (if res then "true" else "false")
+                  return res
+  where
+    go = do char <- getInputChar ("[y]yes or [n]o> ")
+            case char of
+                Nothing -> liftIO exitFailure
+                Just 'y' -> return True
+                Just 'Y' -> return True
+                Just 'n' -> return False
+                Just 'N' -> return False
+                _   -> go
+
+
+setOption :: Text -> Text -> MakePackage ()
+setOption c x = MP $ modify (Map.insert c x)
+
+-- | Get option from configuration file or prompt user
+confOrPrompt :: T.Text -> T.Text -> T.Text -> MakePackage T.Text
+confOrPrompt c p i = confLookup c >>= \case
+    Nothing -> prompt c p i
+    Just x  -> return x
+
+-- | Get option from configuration file, git configuration or promp user
+confOrGitOrPrompt :: T.Text -> T.Text -> T.Text -> T.Text -> MakePackage T.Text
+confOrGitOrPrompt c gitQ p i = confLookup c >>= \case
+    Just x -> return x
+    Nothing -> confLookup "git.enable" >>= \case
+               Just True -> queryGit (T.unpack gitQ) >>= \case
+                   Just x -> do setOption c x
+                                return x
+                   Nothing -> do x <- prompt c p i
+                                 setOption c x
+                                 return x
+               _ -> do x <- prompt c p i
+                       setOption c x
+                       return x
+
+-- | Get license from configuration or prompt
+getLicense :: MakePackage T.Text
+getLicense = do
+    licensesDir <- liftIO $ dataFile "licenses"
+    licenses <- map takeBaseName . filter (".license" `isSuffixOf` ) <$>
+                    liftIO (getDirectoryContents licensesDir)
+    defaultLicense <- confLookup "defaults.license" >>= \case
+        Nothing -> return Nothing
+        Just l -> if (l `elem` licenses)
+                  then return . Just $ T.pack l
+                  else do liftIO . putStrLn $
+                              "Warning, configured default license \""
+                              ++ l ++ "\" is unknown"
+                          return Nothing
+    case defaultLicense of
+        Just l -> return l
+        Nothing -> T.pack <$> selectFrom "license" licenses
+
+-- | Query git configuration
+queryGit :: String -> MakePackage (Maybe T.Text)
+queryGit q = liftIO (readProcessWithExitCode "git" ["config","--get", q] "")
+             >>= \case
+    (ExitSuccess, res, _stderr) -> return . Just $ oneLine res
+    _ -> return Nothing
+  where
+    oneLine = T.concat . take 1 . T.lines . T.pack
+
+-- | Run a programm, exit with error when program returns failure code
+run :: String -> [String] -> MakePackage ()
+run pg args = liftIO $ rawSystem pg args >>= \case
+    ExitSuccess -> return ()
+    ExitFailure n -> do
+                    putStrLn $ "Program " ++ show pg
+                        ++ " exited with error code " ++ show n
+                    exitFailure
+
+-- | Get the file path of packaged file
+dataFile :: String -> IO String
+dataFile fp = getDataFileName ("files/" <> fp)
+
+-- | Load the configuration files
+loadConfig :: IO Conf.Config
+loadConfig = do
+    appData <- getAppUserDataDirectory "make-package"
+    home <- getHomeDirectory
+    Conf.load [ Conf.Optional $ appData </> "make-package.conf"
+              , Conf.Optional $ home </> ".make-package.conf"
+              ]
+
+-- | Run action unless configuration option is set and predicate is true
+unlessConf :: Conf.Configured a => Conf.Name
+                                -> (a -> Bool)
+                                -> MakePackage ()
+                                -> MakePackage ()
+unlessConf option p f = confLookup option >>= \case
+    Just x | p x -> return ()
+    _ -> f
+
+-- | Run action when configuration option is set and predicate is true
+whenConf :: Conf.Configured a => Conf.Name
+                              -> (a -> Bool)
+                              -> MakePackage ()
+                              -> MakePackage ()
+whenConf option p f = confLookup option >>= \case
+    Just x | p x -> f
+    _ -> return ()
+
+-- | Let the user select a string from a list
+selectFrom :: String -> [String] -> MakePackage String
+selectFrom p xs = liftIO $ do
+    runInputT (setComplete cf defaultSettings) (HL.outputStrLn options >> go)
+  where
+    pairs = zip (map show [1:: Int ..]) xs
+    options = unlines $ map (\(l,r) -> l <> ") " <> r ) pairs
+    cf = completeWord Nothing " "
+           (\wd -> return $ simpleCompletion <$> filter (wd `isPrefixOf`) xs)
+    go = do
+        mbln <- HL.getInputLine (p <> "> ")
+        ln <- case mbln of
+            Nothing -> liftIO exitFailure
+            Just ln -> return . strip $ ln
+        if | ln `elem` xs -> return ln
+           | Just line <- ln `lookup` pairs -> return line
+           | "?" <- ln -> HL.outputStrLn options >> go
+           | otherwise -> do
+               HL.outputStrLn $ ln ++ " is not valid, type ? to show options"
+               go
+    strip = reverse . dropWhile isSpace . reverse . dropWhile isSpace
diff --git a/src/Main.hs b/src/Main.hs
new file mode 100644
--- /dev/null
+++ b/src/Main.hs
@@ -0,0 +1,77 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | Main entry point.
+
+module Main where
+
+import           IO
+import           Github
+import           Options
+
+import           Control.Monad (when)
+import           Control.Monad.Trans (liftIO)
+import           Data.Monoid
+import qualified Data.Text as T
+import qualified Data.Text.IO as T
+import           Data.Time
+import           Data.Time.Lens
+import           System.Directory
+import           System.Exit (exitFailure)
+import           System.FilePath
+
+-- import System.Process
+
+-- | Main entry point.
+main :: IO ()
+main = withConfig $ do
+  handleArgs
+  packageName <- prompt "package" "Package Name" ""
+  packageDir <- optionDefault "directory" packageName
+  checkExists packageDir
+  maybeClone packageName packageDir
+  author <- confOrGitOrPrompt "defaults.author" "user.name"  "Author" ""
+  email <- confOrGitOrPrompt "defaults.email" "user.email" "Author Email" ""
+  desc <- prompt "description" "Description" ""
+  licenseType <- getLicense
+  exposed <- prompt "modules" "Exposed Module(s)" "Main"
+  category <- prompt "categories" "Category(s)" ""
+  now <- liftIO getCurrentTime
+  liftIO $ do createDirectoryIfMissing False (T.unpack packageName)
+              setCurrentDirectory (T.unpack packageName)
+              createDirectoryIfMissing False ("src/")
+  let substitutions = [("name"     ,packageName)
+                      ,("desc"     ,desc)
+                      ,("email"    ,email)
+                      ,("author"   ,author)
+                      ,("year"     ,T.pack (show (getL year now)))
+                      ,("category" ,category)
+                      ,("exposed"  ,exposed)
+                      ,("license"  ,licenseType)]
+      copyTemplate = doCopyTemplate substitutions
+  copyTemplate "package.cabal" (T.unpack (packageName <> ".cabal"))
+  copyTemplate "dot-gitignore" ".gitignore"
+  copyTemplate "Setup.hs" "Setup.hs"
+  copyTemplate ("licenses"</> T.unpack licenseType <.> "license") "LICENSE"
+  copyTemplate "README.md" "README.md"
+  copyTemplate "Main.hs" "src/Main.hs"
+  copyTemplate "Package.hs" (T.unpack ("src/" <> exposed <> ".hs"))
+  run "cabal" ["configure"]
+  unlessConf "git.enable" (== False) $ do
+    run "git" ["init"]
+    run "git" ["add", "."]
+    whenConf "git.do-commit" (== True) $ do
+      msg <- confLookupDefault "git.initial-commit-message" "initial commit"
+      run "git" ["commit", "-m", msg]
+  handleGithub packageName desc
+  where
+    checkExists pname = liftIO $
+        do fileExists <- doesFileExist (T.unpack pname)
+           dirExists <- doesDirectoryExist (T.unpack pname)
+           when (fileExists || dirExists) $
+               do putStrLn "A file or directory with this name already exists. Bailing out"
+                  exitFailure
+
+    doCopyTemplate substitutions infile outfile = liftIO $
+        do template <- dataFile infile >>= T.readFile
+           T.writeFile outfile (substitute template substitutions)
+    substitute = foldl (\str (this,that) -> T.replace ("$" <> this) that str)
diff --git a/src/Options.hs b/src/Options.hs
new file mode 100644
--- /dev/null
+++ b/src/Options.hs
@@ -0,0 +1,83 @@
+{-# LANGUAGE DoAndIfThenElse #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+module Options where
+
+import           Control.Monad
+import           Control.Monad.Trans
+import qualified Data.Text as T
+import           System.Console.GetOpt
+import           System.Environment
+import           System.Exit (exitSuccess, exitFailure)
+
+import           IO
+
+setOpt :: T.Text -> String -> ArgDescr (MakePackage ())
+setOpt o = ReqArg (setOption o . T.pack)
+
+options :: [OptDescr (MakePackage ())]
+options = [ Option "h" ["help"] (NoArg $ help [])
+              "display this help text"
+          , Option "P" ["package"] (setOpt "package" "string")
+              "package name"
+          , Option "d" ["dir"] (setOpt "directory" "string")
+            "directory to initialize in (default = package name)"
+          , Option "A" ["author"] (setOpt "defaults.author" "string")
+            "package author"
+          , Option "E" ["email"] (setOpt "defaults.email" "string")
+            "package author email address"
+          , Option "D" ["description"] (setOpt "description" "string")
+            "package description"
+          , Option "L" ["license"] (setOpt "defaults.license" "string")
+            "license name"
+          , Option "M" ["modules"] (setOpt "modules" "string")
+            "exposed modules"
+          , Option "H" ["categories"] (setOpt "categories" "string")
+            "hackage categories"
+          , Option "G" ["git"] (NoArg $ setOption "git.enable" "true")
+            "enable git"
+          , Option "g" ["no-git"] (NoArg $ setOption "git.enable" "false")
+            "disable git"
+          , Option "C" ["commit"] (NoArg $ setOption "git.do-commit" "true")
+            "run git commit"
+          , Option "c" ["no-commit"] (NoArg $ setOption "git.do-commit" "false")
+            "don't run git commit"
+          , Option "M" ["commit-message"] (setOpt "git.initial-commit-message"
+                                                  "string")
+            "commit message to use"
+          , Option "G" ["github"] (NoArg $ setOption "github.enable" "true")
+            "enable github integration"
+          , Option "g" ["no-github"] (NoArg $ setOption "github.enable" "false")
+            "disable github integration"
+          , Option "U" ["username"] (setOpt "github.username" "string")
+            "github username"
+          , Option "R" ["repository"] (setOpt "github.repository" "string")
+            "github repository to create"
+          , Option "T" ["timeout"] (setOpt "github.timeout" "int")
+            "timeout for github interactions in seconds"
+          , Option "K" ["clone"] (NoArg $ setOption "clone" "true")
+            "clone existing repository "
+          , Option "k" ["no-clone"] (NoArg $ setOption "clone" "false")
+            "don't clone existing repository "
+          , Option "O" ["oauth"] (setOpt "github.auth.oauth" "string")
+            "github oauth token"
+          , Option "P" ["password"] (setOpt "github.auth.password" "string")
+            "github password"
+          ]
+
+help :: MonadIO m => [String] -> m a
+help errors = liftIO $
+  do forM_  errors putStrLn
+     putStrLn $ usageInfo "make-package [package-name] [options]" options
+     if null errors
+     then exitSuccess
+     else exitFailure
+
+handleArgs :: MakePackage ()
+handleArgs =
+  do args <- liftIO $ getArgs
+     let (opts, _, errs) = getOpt (ReturnInOrder (setOption "package" . T.pack))
+                                  options
+                                  args
+     unless (null errs) $ help errs
+     sequence_ opts
