diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,84 @@
+[![Build Status](https://travis-ci.org/stackbuilders/hapistrano.svg?branch=master)](https://travis-ci.org/stackbuilders/hapistrano) [![Hackage version](https://img.shields.io/hackage/v/hapistrano.svg)](http://hackage.haskell.org/package/hapistrano)
+
+# Hapistrano
+
+Hapistrano is a deployment library for Haskell applications similar to
+Ruby's [Capistrano](http://capistranorb.com/).
+
+## Purpose
+
+We created Hapistrano because:
+
+* Deploys should be simple, but as close to atomic as possible (eg,
+  they shouldn't require much application downtime).
+* Rollback should be trivial to achieve to bring the application back
+  to the last-deployed state.
+* Deploys shouldn't fail because of dependency problems.
+
+## How it Works
+
+Hapistrano (like Capistrano for Ruby) deploys applications to a new
+directory marked with a timestamp on the remote host. It creates this
+new directory quickly by placing a git repository for caching purposes
+on the remote server.
+
+When the build process completes, it switches a symlink to the
+'current' release directory, and optionally restarts the web server.
+
+By default, Hapistrano keeps the last five releases on the target host
+filesystem and deletes previous releases to avoid filling up the disk.
+
+## Usage
+
+The deploy requires the following environment variables:
+
+* `DEPLOY_PATH` - The root of the deploy target on the remote host
+* `HOST` - The target host
+* `REPOSITORY` - The origin repository
+* `REVISION` - The SHA1 or branch to deploy. If a branch, you will need
+  to specify it as origin/branch_name due to the way that the cache
+  repo is configured.
+
+The following environment variables are *optional* and affect the
+deploy process:
+
+* `BUILD_SCRIPT` - The local path to a file that should be executed on
+  the remote server to build the application. The script isn't
+  executed verbatim - instead, every line is joined with `&&` so that
+  the script aborts if any component fails. See a sample script for a
+  clean build of a Haskell/Cabal application in this project under
+  [script/clean-build.sh].
+* `RESTART_COMMAND` - If you need to restart a remote web server after a
+  successful deploy, specify the command that you use in this
+  variable. It will be run after both deploy and rollback.
+
+You may want to save the environment variables that you need for your
+deploy in a shell script that you `source` before deploy. Make sure
+you `export` these variables so that they're available in the shell
+after you run the script. For example, you could use the following to
+configure your deploy:
+
+    export DEPLOY_PATH="/var/project"
+    export HOST="my-app-staging"
+    export REPOSITORY="git@github.com:yourorg/yourrepo.com.git"
+    export REVISION="origin/staging"
+    export BUILD_SCRIPT="/home/you/Code/hapistrano/script/clean-build.sh"
+    export RESTART_COMMAND="echo Replace me with your restart command"
+
+After creating a configuration script as above, deploying is as simple as:
+
+    source your-config-script.sh && hap deploy
+
+# License
+
+MIT, see [the LICENSE file](LICENSE).
+
+
+# Contributing
+
+Pull requests for modifications to this program are welcome. Fork and
+open a PR. Feel free to [email me](mailto:justin@stackbuilders.com) if
+you have questions about what may be accepted before working on a PR.
+
+If you're looking for a place to start, you may want to check the
+[open issue](https://github.com/stackbuilders/hapistrano/issues).
diff --git a/app/Main.hs b/app/Main.hs
--- a/app/Main.hs
+++ b/app/Main.hs
@@ -1,14 +1,21 @@
-module Main where
+{-# LANGUAGE RecordWildCards #-}
 
+module Main (main) where
+
 import qualified System.Hapistrano as Hap
 import Control.Monad (void)
-import System.Environment (getArgs, getEnv)
 import System.Environment.Compat (lookupEnv)
-import System.IO (hPutStrLn, stderr)
-import System.Exit (exitFailure)
 
 import System.Hapistrano (ReleaseFormat(..))
 
+import qualified Control.Monad as Monad
+import qualified Data.Maybe as Maybe
+import qualified System.Console.GetOpt as GetOpt
+import qualified System.Environment as Environment
+import qualified System.Exit as Exit
+import qualified System.Exit.Compat as Exit
+import qualified System.IO as IO
+
 -- | Rolls back to previous release.
 rollback :: Hap.Config -> IO ()
 rollback cfg =
@@ -36,15 +43,18 @@
 -- | Retrieves the configuration from environment variables.
 configFromEnv :: IO Hap.Config
 configFromEnv = do
-  deployPath     <- getEnv    "DEPLOY_PATH"
-  repository     <- getEnv    "REPOSITORY"
-  revision       <- getEnv    "REVISION"
+  maybeDeployPath <- lookupEnv "DEPLOY_PATH"
+  maybeRepository <- lookupEnv "REPOSITORY"
+  maybeRevision <- lookupEnv "REVISION"
 
+  deployPath <- maybe (Exit.die (noEnv "DEPLOY_PATH")) return maybeDeployPath
+  repository <- maybe (Exit.die (noEnv "REPOSITORY")) return maybeRepository
+  revision <- maybe (Exit.die (noEnv "REVISION")) return maybeRevision
+
   host           <- lookupEnv "HOST"
   buildScript    <- lookupEnv "BUILD_SCRIPT"
   restartCommand <- lookupEnv "RESTART_COMMAND"
 
-
   return Hap.Config { Hap.deployPath     = deployPath
                     , Hap.host           = host
                     , Hap.releaseFormat  = Short
@@ -53,22 +63,85 @@
                     , Hap.buildScript    = buildScript
                     , Hap.restartCommand = restartCommand
                     }
+  where
+    noEnv env = env ++ " environment variable does not exist"
 
+data HapCommand
+  = HapDeploy
+  | HapRollback
+  deriving Show
+
+parseHapCommand :: String -> Maybe HapCommand
+parseHapCommand "deploy" = Just HapDeploy
+parseHapCommand "rollback" = Just HapRollback
+parseHapCommand _ = Nothing
+
+data HapOptions =
+  HapOptions
+    { hapCommand :: Maybe HapCommand
+    , hapHelp :: Bool
+    }
+  deriving Show
+
+defaultHapOptions :: HapOptions
+defaultHapOptions =
+  HapOptions
+    { hapCommand = Nothing
+    , hapHelp = False
+    }
+
+hapOptionDescriptions :: [GetOpt.OptDescr (HapOptions -> HapOptions)]
+hapOptionDescriptions =
+  [ GetOpt.Option
+      ['h']
+      ["help"]
+      (GetOpt.NoArg (\hapOptions -> hapOptions { hapHelp = True }))
+      "Show this help text"
+
+  ]
+
+parseHapOptions :: [String] -> Either String HapOptions
+parseHapOptions args =
+  case GetOpt.getOpt GetOpt.Permute hapOptionDescriptions args of
+    (options, [], []) ->
+      Right (foldl (flip id) defaultHapOptions options)
+
+    (options, [command], []) ->
+      case parseHapCommand command of
+        Nothing ->
+          Left ("Invalid argument: " ++ command)
+
+        maybeHC ->
+          Right (foldl (flip id) defaultHapOptions {hapCommand = maybeHC} options)
+
+    _ ->
+      Left "First argument must be either 'deploy' or 'rollback'."
+
+hapHelpAction :: Maybe HapCommand -> IO ()
+hapHelpAction _ =
+  putStrLn hapUsage >> Exit.exitSuccess
+
+hapUsage :: String
+hapUsage =
+  GetOpt.usageInfo hapUsageHeader hapOptionDescriptions
+
+hapUsageHeader :: String
+hapUsageHeader =
+  "usage: hap [-h | --help] <command>\n"
+
 main :: IO ()
 main = do
-  args <- getArgs
-  case args of
-    [] -> do
-      hPutStrLn stderr
-        "First argument must be either 'deploy' or 'rollback'."
-      exitFailure
+  eitherHapOptions <- fmap parseHapOptions Environment.getArgs
 
-    arg1:_ -> do
-      cfg <- configFromEnv
+  HapOptions{..} <- either Exit.die return eitherHapOptions
 
-      case arg1 of
-        "deploy"   -> deploy cfg
-        "rollback" -> rollback cfg
-        _ -> do
-          hPutStrLn stderr $ "Invalid argument: " ++ arg1
-          exitFailure
+  Monad.when hapHelp (hapHelpAction hapCommand)
+
+  hapConfiguration <- configFromEnv
+
+  case hapCommand of
+    Just HapDeploy -> deploy hapConfiguration
+
+    Just HapRollback -> rollback hapConfiguration
+
+    Nothing -> hapHelpAction Nothing
diff --git a/changes.md b/changes.md
new file mode 100644
--- /dev/null
+++ b/changes.md
@@ -0,0 +1,13 @@
+## Unreleased changes
+
+* Add change log (#23).
+
+## 0.2.1.1
+
+* Fix tests (#31).
+
+## 0.2.1
+
+* Use Stack (#17).
+* Clean up package (#20).
+* Fix tests (#25).
diff --git a/hapistrano.cabal b/hapistrano.cabal
--- a/hapistrano.cabal
+++ b/hapistrano.cabal
@@ -1,5 +1,5 @@
 name:                hapistrano
-version:             0.2.1.1
+version:             0.2.1.2
 synopsis:            A deployment library for Haskell applications
 description:
   .
@@ -28,12 +28,13 @@
 bug-reports:         https://github.com/stackbuilders/hapistrano/issues
 build-type:          Simple
 cabal-version:       >=1.10
+extra-source-files:  changes.md README.md
 
 library
   hs-source-dirs:      src
   exposed-modules:     System.Hapistrano
   other-modules:       System.Hapistrano.Types
-  build-depends:       base >=4.5 && <4.9
+  build-depends:       base >= 4.5 && < 4.10
                      , either
                      , filepath
                      , mtl
