diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2015 ElvishJerricco
+
+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/MTGBuilder.cabal b/MTGBuilder.cabal
new file mode 100644
--- /dev/null
+++ b/MTGBuilder.cabal
@@ -0,0 +1,28 @@
+-- Initial MTGBuilder.cabal generated by cabal init.  For further 
+-- documentation, see http://haskell.org/cabal/users-guide/
+
+name:                MTGBuilder
+version:             0.1.0.0
+synopsis:            Builds decks out of a meta
+-- description:         
+license:             MIT
+license-file:        LICENSE
+author:              ElvishJerricco
+maintainer:          elvishjerricco@gmail.com
+-- copyright:           
+-- category:            
+build-type:          Simple
+-- extra-source-files:  
+cabal-version:       >=1.10
+
+executable mtg-builder
+  main-is:             Main.hs
+  -- other-modules:       
+  -- other-extensions:    
+  build-depends:
+        base >=4.8 && <4.9
+      , parsec
+      , containers
+      , mtl
+  hs-source-dirs:      src
+  default-language:    Haskell2010
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/src/Main.hs b/src/Main.hs
new file mode 100644
--- /dev/null
+++ b/src/Main.hs
@@ -0,0 +1,118 @@
+module Main (
+    main
+) where
+
+import System.Environment
+import System.IO
+import System.Console.GetOpt
+import System.Exit
+import Control.Monad
+import Control.Monad.Reader
+import MTGBuilder.Deck
+import MTGBuilder.Parser
+import Data.Set (Set)
+import qualified Data.Set as Set
+
+data Options = Options  {
+    optVerbose      :: Bool,
+    optWriteRanking :: String -> IO (),
+    optOutput       :: Handle,
+    optPrecision    :: Int
+}
+
+options :: [OptDescr (Options -> IO Options)]
+options =
+    [ Option "o" ["output"]
+        (ReqArg
+            (\arg opt -> do
+                handle <- openFile arg WriteMode
+                return opt { optOutput = handle })
+            "FILE")
+        "Output file"
+ 
+    , Option "r" ["ranking"]
+        (ReqArg
+            (\arg opt -> return opt { optPrecision = read arg })
+            "NUMBER")
+        "Order of rankings to compose the input decks with"
+ 
+    , Option "f" ["rankingFile"]
+        (ReqArg
+            (\arg opt -> return opt { optWriteRanking = writeFile arg })
+            "FILE")
+        "Order of precision to measure interactions with"
+ 
+    , Option "v" ["verbose"]
+        (NoArg
+            (\opt -> return opt { optVerbose = True }))
+        "Enable verbose messages"
+ 
+    , Option "V" ["version"]
+        (NoArg
+            (\_ -> do
+                hPutStrLn stderr "Version 0.1.0.0"
+                exitWith ExitSuccess))
+        "Print version"
+ 
+    , Option "h" ["help"]
+        (NoArg
+            (\_ -> do
+                hPutStrLn stderr (usageInfo "mtg-builder" options)
+                exitWith ExitSuccess))
+        "Show help"
+    ]
+
+startOptions :: Options
+startOptions = Options  {
+    optVerbose      = False,
+    optWriteRanking  = (\s -> return ()),
+    optOutput       = stdout,
+    optPrecision    = 2     -- Default to only second order rankings
+}
+
+main = do
+    args <- getArgs
+ 
+    -- Parse options, getting a list of option actions and input deck files
+    let (actions, nonOptions, errors) = getOpt RequireOrder options args
+
+    -- Thread startOptions through all supplied option actions
+    opts <- foldl (>>=) (return startOptions) actions
+ 
+    let Options {
+        optVerbose = verbose,
+        optWriteRanking = writeRanking,
+        optOutput = output,
+        optPrecision = precision
+    } = opts
+
+    -- Produce a list of IO (name, contents)
+    let input = sequence $ case nonOptions of
+            []      -> [getContents >>= \s -> return ("stdin", s)]
+            inputs  -> fmap (\i -> readFile i >>= \s -> return (i, s)) inputs
+
+    -- =)
+    when verbose (hPutStrLn stderr "Hello!")
+ 
+
+    deckNamesAndContents <- input
+    namedDecks <- forM deckNamesAndContents (\(name, source) -> case parseDeckString name source of
+            Left err    -> fail $ show err
+            Right deck  -> do
+                when verbose (hPutStrLn stderr ("Parsing deck: " ++ name))
+                return (name, deck))
+
+    let decks = fmap snd namedDecks
+
+    -- Produce the rank mappings
+    ranking <- runReaderT (makeRanking precision namedDecks) verbose
+    writeRanking $ dumpRanking ranking
+
+    -- Compose the decks into the aggregate deck
+    deck <- runReaderT (composeDecks ranking 60 decks) verbose
+    when verbose $ hPutStrLn stderr ("Final size: " ++ (show $ Set.size deck))
+    let dump = dumpDeck deck
+    hPutStrLn output dump
+    when verbose $ hPutStrLn stderr $ dump
+    hClose output
+    return ()
