diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright Vanessa McHale (c) 2017
+
+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 Vanessa McHale 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/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,66 @@
+# Wordchoice Command-Line Tool
+[![Build Status](https://travis-ci.org/vmchale/wordchoice.svg?branch=master)](https://travis-ci.org/vmchale/wordchoice)
+
+## Usage
+
+The following will print the 10 most used words *and* output a bar graph
+showing the distribution of those 10 words.
+
+```bash
+ $ wordchoice test/ulysses.txt -n10 -o distribution.html
+ 13609: the
+ 8134: of
+ 6550: and
+ 5841: a
+ 4788: to
+ 4619: in
+ 3034: his
+ 2712: he
+ 2431: I
+ 2391: with
+```
+
+## Installation
+
+### Manual
+
+Download the binaries from the [release
+page](https://github.com/vmchale/wordchoice/releases) for 64-bit Linux, ARM
+Linux, and 64-bit Windows.
+
+### Nix
+
+Install [nix](https://nixos.org/nix/), then type:
+
+```bash
+nix-env -i
+```
+
+to download the package for Mac or Linux.
+
+### Stack
+
+Install stack, following instructions 
+[here](https://docs.haskellstack.org/en/stable/README/). Then:
+
+```bash
+ $ stack install wordchoice
+```
+
+You might need to do a `stack setup` first. 
+
+### Build
+
+To build this repo, simply type:
+
+```bash
+ $ stack install
+```
+
+or
+
+```bash
+ $ cabal new-build
+```
+
+in the `wordchoice/` directory.
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/app/Main.hs b/app/Main.hs
new file mode 100644
--- /dev/null
+++ b/app/Main.hs
@@ -0,0 +1,6 @@
+module Main where
+
+import Data.Text.WordCount.Exec
+
+main :: IO ()
+main = exec
diff --git a/default.nix b/default.nix
new file mode 100644
--- /dev/null
+++ b/default.nix
@@ -0,0 +1,18 @@
+{ mkDerivation, base, bytestring, Chart, Chart-diagrams, containers
+, lens, optparse-applicative, pandoc, stdenv, system-filepath, text
+}:
+mkDerivation {
+  pname = "wordchoice";
+  version = "0.1.0.0";
+  src = ./.;
+  isLibrary = true;
+  isExecutable = true;
+  libraryHaskellDepends = [
+    base bytestring Chart Chart-diagrams containers lens
+    optparse-applicative pandoc system-filepath text
+  ];
+  executableHaskellDepends = [ base ];
+  testHaskellDepends = [ base ];
+  homepage = "https://github.com/githubuser/wordchoice#readme";
+  license = stdenv.lib.licenses.bsd3;
+}
diff --git a/release.nix b/release.nix
new file mode 100644
--- /dev/null
+++ b/release.nix
@@ -0,0 +1,5 @@
+let
+  pkgs = import <nixpkgs> { };
+
+in
+  pkgs.haskell.lib.justStaticExecutables (pkgs.haskellPackages.callPackage ./default.nix { })
diff --git a/src/Data/Text/WordCount.hs b/src/Data/Text/WordCount.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Text/WordCount.hs
@@ -0,0 +1,70 @@
+{-# LANGUAGE FlexibleContexts #-}
+
+module Data.Text.WordCount
+    ( topN
+    , displayWords
+    -- * For making graphs
+    , makeFile
+    , makeDistribution
+    -- * Low level-ish
+    , buildFreq
+    ) where
+
+import qualified Data.Map.Lazy as M
+import Data.Map.Lens
+import Control.Lens hiding (argument)
+import qualified Data.Text.Lazy as TL
+import Data.Tuple
+import Data.Monoid
+import Data.List
+import Data.Ord
+import Graphics.Rendering.Chart.Easy hiding (argument)
+import Graphics.Rendering.Chart.Backend.Diagrams
+import Data.Char
+
+-- | Return top n words and their frequencies
+--
+-- @
+-- >>> topN 2 "hello hello goodbye it is time is it why why why it it"
+-- [(4,"it"),(3,"why")]
+-- @
+topN :: Int -> TL.Text -> [(Int,TL.Text)]
+topN n = take n . order . buildFreq
+
+displayWords :: [(Int,TL.Text)] -> TL.Text
+displayWords [] = ""
+displayWords (pair:pairs) = display pair <> "\n" <> displayWords pairs
+    where display (n,str) = (TL.pack . show) n <> ": " <> str
+
+buildFreq :: TL.Text -> M.Map TL.Text Int
+buildFreq = count . TL.words . TL.map toLower
+
+order :: M.Map TL.Text Int -> [(Int, TL.Text)]
+order = sortBy (flip (comparing fst)) . fmap swap . M.toList
+
+count :: [TL.Text] -> M.Map TL.Text Int
+count words = foldr ((.) . wordFunction) id words M.empty
+    where wordFunction word map = case map ^. at word of
+            Nothing -> at word ?~ 1 $ map
+            _ -> ix word %~ (+1) $ map
+
+-- | Make a bar graph from the word frequencies
+-- 
+-- @
+-- makeFile :: IO ()
+-- makeFile [(4,"it"),(3,"why")] "out.html"
+-- @
+makeFile :: [(Int,TL.Text)] -> FilePath -> IO ()
+makeFile points out = toFile def out (makeDistribution points)
+
+makeDistribution points = do
+    let values = addIndexes (fmap fst points)
+    let alabels = fmap (TL.unpack . snd) points
+    let fillStyle = solidFillStyle (opaque lightblue)
+    layout_title .= "Word Frequencies"
+    layout_x_axis . laxis_generate .= autoIndexAxis alabels
+    layout_y_axis . laxis_override .= axisGridHide
+    layout_left_axis_visibility . axis_show_ticks .= False
+    plot $ fmap plotBars $ liftEC $ do
+        plot_bars_values .= [ (x,[y]) | (x,y) <- values ]
+        plot_bars_item_styles .= [ (fillStyle, Nothing) ]
diff --git a/src/Data/Text/WordCount/Exec.hs b/src/Data/Text/WordCount/Exec.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Text/WordCount/Exec.hs
@@ -0,0 +1,58 @@
+module Data.Text.WordCount.Exec where
+    
+import Data.Monoid
+import qualified Data.Text.Lazy.IO as TLIO
+import Paths_wordchoice
+import Options.Applicative
+import Data.Maybe
+import Data.Version
+import Data.Text.WordCount
+import Data.Text.WordCount.FileRead
+
+-- | Program datatype to be parsed
+data Program = Program { file :: FilePath 
+                       , num :: Maybe Int 
+                       , output :: Maybe FilePath } -- TODO add option for separators
+
+-- | Command line argument parser
+program :: Parser Program
+program = Program
+    <$> (argument str
+        (metavar "FILEPATH"
+        <> help "File to analyze"))
+    <*> (optional (read <$> strOption
+        (short 'n'
+        <> long "number"
+        <>  metavar "NUM"
+        <> help "Top NUM words will be listed")))
+    <*> (optional (strOption
+        (short 'o'
+        <> long "output"
+        <>  metavar "OUTPUT"
+        <> help "Filepath for output graph")))
+
+-- | Parse for version info
+versionInfo :: Parser (a -> a)
+versionInfo = infoOption 
+    ("wordchoice version: " ++ showVersion version) 
+    (short 'v' <> long "version" <> help "Show version")
+
+-- | Wraps parser with help parser
+wrapper :: ParserInfo Program
+wrapper = info (helper <*> versionInfo <*> program)
+    (fullDesc
+    <> progDesc "Word choice is a command-line meant to help you improve your writing. Simply point it to a file containing text and it will list your most frequently used words and their frequencies."
+    <> header "Word choice command-line utility")
+
+-- | Actual executable
+exec :: IO ()
+exec = execParser wrapper >>= pick
+
+-- | Run parsed record
+pick :: Program -> IO ()
+pick rec = let n = fromMaybe 25 (num rec) in do
+    contents <- processFile (file rec)
+    TLIO.putStrLn . displayWords . topN n $ contents 
+    case output rec of
+        (Just out) -> flip makeFile out . topN n $ contents
+        _ -> pure ()
diff --git a/src/Data/Text/WordCount/FileRead.hs b/src/Data/Text/WordCount/FileRead.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Text/WordCount/FileRead.hs
@@ -0,0 +1,32 @@
+-- | Module with function to read file in with pandoc and discard everything superfluous.
+module Data.Text.WordCount.FileRead where
+
+import Text.Pandoc
+import Filesystem.Path.CurrentOS as F
+import qualified Data.Text.Lazy as TL
+import qualified Data.Text.Lazy.IO as TLIO
+import qualified Data.ByteString.Lazy as BSL
+
+eitherError = either (error . show) id
+
+-- | Process a file given its filename. Return text only, discarding superflouous material.
+processFile :: String -> IO TL.Text
+processFile filepath = case (extension . decodeString $ filepath) of
+    (Just "md") -> TL.pack . writePlain def . filterCode . eitherError . readMarkdown def . TL.unpack <$> TLIO.readFile filepath
+    (Just "dbk") -> TL.pack . writePlain def . filterCode . eitherError . readDocBook def . TL.unpack <$> TLIO.readFile filepath
+    (Just "docx") -> TL.pack . writePlain def . filterCode . fst . eitherError . readDocx def <$> BSL.readFile filepath
+    (Just "epub") -> TL.pack . writePlain def . filterCode . fst . eitherError . readEPUB def <$> BSL.readFile filepath
+    (Just "html") -> TL.pack . writePlain def . filterCode . eitherError . readHtml def . TL.unpack <$> TLIO.readFile filepath
+    (Just "tex") -> TL.pack . writePlain def . filterCode . eitherError . readLaTeX def . TL.unpack <$> TLIO.readFile filepath
+    (Just "xml") -> TL.pack . writePlain def . filterCode . eitherError . readOPML def . TL.unpack <$> TLIO.readFile filepath
+    (Just "odt") -> TL.pack . writePlain def . filterCode . fst . eitherError . readOdt def <$> BSL.readFile filepath
+    (Just "rst") -> TL.pack . writePlain def . filterCode . eitherError . readRST def . TL.unpack <$> TLIO.readFile filepath
+    (Just "textile") -> TL.pack . writePlain def . filterCode . eitherError . readTextile def . TL.unpack <$> TLIO.readFile filepath
+    _ -> TLIO.readFile filepath
+
+-- | Filter out code and tables from the document
+filterCode :: Pandoc -> Pandoc
+filterCode (Pandoc meta content) = Pandoc meta $ filter rightBlock content
+    where rightBlock CodeBlock { } = False
+          rightBlock Table { }     = False
+          rightBlock _             = True
diff --git a/stack.yaml b/stack.yaml
new file mode 100644
--- /dev/null
+++ b/stack.yaml
@@ -0,0 +1,66 @@
+# This file was automatically generated by 'stack init'
+#
+# Some commonly used options have been documented as comments in this file.
+# For advanced use and comprehensive documentation of the format, please see:
+# http://docs.haskellstack.org/en/stable/yaml_configuration/
+
+# Resolver to choose a 'specific' stackage snapshot or a compiler version.
+# A snapshot resolver dictates the compiler version and the set of packages
+# to be used for project dependencies. For example:
+#
+# resolver: lts-3.5
+# resolver: nightly-2015-09-21
+# resolver: ghc-7.10.2
+# resolver: ghcjs-0.1.0_ghc-7.10.2
+# resolver:
+#  name: custom-snapshot
+#  location: "./custom-snapshot.yaml"
+resolver: lts-8.12
+
+# User packages to be built.
+# Various formats can be used as shown in the example below.
+#
+# packages:
+# - some-directory
+# - https://example.com/foo/bar/baz-0.0.2.tar.gz
+# - location:
+#    git: https://github.com/commercialhaskell/stack.git
+#    commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a
+# - location: https://github.com/commercialhaskell/stack/commit/e7b331f14bcffb8367cd58fbfc8b40ec7642100a
+#   extra-dep: true
+#  subdirs:
+#  - auto-update
+#  - wai
+#
+# A package marked 'extra-dep: true' will only be built if demanded by a
+# non-dependency (i.e. a user package), and its test suites and benchmarks
+# will not be run. This is useful for tweaking upstream packages.
+packages:
+- '.'
+# Dependency packages to be pulled from upstream that are not in the resolver
+# (e.g., acme-missiles-0.3)
+extra-deps: []
+
+# Override default flag values for local packages and extra-deps
+flags: {}
+
+# Extra package databases containing global packages
+extra-package-dbs: []
+
+# Control whether we use the GHC we find on the path
+# system-ghc: true
+#
+# Require a specific version of stack, using version ranges
+# require-stack-version: -any # Default
+# require-stack-version: ">=1.4"
+#
+# Override the architecture used by stack, especially useful on Windows
+# arch: i386
+# arch: x86_64
+#
+# Extra directories used by stack for building
+# extra-include-dirs: [/path/to/dir]
+# extra-lib-dirs: [/path/to/dir]
+#
+# Allow a newer minor version of GHC than the snapshot specifies
+# compiler-check: newer-minor
diff --git a/test/Spec.hs b/test/Spec.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec.hs
@@ -0,0 +1,2 @@
+main :: IO ()
+main = putStrLn "Test suite not yet implemented"
diff --git a/wordchoice.cabal b/wordchoice.cabal
new file mode 100644
--- /dev/null
+++ b/wordchoice.cabal
@@ -0,0 +1,57 @@
+name:                wordchoice
+version:             0.1.0.0
+synopsis:            Get word counts and distributions
+description:         A command line tool to compute the word distribution from various types of document, converting to text with pandoc.
+homepage:            https://github.com/githubuser/wordchoice#readme
+license:             BSD3
+license-file:        LICENSE
+author:              Author name here
+maintainer:          example@example.com
+copyright:           2017 Author name here
+category:            Web
+build-type:          Simple
+extra-source-files:  README.md
+                   , stack.yaml
+                   , default.nix
+                   , release.nix
+cabal-version:       >=1.10
+
+library
+  hs-source-dirs:      src
+  exposed-modules:     Data.Text.WordCount
+                     , Data.Text.WordCount.Exec
+  other-modules:       Paths_wordchoice
+                     , Data.Text.WordCount.FileRead
+  build-depends:       base >= 4.7 && < 5
+                     , pandoc
+                     , containers
+                     , text
+                     , optparse-applicative
+                     , Chart
+                     , bytestring
+                     , system-filepath
+                     , Chart-diagrams
+                     , lens
+  default-language:    Haskell2010
+  default-extensions:  OverloadedStrings
+
+executable wordchoice
+  hs-source-dirs:      app
+  main-is:             Main.hs
+  ghc-options:         -threaded -rtsopts -with-rtsopts=-N
+  build-depends:       base
+                     , wordchoice
+  default-language:    Haskell2010
+
+test-suite wordchoice-test
+  type:                exitcode-stdio-1.0
+  hs-source-dirs:      test
+  main-is:             Spec.hs
+  build-depends:       base
+                     , wordchoice
+  ghc-options:         -threaded -rtsopts -with-rtsopts=-N
+  default-language:    Haskell2010
+
+source-repository head
+  type:     git
+  location: https://github.com/githubuser/wordchoice
