diff --git a/ChangeLog.md b/ChangeLog.md
new file mode 100644
--- /dev/null
+++ b/ChangeLog.md
@@ -0,0 +1,21 @@
+# 1.1.1
+
+ - bugfix: Show cursor in empty entry widget
+ - bugfix: Correctly execute `--help` and `--dump-default-config` in
+   the presence of syntax errors in the config file
+
+# 1.1
+
+ - Add a configuration file for persistent settings
+ - Disallow unbalanced transactions
+ - Order postings naturally and omit balancing amounts in transaction preview (thanks Tristan Hume)
+ - Suggest account based on last transaction if no similar transaction is found (thanks Tristan Hume)
+ - Make completed dates as recent as possible (thanks Thorsten Wißmann)
+ - Optional fuzzy matching via config option "completion-engine" (thanks Tristan Hume)
+ - Add Ctrl-d as new keybinding for 'quit'
+ - Make ESC quit at the toplevel
+ - Various bug fixes
+
+# 1.0
+
+ - Initial release
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,162 @@
+# hledger-iadd
+
+An interactive terminal UI as drop-in replacement for `hledger add`.
+
+![Screencast](doc/screencast.gif)
+
+## Features
+
+This project improves in the following ways on hledger's `add` command:
+
+ - Interactive as-you-type completion for account names and
+   descriptions with optional fuzzy matching (see [below](#configuration-file)).
+
+ - Integrated calculator: Amounts can be written as simple sums with
+   real-time feedback on the result.
+
+ - All actions while entering a transaction can be undone
+
+ - Configurable format for date input. Instead of `y/m/d` it is also
+   possible to use other formats like the german `d.m.y`.
+
+## Installation
+### stack
+
+The easiest method would be [stack]: Install the [stack] program, `cd`
+to `hledger-iadd`s source directory and type:
+
+    stack install
+
+To build and install all Haskell dependencies locally and install
+`hledger-iadd` to `~/.local/bin`. See `stack --help` for more options.
+You may get asked to install the GHC Haskell compiler locally. To do
+that, type `stack setup`.
+
+### Cabal
+
+First, install the GHC Haskell compiler and the `cabal install`,
+`alex` and `happy` build tools, possibly from your distribution or the
+[haskell platform].
+
+Since `cabal` builds regularly break in non-isolated environments, the
+recommended next step is to create a cabal sandbox where all
+dependencies will be installed in:
+
+    cd hledger-iadd
+	cabal sandbox init
+
+You can now download and install all dependencies locally with
+
+    cabal install --only-dependencies
+
+And finally you're ready to build and install `hledger-iadd`:
+
+    cabal configure --bindir ~/bin
+	cabal build
+	cabal copy
+
+## Usage
+
+You can start the program either with
+
+    hledger iadd
+
+or simply `hledger-iadd`.
+
+The following command line options are available:
+
+  - `-f/--file/`: Path to the journal file. (Default: `~/.hledger.journal`)
+  - `--date-format`: Format for parsing dates. (Default:
+    `[[%y/]%m/]%d`, the usual ledger date format). Brackets can be
+    used to specify optional parts. E.g the german date format would
+    be `%d[.[%m[.[%y]]]]`
+  - `--completion-engine`: Algorithm for account name completion. Can
+    be `substrings` or `fuzzy`.
+  - `--dump-default-config`: Print the example config file to stdout
+    and exit
+
+The UI is partitioned in 4 regions:
+
+    Current Transaction (view of your work in progress)
+	---------------------------------------------------
+	Question: [ text area                             ]
+	---------------------------------------------------
+	Context information (e.g. list of accounts)
+
+
+
+
+	---------------------------------------------------
+	Message area
+
+For each transaction, you will get asked the following questions in
+order:
+
+ 1. Date?
+ 2. Description?
+ 3. Account name?
+ 4. Amount?
+ 5. The last two questions are repeated until you enter the empty account
+ 6. Do you want to add this transaction to the journal?
+
+To accept the default answer, immediately press <kbd>Return</kbd> at a
+promt.
+
+While you type, the context area shows possible completions. Pressing
+<kbd>Return</kbd> answers the question with the currently selected
+completion. You can select differnt completions with <kbd>C-n</kbd>
+and <kbd>C-p</kbd>.
+
+The following keyboard shortcuts are available:
+
+| Key                             | Function                                                                      |
+| ------------------------------- | ----------------------------------------------------------------------------- |
+| <kbd>C-c</kbd>, <kbd>C-d</kbd>  | Quit the program without saving the current transaction                       |
+| <kbd>Esc</kbd>                  | Abort the current transaction or exit when at toplevel                        |
+| <kbd>Ret</kbd>                  | Accept the currently selected answer                                          |
+| <kbd>Alt-Ret</kbd>              | Accept the current answer verbatim from the text area, ignoring the selection |
+| <kbd>C-z</kbd>                  | Undo the last action                                                          |
+| <kbd>Tab</kbd>                  | Insert the currently selected answer into the text area                       |
+| <kbd>C-n</kbd>,<kbd>↓</kbd>     | Select the next context item                                                  |
+| <kbd>C-p</kbd>,<kbd>↑</kbd>     | Select the previous context item                                              |
+| <kbd>F1</kbd>,<kbd>Alt-?</kbd>  | Show help dialog                                                              |
+
+## Default Currency
+
+To make entry easier it is recommended that you set a [default commodity](http://hledger.org/manual.html#default-commodity)
+in your ledger file if you haven't already done so.
+That way when entering amounts, `hledger-iadd` will add the symbols for you.
+You can do this by adding a line like below to the top of your ledger file:
+
+```lisp
+; sets the default commodity symbol and placement, thousands separator, and decimal symbol
+D $1,000.00
+```
+
+## Configuration File
+
+`hledger-iadd` is optionally configurable through a configuration file
+in `${XDG_CONFIG_HOME}/hledger-iadd/config.conf`. This file consists
+of simple
+
+    key = value
+
+assignments on individual lines with whitespace or comments starting
+with `#` between them. The default config can be obtained by
+passing `--dump-default-config` to `hledger-iadd`.
+
+The following options are currently available:
+
+  - `file`: Path to the journal file.
+  - `date-format`: The date format. See the documentation for
+    `--date-format` for details.
+  - `completion-engine`: Algorithm used to find completions for
+    account names. Possible values are:
+	- `substrings`: Every word in the search string has to occur
+      somewhere in the account name
+	- `fuzzy`: All letters from the search string have to appear in
+      the name in the same order
+
+
+[stack]: https://github.com/commercialhaskell/stack
+[haskell platform]: https://www.haskell.org/platform/
diff --git a/doc/screencast.gif b/doc/screencast.gif
new file mode 100644
Binary files /dev/null and b/doc/screencast.gif differ
diff --git a/hledger-iadd.cabal b/hledger-iadd.cabal
--- a/hledger-iadd.cabal
+++ b/hledger-iadd.cabal
@@ -1,20 +1,42 @@
 name:                hledger-iadd
-version:             1.1
+version:             1.1.1
 synopsis:            A terminal UI as drop-in replacement for hledger add
-description:         Please see README.md
-homepage:            http://github.com/rootzlevel/hledger-iadd#readme
+description:         This is a terminal UI as drop-in replacement for hledger add.
+                     .
+                     It improves in the following ways on hledger's add command:
+                     .
+                       * Interactive as-you-type completion for
+                         account names and descriptions with optional
+                         fuzzy matching.
+                       * Integrated calculator: Amounts can be written
+                         as simple sums with real-time feedback on the
+                         result.
+                       * All actions while entering a transaction can
+                         be undone
+                       * Configurable format for date input. Instead
+                         of @y\/m\/d@ it is also possible to use other
+                         formats like the german @d.m.y@.
+
+homepage:            https://github.com/hpdeifel/hledger-iadd#readme
+bug-reports:         https://github.com/hpdeifel/hledger-iadd/issues
 license:             BSD3
 license-file:        LICENSE
-author:              Hans-Peter Deifel
-maintainer:          hpd@hpdeifel.de
+author:              Hans-Peter Deifel <hpd@hpdeifel.de>
+maintainer:          Hans-Peter Deifel <hpd@hpdeifel.de>
 copyright:           2016 Hans-Peter Deifel
 category:            Finance, Console
 build-type:          Simple
 cabal-version:       >=1.10
+tested-with:         GHC==7.10.3, GHC==8.0
                      
+extra-source-files:
+  doc/screencast.gif
+  README.md
+  ChangeLog.md
+
 source-repository head
   type: git
-  location: https://github.com/rootzlevel/hledger-iadd.git
+  location: https://github.com/hpdeifel/hledger-iadd.git
   
 library
   hs-source-dirs:      src
@@ -78,6 +100,7 @@
   main-is:            Spec.hs
   other-modules:      DateParserSpec
                     , ConfigParserSpec
+                    , AmountParserSpec
   default-language:   Haskell2010
   build-depends:      base >= 4.8 && < 5
                     , hledger-iadd
diff --git a/src/ConfigParser.hs b/src/ConfigParser.hs
--- a/src/ConfigParser.hs
+++ b/src/ConfigParser.hs
@@ -100,7 +100,7 @@
 instance Show ConfParseError where
   show (SyntaxError e) = parseErrorPretty e
   show (UnknownOption pos key) =
-    show pos ++ ": Unknown option " ++ T.unpack key
+    sourcePosPretty pos ++ ": Unknown option " ++ T.unpack key ++ "\n"
   show (TypeError e) = parseErrorPretty e
 
 -- | Class for supported option types.
diff --git a/src/main/Main.hs b/src/main/Main.hs
--- a/src/main/Main.hs
+++ b/src/main/Main.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE OverloadedStrings, LambdaCase #-}
 
@@ -15,6 +17,7 @@
 import           Control.Monad
 import           Control.Monad.IO.Class
 import           Control.Monad.Trans.Except
+import           Data.Functor.Identity
 import           Data.Maybe
 import           Data.Monoid
 import           Data.Text (Text)
@@ -25,8 +28,8 @@
 import qualified Hledger as HL
 import qualified Hledger.Read.JournalReader as HL
 import           Lens.Micro
-import           Options.Applicative hiding (str, option)
 import qualified Options.Applicative as OA
+import           Options.Applicative hiding (str, option)
 import           System.Directory
 import           System.Environment.XDG.BaseDir
 import           System.Exit
@@ -261,7 +264,53 @@
 addToJournal :: HL.Transaction -> FilePath -> IO ()
 addToJournal trans path = appendFile path (HL.showTransaction trans)
 
+--------------------------------------------------------------------------------
+-- Command line and config parsing
+--------------------------------------------------------------------------------
 
+data CommonOptions f = CommonOptions
+  { optLedgerFile :: f FilePath
+  , optDateFormat :: f String
+  , optMatchAlgo  :: f MatchAlgo
+  }
+
+instance Monoid (CommonOptions Maybe) where
+  mappend opt1 opt2 =
+    let opt1' = optNatTrans First opt1
+        opt2' = optNatTrans First opt2
+    in optNatTrans getFirst $ CommonOptions
+       { optLedgerFile = optLedgerFile opt1' <> optLedgerFile opt2'
+       , optDateFormat = optDateFormat opt1' <> optDateFormat opt2'
+       , optMatchAlgo = optMatchAlgo opt1' <> optMatchAlgo opt2'
+       }
+
+  mempty = CommonOptions Nothing Nothing Nothing
+
+optNatTrans :: Functor f => (forall a. f a -> g a) -> CommonOptions f -> CommonOptions g
+optNatTrans nat opts = CommonOptions
+  { optLedgerFile = nat $ optLedgerFile opts
+  , optDateFormat = nat $ optDateFormat opts
+  , optMatchAlgo = nat $ optMatchAlgo opts
+  }
+
+optFromJust :: CommonOptions Identity -> CommonOptions Maybe -> CommonOptions Identity
+optFromJust def opts =
+  optNatTrans (Identity . fromJust) ( opts <> optNatTrans (Just . runIdentity) def)
+
+data CmdLineOptions = CmdLineOptions
+  { cmdCommon :: CommonOptions Maybe
+  , cmdDumpConfig :: Bool
+  }
+
+data ConfOptions = ConfOptions { confCommon :: CommonOptions Maybe }
+
+defaultOptions :: FilePath -> CommonOptions Identity
+defaultOptions home = CommonOptions
+  { optLedgerFile = Identity (ledgerPath home)
+  , optDateFormat = Identity "[[%y/]%m/]%d"
+  , optMatchAlgo = Identity Substrings
+  }
+
 ledgerPath :: FilePath -> FilePath
 ledgerPath home = home <> "/.hledger.journal"
 
@@ -282,98 +331,107 @@
       | str == "substrings" = return Substrings
       | otherwise = Left "Expected \"fuzzy\" or \"substrings\""
 
-data Options = Options
-  { optLedgerFile :: FilePath
-  , optDateFormat :: String
-  , optMatchAlgo :: MatchAlgo
-  , optDumpConfig :: Bool
-  }
-
-confParser :: FilePath -> OptParser Options
-confParser home = Options
+-- | Parser for our config file
+confParser :: CommonOptions Identity -> OptParser ConfOptions
+confParser def = fmap ConfOptions $ CommonOptions
   -- TODO Convert leading tilde to home
-  <$> option "file" (ledgerPath home) "Path to the journal file"
-  <*> option "date-format" "[[%y/]%m/]%d" "Format used to parse dates"
-  <*> customOption "completion-engine" Substrings "substrings"
+  <$> (Just <$> option "file" (runIdentity $ optLedgerFile def) "Path to the journal file")
+  <*> (Just <$> option "date-format" (runIdentity $ optDateFormat def) "Format used to parse dates")
+  <*> (Just <$> customOption "completion-engine" matchAlgo (T.toLower $ T.pack $ show matchAlgo)
       ( "Algorithm used to find completions for account names. Possible values are:\n"
       <> "  - substrings: Every word in the search string has to occur somewhere in the account name\n"
       <> "  - fuzzy: All letters from the search string have to appear in the name in the same order"
       )
       "string"
       parseMatchAlgo
-  <*> pure False
+      )
 
-parseConfigFile :: IO Options
+  where matchAlgo = runIdentity (optMatchAlgo def)
+
+-- | IO Action to read and parse config file
+parseConfigFile :: IO ConfOptions
 parseConfigFile = do
   path <- configPath
   home <- getHomeDirectory
+  let def = defaultOptions home
 
   try (T.readFile path) >>= \case
-    Left (_ :: SomeException) -> return (parserDefault $ confParser home)
-    Right res -> case parseConfig path res (confParser home) of
+    Left (_ :: SomeException) -> return (parserDefault $ confParser def)
+    Right res -> case parseConfig path res (confParser def) of
       Left err -> do
         putStr (show err)
         exitFailure
       Right res' -> return res'
 
-optionParser :: Options -> Parser Options
-optionParser def = Options
-  <$> strOption
-        (  long "file"
-        <> short 'f'
-        <> metavar "FILE"
-        <> value (optLedgerFile def)
-        <> help "Path to the journal file"
-        )
-  <*> strOption
-        (  long "date-format"
-        <> metavar "FORMAT"
-        <> value (optDateFormat def)
-        <> help "Format used to parse dates"
-        )
-  <*> OA.option readMatchAlgo
-        (  long "completion-engine"
-        <> metavar "ENGINE"
-        <> value (optMatchAlgo def)
-        <> help "Algorithm for account name completion. Possible values: \"fuzzy\", \"substrings\"")
+-- | command line option parser
+cmdOptionParser :: Parser CmdLineOptions
+cmdOptionParser = CmdLineOptions
+  <$> (CommonOptions
+       <$> OA.option (Just <$> OA.str)
+           (  long "file"
+           <> short 'f'
+           <> metavar "FILE"
+           <> value Nothing
+           <> help "Path to the journal file"
+           )
+       <*> OA.option (Just <$> OA.str)
+             (  long "date-format"
+             <> metavar "FORMAT"
+             <> value Nothing
+             <> help "Format used to parse dates"
+             )
+      <*> OA.option (Just <$> readMatchAlgo)
+            (  long "completion-engine"
+            <> metavar "ENGINE"
+            <> value Nothing
+            <> help "Algorithm for account name completion. Possible values: \"fuzzy\", \"substrings\"")
+      )
   <*> switch
         ( long "dump-default-config"
        <> help "Print an example configuration file to stdout and exit"
         )
 
+--------------------------------------------------------------------------------
+-- main
+--------------------------------------------------------------------------------
+
 main :: IO ()
 main = do
-  opts1 <- parseConfigFile
+  home <- getHomeDirectory
+  path <- configPath
+  let defOpts = defaultOptions home
 
-  opts <- execParser $ info (helper <*> optionParser opts1) $
-            fullDesc <> header "A terminal UI as drop-in replacement for hledger add."
+  cmdOpts <- execParser $ info (helper <*> cmdOptionParser) $
+               fullDesc <> header "A terminal UI as drop-in replacement for hledger add."
 
-  when (optDumpConfig opts) $ do
-    home <- getHomeDirectory
-    path <- configPath
+  when (cmdDumpConfig cmdOpts) $ do
     T.putStrLn $ "# Write this to " <> T.pack path <> "\n"
-    T.putStrLn (parserExample $ confParser home)
+    T.putStrLn (parserExample $ confParser defOpts)
     exitSuccess
 
-  date <- case parseDateFormat (T.pack $ optDateFormat opts) of
+  confOpts <- parseConfigFile
+
+  let opts = optFromJust defOpts $ cmdCommon cmdOpts <> confCommon confOpts
+
+  date <- case parseDateFormat (T.pack $ runIdentity $ optDateFormat opts) of
     Left err -> do
       hPutStr stderr "Could not parse date format: "
       T.hPutStr stderr err
       exitWith (ExitFailure 1)
     Right res -> return res
 
-  let path = optLedgerFile opts
+  let path = runIdentity $ optLedgerFile opts
   journalContents <- T.readFile path
 
   runExceptT (HL.parseAndFinaliseJournal HL.journalp True path journalContents) >>= \case
     Left err -> hPutStrLn stderr err >> exitFailure
     Right journal -> do
-      let edit = editor EditorName (txt . T.concat) (Just 1) ""
+      let edit = editor EditorName (nonEmptyTxt . T.concat) (Just 1) ""
 
       sugg <- suggest journal date DateQuestion
 
       let welcome = "Welcome! Press F1 (or Alt-?) for help. Exit with Ctrl-d."
-          matchAlgo = optMatchAlgo opts
+          matchAlgo = runIdentity $ optMatchAlgo opts
           as = AppState edit DateQuestion journal (ctxList V.empty) sugg welcome path date matchAlgo NoDialog
 
       void $ defaultMain app as
@@ -390,3 +448,12 @@
 
 ctxList :: V.Vector e -> List Name e
 ctxList v = (if V.null v then id else listMoveTo 0) $ list ListName v 1
+
+-- | Workaround for bug in brick's edit widget
+--
+-- Since brick version 0.15, an empty edit widget wouldn't show a cursor, so
+-- this artificially adds a space to empty input text.
+nonEmptyTxt :: Text -> Widget n
+nonEmptyTxt input
+  | T.null input = txt " "
+  | otherwise    = txt input
diff --git a/tests/AmountParserSpec.hs b/tests/AmountParserSpec.hs
new file mode 100644
--- /dev/null
+++ b/tests/AmountParserSpec.hs
@@ -0,0 +1,40 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module AmountParserSpec (spec) where
+
+import           Test.Hspec
+
+import           Control.Monad.Trans.State.Strict
+import           Data.Either
+import           Data.Functor.Identity
+import           Data.Text (Text)
+import qualified Hledger as HL
+import           Text.Megaparsec
+
+import           AmountParser
+
+spec :: Spec
+spec = describe "parseAmount" $ do
+  it "parses single amount" $
+    parseAmount HL.nulljournal "42" `shouldBe` Right (amount "42")
+
+  it "parses a positive number" $
+    parseAmount HL.nulljournal "+42" `shouldBe` Right (amount "42")
+
+  it "parses a negative number" $
+    parseAmount HL.nulljournal "-42" `shouldBe` Right (amount "-42")
+
+  it "parses a simple sum" $
+    parseAmount HL.nulljournal "23 + 23 + 42 + 1" `shouldBe` Right (amount "89")
+
+  it "parses a sum with negative values" $
+    parseAmount HL.nulljournal "-42 + 23 + 42 - 23 + 1" `shouldBe` Right (amount "1")
+
+  it "fails to parse a trailing plus" $
+    parseAmount HL.nulljournal "23 +" `shouldSatisfy` isLeft
+
+amount :: Text -> HL.MixedAmount
+amount = HL.mixed . pure . fromRight . runIdentity . runParserT (evalStateT HL.amountp HL.nulljournal) ""
+
+fromRight :: Either a b -> b
+fromRight = either (error "fromRight: Left value encountered") id
