diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+# 0.0.4
+
+* Documentation received some love.
+
+* A few renames of repurposed internals.
+
 # 0.0.3
 
 * Debugging facilities for ghci have been added. Check out the
diff --git a/TestPlugins.hs b/TestPlugins.hs
--- a/TestPlugins.hs
+++ b/TestPlugins.hs
@@ -12,16 +12,16 @@
 -- The script `TestPlugins.vim` comments how these functions should behave.
 
 main :: IO ()
-main = realMain finalizer Nothing defaultConfig
+main = realMain transitionHandler Nothing defaultConfig
     { plugins = [ randPlugin ]
     }
-
-finalizer tids cfg = takeMVar (Internal.quit cfg) >>= \case
-    Internal.InitSuccess ->
-        finalizer tids cfg
+  where
+    transitionHandler tids cfg = takeMVar (Internal.transitionTo cfg) >>= \case
+        Internal.InitSuccess ->
+            transitionHandler tids cfg
 
-    _ ->
-        mapM_ killThread tids
+        _ ->
+            mapM_ killThread tids
 
 randPlugin :: Neovim (StartupConfig NeovimConfig) () NeovimPlugin
 randPlugin = do
diff --git a/library/Neovim.hs b/library/Neovim.hs
--- a/library/Neovim.hs
+++ b/library/Neovim.hs
@@ -11,10 +11,8 @@
 This module should contain all the things you need to write neovim plugins in
 your favorite language! @:-)@
 
-The documentation in this module should enable you to write plugins.
-The chapters in this module start with a tl;dr paragraph that sums things up,
-which is useful to get an idea whether you should actually read the chapter and
-which will reduce your reading time if you just want to refresh your memory.
+The documentation in this module should provide every information you need to start
+writing plugins.
 -}
 module Neovim (
     -- * Installation
@@ -26,7 +24,7 @@
 
     -- * Tutorial
     -- ** tl;dr
-    -- $tldrtutorial
+    -- $tldrgettingstarted
     Neovim,
     Neovim',
     neovim,
@@ -91,6 +89,7 @@
     module Control.Applicative,
     module Data.Monoid,
     module Data.Int,
+    module Data.Word,
 
     ) where
 
@@ -101,6 +100,7 @@
 import           Data.Int                   (Int16, Int32, Int64, Int8)
 import           Data.MessagePack           (Object (..))
 import           Data.Monoid
+import           Data.Word                  (Word, Word32,Word16, Word8)
 import           Neovim.API.String
 import           Neovim.API.TH              (autocmd, command, command',
                                              function, function')
@@ -127,11 +127,15 @@
 -- tl;dr installation {{{2
 {- $tldrinstallation
 
-Since this is still very volatile, I recommend using a sandbox.
+Make sure that neovim's executable (@nvim@) is on your @\$PATH@ during the
+cabal commands!
 
-Make sure that neovim's executable (@nvim@) is on your @\$PATH@ during the following steps!
+/nvim-hs/ is a normal haskell program and a normal haskell library. You can install it
+in various flavors. These steps describe a more laborous approach that is suited for
+developing plugins or /nvim-hs/ itself.
 
-Install `nvim-hs` from git (example assumes you clone to @\$HOME\/git\/nvim-hs@)
+The following steps will install `nvim-hs` from git
+(example assumes you clone to @\$HOME\/git\/nvim-hs@)
 using a sandbox:
 
 @
@@ -142,8 +146,14 @@
 \$ cabal install
 @
 
+Or in one line for copy-pasting:
+
+@
+mkdir -p ~\/git ; cd ~\/git ; git clone https:\/\/github.com\/neovimhaskell\/nvim-hs && cd nvim-hs && cabal sandbox init && cabal install
+@
+
 Copy the script @nvim-hs-devel.sh@ to a location you like, make it executable
-and follow the brief instructions in the comments.
+and __follow the brief instructions__ in the comments.
 
 @
 \$ cp nvim-hs-devel.sh ~\/bin\/
@@ -155,16 +165,7 @@
 
 @
 if has(\'nvim\') \" This way you can also put it in your vim config file
-  function! s:RequireHaskellHost(name)
-    \" If the nvim-hs script\/executable is not on your path, you should give the full path here
-    return rpcstart(expand(\'$HOME\/bin\/nvim-hs-devel.sh\'), [a:name.name])
-  endfunction
-
-  \" You can replace \'haskell\' in the following lines with any name you like.
-  call remote\#host\#Register(\'haskell\', \'*.[cl]\\?hs\', function(\'s:RequireHaskellHost\'))
-  \" Blocks until nvim-hs has started (optional)
-  call rpcrequest(remote\#host\#Require(\'haskell\'),
-          \\ \'PingNvimhs\', [])
+    call rpcrequest(rpcstart(expand(\'\$HOME\/.bin\/nvim-hs-devel.sh\')), \"PingNvimhs\")
 endif
 @
 
@@ -174,21 +175,22 @@
 -- Explained {{{2
 {- $explainedinstallation
 
-You essentially have to follow the instructions of the tl;dr subsection above,
-but this subsection tells you why you need those steps and it gives you the
-required knowledge to deviate from those instructions.
-
 If you want to use or write plugins written in haskell for /nvim-hs/, you first
 have to make sure that neovim is installed and that it is available on your
 @\$PATH@ during the compilation of /nvim-hs/. Neovim emits information about its
-remotely callable API if you call it with the `--api-info` argument. This output
-is used to generate the API functions you desperately need to create useful
-plugins. Also, some internal functionality requires some of these functions.
+remotely callable API if you call it with the `--api-info` command line
+argument. This output is used to generate the API functions you need
+to create useful plugins. Also, some internal functionality requires some of
+these functions.
 
 The instructions to install /nvim-hs/ should be self-explanatory. In any case, I
-(saep) recommend using a sandbox for now since there is no stable hackage
-release yet and a few libraries are newer than what is currently in stackage
-(namely mtl, which is a big deal). Using a sandbox requires you to install all
+(saep) recommend using a sandbox for now since I the version constraints of the
+dependencies are quire lax and there are still changes on the way. Also, there is
+no official neovim release yet, so you may have to reinstall /nvim-hs/ a few times
+because the generated API could change or something similar. A sandboxed environment
+can be saefly deleted and it requires you only to copy and edit a small shell script!
+
+Using a sandbox requires you to install all
 the libraries you want or have to use in your plugins to be installed inside the
 sandbox! Some Vim plugins (e.g. ghc-mod) may show weird errors inside neovim for
 your configuration file because the sandbox is not inside your configuration folder.
@@ -196,17 +198,15 @@
 builtin plugin which puts all compile-errors in the quickfix
 list automatically after you save your configuration file, so you don't need
 another plugin to detect compile time errors here. But we will discuss this
-later in more detail. The executable script sets up the build environment for
-/nvim-hs/ to use the sandbox.
+later in more detail. The executable script mentioned in the tl;dr installation
+instructions sets up the build environment for /nvim-hs/ to use the sandbox.
 
-The Vim-script snippet is a bit lengthy, but the comments should explain how it
-works. In any case, the snippet can be put anywhere in your neovim configuration
-file and the last call of `rpcrequest` is not needed if you don't call any
-functionality before /nvim-hs/ has started properly. Removing the call can
-improve the startup time. If you only need some functionality for Haskell source
-files, you could move those last (or the last two) lines at the top of
-@\$HOME\/.nvim\/ftplugin\/haskell.vim@. You may wonder why we have to explicitly
-call 'PingNvimhs' with the function `rpcrequest` here. The short answer is:
+The Vim-script snippet is a bit conservative and may have a negative impact on
+your startup time. You can remove the @rpcrequest()@ wrapping and call the function
+@PingNvimhs@ at a later time when you need /nvim-hs/ to be initialized. Use your
+own judgement!  In any case, the snippet can be put anywhere in your neovim
+configuration. You may wonder why we have to explicitly
+call @PingNvimhs@ with the function @rpcrequest@ here. The short answer is:
 The internals for registering functions from a remote host require this. The
 longer answer is as follows: Registering functions from a remote host does not
 define a function directly. It instead installs a hook via an autocmd that
@@ -216,7 +216,7 @@
 not yet be in place and we receive error messages. Since we do not generate any
 Vim-script files which contain those hooks, /nvim-hs/ must be started and
 initialized and create those hooks. So the best way to make sure that /nvim-hs/
-is initialized is to try to call some functionon the msgpack-rpc channel that
+is initialized is to try to call some functionon on the msgpack-rpc channel that
 /nvim-hs/ listens on. The function must not even exist, but not throwing an
 error message is probably nicer, so /nvim-hs/ provides a function \"PingNvimhs\"
 which takes no arguments and returns @\"Pong\"@.
@@ -225,7 +225,10 @@
 plugins. It is generated using the 'Dyre' library and the binary itself is found
 in @\$XDG_CACHE_DIR\/nvim@ (usually @~\/.cache\/nvim@). The 'Dyre' library makes
 it feel more like a scripting language, because the binary is automatically
-created and executed without having to restart neovim.
+created and executed without having to restart neovim. You can also use the
+functions from the "Neovim.Debug" module if you want to develop your plugins in
+a REPL environment. This is probably a bit more difficult to use, so I won't go
+into detail here.
 
 -}
 -- 2}}}
@@ -234,17 +237,26 @@
 -- Tutorial {{{1
 -- tl;dr {{{2
 {- $tldrgettingstarted
+If you are proficient with Haskell, it may be sufficient to point you at some of the
+important data structures and functions. So, I will do it here. If you need more
+assistance, please skip to the next section and follow the links for functions or data
+types you do no understand how to use. If you think that the documentation is lacking,
+please create an issue on github (or even better, a pull request with a fix @;-)@).
+The code sections that describe new functionality are followed by the source code
+documentation of the used functions (and possibly a few more).
+
 Create a file called @nvim.hs@ in @\$XDG_CONFIG_HOME\/nvim@ (usually
 @~\/.config\/nvim@ with the following content:
 
 @
-\{\-\# LANGUAGE TemplateHaskell   \#\-\}
-import           Neovim
+import Neovim
 
 main = 'neovim' 'defaultConfig'
 @
 
-Adjust the fields in @def@ according to the the parameters in 'NeovimConfig'.
+Adjust the fields in 'defaultConfig' according to the the parameters in 'NeovimConfig'.
+Depending on how you define the parameters, you may have to add some language extensions
+which GHC should point you to.
 
 -}
 
@@ -270,19 +282,17 @@
 
 -- Existing Plugins {{{2
 {- $existingplugins
-/nvim-hs/ is all about importing and creating plugins. This is done following
-simple and concise API. Let's start by making a given plugin available inside
+/nvim-hs/ is all about importing and creating plugins. This is done following a
+concise API. Let's start by making a given plugin available inside
 our plugin provider. Assuming that we have installed a cabal package that exports
 an @examplePlugin@ from the module @TestPlugin.ExamplePlugin@. A minimal
 configuration would then look like this:
 
 @
-\{\-\# LANGUAGE TemplateHaskell \#\-\}
-
 import TestPlugin.ExamplePlugin (examplePlugin)
 
 main = 'neovim' 'def'
-        { plugins = [examplePlugin]
+        { 'plugins' = [ examplePlugin ] ++ 'plugins' 'defaultConfig'
         }
 @
 
@@ -303,8 +313,8 @@
 -- 2}}}
 -- Creating a plugin {{{2
 {- $creatingplugins
-Creating plugins isn't difficult either. You just have to follow a simple API
-and not be surprised about compile time errors of seemingly valid code. This may
+Creating plugins isn't difficult either. You just have to follow and survive the
+the compile time errors of seemingly valid code. This may
 sound scary, but it is not so bad. We will cover most pitfalls in the following
 paragraphs and if there isn't a solution for your error, you can always ask any
 friendly Haskeller in \#haskell on @irc.freenode.net@!
@@ -319,51 +329,63 @@
 So, let's write a plugin that calculates the @n@th Fibonacci number. Don't we all
 love those!
 
-File @~\/.config\/nvim\/lib\/MyFirstPlugin.hs@
+File @~\/.config\/nvim\/lib\/Fibonacci/Plugin.hs@
 
 @
-module MyFirstPlugin
-    ( fibonacci
-    ) where
+module Fibonacci.Plugin (fibonacci) where
 
-import Neovim
+import "Neovim"
 
-fibonacci :: 'Int' -> Neovim' 'String'
-fibonacci n = 'show' $ fibs !! n
+-- | Neovim is not really good with big numbers, so we return a 'String' here.
+fibonacci :: 'Int' -> 'Neovim'' 'String'
+fibonacci n = 'return' . 'show' \$ fibs !! n
   where
-    fibs :: ['Integer']
+    fibs :: [Integer]
     fibs = 0:1:'scanl1' (+) fibs
 @
 
-File @~\/.config\/nvim\/nvim.hs@:
+File @~\/.config\/nvim\/lib/Fibonacci.hs@:
 
 @
 \{\-\# LANGUAGE TemplateHaskell \#\-\}
+module Fibonacci (plugin) where
 
-import MyFirstPlugin (fibonacci)
+import "Neovim"
+import Fibonacci.Plugin (fibonacci)
 
-fibonacciPlugin = 'wrapPlugin'
-    { 'exports' = [ $('function'' 'fibonacci) 'Sync' ]
+plugin :: 'Neovim' ('StartupConfig' 'NeovimConfig') () 'NeovimPlugin'
+plugin = 'wrapPlugin' Plugin
+    { 'exports'         = [ $('function'' 'fibonacci) 'Sync' ]
+    , 'statefulExports' = []
     }
+@
 
-main = 'neovim' 'def'
-        { 'plugins' = [fibonacciPlugin]
-        }
+File @~\/.config\/nvim\/nvim.hs@:
+
 @
+import "Neovim"
 
-Let's analyze how it works. The module @MyFirstPlugin@ simply defines a function
+import qualified Fibonacci as Fibonacci
+
+main :: 'IO' ()
+main = 'neovim' 'defaultConfig'
+    { 'plugins' = 'plugins' 'defaultConfig' ++ [ Fibonacci.plugin ]
+    }
+@
+
+Let's analyze how it works. The module @Fibonacci.Plugin@ simply defines a function
 that takes the @n@th element of the infinite list of Fibonacci numbers. Even though
 the definition is very concise and asthetically pleasing, the important part is the
 type signature for @fibonacci@. Similarly how @main :: IO ()@ works in normal Haskell
 programs, 'Neovim'' is the environment we need for plugins. Internally, it stores a
 few things that are needed to communicate with neovim, but that shouldn't bother you
 too much. Simply remember that every plugin function must have a function signature
-whose last element is of type @'Neovim' r st something@'. The result of @fibonacci@
+whose last element is of type @'Neovim' r st something@. The result of @fibonacci@
 is 'String' because neovim cannot handle big numbers so well. :-)
 You can use any argument or result type as long as it is an instance of 'NvimObject'.
 
-The second part of of the puzzle, which is the definition of @fibonacciPlugin@
-in @~\/.config\/nvim\/nvim.hs@, shows what a plugin is. It is essentially two
+The second part of of the puzzle, which is the definition of @plugin@
+in @~\/.config\/nvim\/lib\/Fibonaccin.hs@, shows what a plugin is. It is essentially two
 lists of stateless and stateful functionality. A functionality can currently be one
 of three things: a function, a command and an autocmd in the context of vim
 terminology. In the end, all of those functionalities map to a function at the side
@@ -398,11 +420,13 @@
 you to put that in front of function names that are passed in a splice.
 
 If you compile this (which should happen automatically if you have put those
-files at the appropriate places), you can calculate the 287323rd Fibonacci number
-like this:
+files at the appropriate places), you can restart /nvim-hs/ with the command
+@:RestartNvimhs@ which is available as long as you do not remove the default
+plugins from you rconfig. Afterwards, you can calculate the 2000th Fibonacci
+number like as if it were a normal vim-script function:
 
 @
-:echo Fibonacci(287323)
+:echo Fibonacci(2000)
 @
 
 You can also directly insert the result inside any text file opened with neovim
@@ -410,7 +434,7 @@
 mode:
 
 @
-\<C-r\>=Fibonacci(287323)
+\<C-r\>=Fibonacci(2000)
 @
 
 -}
@@ -419,56 +443,90 @@
 {- $remote
 Now that we are a little bit comfortable with the interface provided by /nvim-hs/,
 we can start to write a more complicated plugin. Let's create a random number
-generator.
+generator!
 
-File @~\/.config\/nvim\/lib\/MyRandomNumberGenerator.hs@:
+File @~\/.config\/nvim\/lib\/Random\/Plugin.hs@:
 
 @
-module MyRandomNumberGenerator
-    ( nextRand
-    , setNextNumber
-    ) where
+module Random.Plugin (nextRandom, setNextRandom) where
 
-nextRand :: 'Neovim' r ['Int16'] Int16
-nextRand = do
-    r <- gets head
-    modify tail
-    return r
+import "Neovim"
 
-setNextNumber :: Int16 -> 'Neovim' r ['Int16'] ()
-setNextNumber n = modify (n:)
+-- | Neovim isn't so good with big numbers here either.
+nextRandom :: 'Neovim' r ['Int16'] 'Int16'
+nextRandom = do
+    r <- 'gets' 'head' -- get the head of the infinite random number list
+    'modify' 'tail'    -- set the list to its tail
+    'return' r
+
+setNextRandom :: 'Int' -> 'Neovim' r ['Int16'] ()
+setNextRandom n = 'modify' (n:) -- cons to the front of the infinite list
 @
 
-File @~\/.config\/nvim\/nvim.hs@:
+File @~\/.config\/nvim\/lib\/Random.hs@:
 
 @
 \{\-\# LANGUAGE TemplateHaskell \#\-\}
+module Random (plugin) where
 
-import MyRandomNumberGenerator (nextRand, setNextNumber)
-import System.Random (newStdGen, randoms)
+import "Neovim"
+import Random.Plugin (nextRandom, setNextRandom)
+import "System.Random" ('newStdGen', 'randoms')
 
-randPlugin = do
-    g <- newStdGen                -- initialize with a random seed
-    let randomNumbers = randoms g -- an infite list of random numbers
-    'wrapPlugin'
-        { 'statefulExports' =
+plugin :: 'Neovim' ('StartupConfig' 'NeovimConfig') () 'NeovimPlugin'
+plugin = do
+    g <- 'liftIO' 'newStdGen'         -- initialize with a random seed
+    let randomNumbers = 'randoms' g -- an infinite list of random numbers
+    'wrapPlugin' 'Plugin'
+        { 'exports'         = []
+        , 'statefulExports' =
             [ ((), randomNumbers,
-                [ $('function'' 'nextRand) 'Sync'
-                , $('function'' 'setNextNumber) 'Async'
+                [ $('function'' 'nextRandom) 'Sync'
+                , $('function' \"SetNextRandom\" 'setNextRandom) 'Async'
                 ])
             ]
         }
+@
 
-main = 'neovim' 'def'
-        { 'plugins' = [randPlugin]
-        }
+File @~\/.config\/nvim\/nvim.hs@:
+
 @
+import "Neovim"
 
+import qualified Fibonacci as Fibonacci
+import qualified Random    as Random
+
+main :: 'IO' ()
+main = 'neovim' 'defaultConfig'
+    { 'plugins' = 'plugins' 'defaultConfig' ++ [ Fibonacci.plugin, Random.plugin ]
+    }
+@
+
+
 That wasn't too hard, was it? The definition is very similar to the previous
 example, we just were able to mutate our state and share that with other
-functions. The only slightly tedious thing was to define the 'statefulExpors'
-field because it is a list of triples which has a list of exported functionality
-as its third argument.
+functions. The only slightly tedious thing was to define the 'statefulExports'
+field because it is a list of triples which has a list of exported
+functionalities as its third argument. Another noteworthy detail, in case you
+are not familiar with it, is the use of 'liftIO' in front of 'newStdGen'. You
+have to do this, because 'newStdGen' has type @'IO' 'StdGen'@ but the actions
+inside the startup code are of type
+@'Neovim' ('StartupConfig' 'NeovimConfig') () something@. 'liftIO' lifts an
+'IO' function so that it can be run inside the 'Neovim' context (or more
+generally, any monad that implements the 'MonadIO' type class).
+
+After you have saved these files (and removed any typos @:-)@), you can restart
+/nvim-hs/ with @:RestartNvimhs@ and insert random numbers in your text files!
+
+@
+\<C-r\>=NextRandom()
+@
+
+You can also cheat and pretend you know the next number:
+
+@
+:call SetNextRandom(42)
+@
 
 -}
 -- 2}}}
diff --git a/library/Neovim/Config.hs b/library/Neovim/Config.hs
--- a/library/Neovim/Config.hs
+++ b/library/Neovim/Config.hs
@@ -19,6 +19,9 @@
 
 import           System.Log             (Priority (..))
 
+-- | This data type contins information about the configuration of neovim. See
+-- the fields' documentation for what you possibly want to change. Also, the
+-- tutorial in the "Neovim" module should get you started.
 data NeovimConfig = Config
     { plugins      :: [Neovim (StartupConfig NeovimConfig) () NeovimPlugin]
     -- ^ The list of plugins. The IO type inside the list allows the plugin
diff --git a/library/Neovim/Context.hs b/library/Neovim/Context.hs
--- a/library/Neovim/Context.hs
+++ b/library/Neovim/Context.hs
@@ -51,8 +51,11 @@
 import           Data.Data               (Typeable)
 
 
+-- | Exceptions specific to /nvim-hs/.
 data NeovimException
     = ErrorMessage String
+    -- ^ Simply error message that is passed to neovim. It should currently only
+    -- contain one line of text.
     deriving (Typeable, Show)
 
 instance Exception NeovimException
@@ -65,10 +68,10 @@
 
 -- | Initiate a restart of the plugin provider.
 restart :: Neovim r st ()
-restart = liftIO . flip putMVar Internal.Restart =<< Internal.asks' Internal.quit
+restart = liftIO . flip putMVar Internal.Restart =<< Internal.asks' Internal.transitionTo
 
 
 -- | Initiate the termination of the plugin provider.
 quit :: Neovim r st ()
-quit = liftIO . flip putMVar Internal.Quit =<< Internal.asks' Internal.quit
+quit = liftIO . flip putMVar Internal.Quit =<< Internal.asks' Internal.transitionTo
 
diff --git a/library/Neovim/Context/Internal.hs b/library/Neovim/Context/Internal.hs
--- a/library/Neovim/Context/Internal.hs
+++ b/library/Neovim/Context/Internal.hs
@@ -134,6 +134,7 @@
     -- is the communication endpoint for the arguments we have to pass.
 
 
+-- | Type of the values stored in the function map.
 type FunctionMapEntry = (FunctionalityDescription, FunctionType)
 
 
@@ -168,10 +169,10 @@
     -- ^ A queue of messages that the event handler will propagate to
     -- appropriate threads and handlers.
 
-    , quit              :: MVar QuitAction
+    , transitionTo      :: MVar StateTransition
     -- ^ The main thread will wait for this 'MVar' to be filled with a value
     -- and then perform an action appropriate for the value of type
-    -- 'QuitAction'.
+    -- 'StateTransition'.
 
     , providerName      :: TMVar (Either String Int)
     -- ^ Since nvim-hs must have its "Neovim.RPC.SocketReader" and
@@ -245,17 +246,18 @@
     <*> r
 
 
-data QuitAction = Quit
-                -- ^ Quit the plugin provider.
+-- | The state that the plugin provider wants to transition to.
+data StateTransition
+    = Quit
+    -- ^ Quit the plugin provider.
 
-                | Restart
-                -- ^ Restart the plugin provider.
+    | Restart
+    -- ^ Restart the plugin provider.
 
-                | Failure String
-                -- ^ The plugin provider failed to start or some other error
-                -- occured.
+    | Failure String
+    -- ^ The plugin provider failed to start or some other error occured.
 
-                | InitSuccess
-                -- ^ The plugin provider started successfully.
+    | InitSuccess
+    -- ^ The plugin provider started successfully.
 
-                deriving (Show, Read, Eq, Ord)
+    deriving (Show, Read, Eq, Ord)
diff --git a/library/Neovim/Debug.hs b/library/Neovim/Debug.hs
--- a/library/Neovim/Debug.hs
+++ b/library/Neovim/Debug.hs
@@ -14,6 +14,8 @@
     debug,
     debug',
     develMain,
+    quitDevelMain,
+    restartDevelMain,
 
     runNeovim,
     runNeovim',
@@ -46,9 +48,9 @@
 -- automatically set.
 debug :: r -> st -> Internal.Neovim r st a -> IO (Either String (a, st))
 debug r st a = disableLogger $ do
-    runPluginProvider def { env = True } Nothing finalizer Nothing
+    runPluginProvider def { env = True } Nothing transitionHandler Nothing
   where
-    finalizer tids cfg = takeMVar (Internal.quit cfg) >>= \case
+    transitionHandler tids cfg = takeMVar (Internal.transitionTo cfg) >>= \case
         Internal.Failure e ->
             return $ Left e
 
@@ -62,7 +64,7 @@
             return res
 
         _ ->
-            return $ Left "Unexpected finalizer state."
+            return $ Left "Unexpected transition state."
 
 
 -- | Run a 'Neovim'' function.
@@ -79,46 +81,81 @@
 -- | This function is intended to be run _once_ in a ghci session that to
 -- give a REPL based workflow when developing a plugin.
 --
+-- Note that the dyre-based reload mechanisms, i.e. the
+-- "Neovim.Plugin.ConfigHelper" plugin, is not started this way.
+--
 -- To use this in ghci, you simply bind the results to some variables. After
 -- each reload of ghci, you have to rebind those variables.
 --
 -- Example:
 --
 -- @
--- λ Right (tids, cfg) <- develMain
+-- λ 'Right' (tids, cfg) <- 'develMain' 'Nothing'
 --
--- λ runNeovim' cfg \$ vim_call_function "getqflist" []
--- Right (Right (ObjectArray []))
+-- λ 'runNeovim'' cfg \$ vim_call_function \"getqflist\" []
+-- 'Right' ('Right' ('ObjectArray' []))
 --
 -- λ :r
 --
--- λ Right (tids, cfg) <- develMain
+-- λ 'Right' (tids, cfg) <- 'develMain' 'Nothing'
 -- @
 --
-develMain :: IO (Either String ([ThreadId], Internal.Config RPCConfig ()))
-develMain = lookupStore 0 >>= \case
+develMain
+    :: Maybe NeovimConfig
+    -> IO (Either String ([ThreadId], Internal.Config RPCConfig ()))
+develMain mcfg = lookupStore 0 >>= \case
     Nothing -> do
         x <- disableLogger $
-                runPluginProvider def { env = True } Nothing finalizer Nothing
+                runPluginProvider def { env = True } mcfg transitionHandler Nothing
         void $ newStore x
         return x
 
     Just x ->
         readStore x
   where
-    finalizer tids cfg = takeMVar (Internal.quit cfg) >>= \case
+    transitionHandler tids cfg = takeMVar (Internal.transitionTo cfg) >>= \case
         Internal.Failure e ->
             return $ Left e
 
-        Internal.InitSuccess ->
-            return $ Right (tids, cfg)
+        Internal.InitSuccess -> do
+            transitionHandlerThread <- forkIO $ do
+                myTid <- myThreadId
+                void $ transitionHandler (myTid:tids) cfg
+            return $ Right (transitionHandlerThread:tids, cfg)
 
+        Internal.Quit -> do
+            lookupStore 0 >>= \case
+                Nothing ->
+                    return ()
+
+                Just x ->
+                    deleteStore x
+
+            mapM_ killThread tids
+            return $ Left "Quit develMain"
+
         _ ->
-            return $ Left "Unexpected finalizer state for develMain."
+            return $ Left "Unexpected transition state for develMain."
 
 
+-- | Quit a previously started plugin provider.
+quitDevelMain :: Internal.Config r st -> IO ()
+quitDevelMain cfg = putMVar (Internal.transitionTo cfg) Internal.Quit
+
+
+-- | Restart the development plugin provider.
+restartDevelMain
+    :: Internal.Config RPCConfig ()
+    -> Maybe NeovimConfig
+    -> IO (Either String ([ThreadId], Internal.Config RPCConfig ()))
+restartDevelMain cfg mcfg = do
+    quitDevelMain cfg
+    develMain mcfg
+
+
 -- | Convenience function to run a stateless 'Neovim' function.
 runNeovim' :: Internal.Config r st -> Neovim' a -> IO (Either String a)
 runNeovim' cfg =
     fmap (fmap fst) . runNeovim (Internal.retypeConfig () () cfg) ()
+
 
diff --git a/library/Neovim/Main.hs b/library/Neovim/Main.hs
--- a/library/Neovim/Main.hs
+++ b/library/Neovim/Main.hs
@@ -127,31 +127,36 @@
     in Dyre.wrapMain params
 
 
-type Finalizer a = [ThreadId] -> Internal.Config RPCConfig () -> IO a
+-- | A 'TransitionHandler' function receives the 'ThreadId's of all running
+-- threads which have been started by the plugin provider as well as the
+-- 'Internal.Config' with the custom field set to 'RPCConfig'. These information
+-- can be used to properly clean up a session and then do something else.
+-- The transition handler is first called after the plugin provider has started.
+type TransitionHandler a = [ThreadId] -> Internal.Config RPCConfig () -> IO a
 
 
 -- | This main functions can be used to create a custom executable without
 -- using the "Config.Dyre" library while still using the /nvim-hs/ specific
 -- configuration facilities.
-realMain :: Finalizer a
+realMain :: TransitionHandler a
          -> Maybe (Dyre.Params NeovimConfig)
          -> NeovimConfig
          -> IO ()
-realMain finalizer mParams cfg = do
+realMain transitionHandler mParams cfg = do
     os <- execParser opts
     maybe disableLogger (uncurry withLogger) (logOpts os <|> logOptions cfg) $ do
         debugM logger "Starting up neovim haskell plguin provider"
-        void $ runPluginProvider os (Just cfg) finalizer mParams
+        void $ runPluginProvider os (Just cfg) transitionHandler mParams
 
 
 -- | Generic main function. Most arguments are optional or have sane defaults.
 runPluginProvider
     :: CommandLineOptions -- ^ See /nvim-hs/ executables --help function or 'optParser'
     -> Maybe NeovimConfig
-    -> Finalizer a
+    -> TransitionHandler a
     -> Maybe (Dyre.Params NeovimConfig)
     -> IO a
-runPluginProvider os mcfg finalizer mDyreParams = case (hostPort os, unix os) of
+runPluginProvider os mcfg transitionHandler mDyreParams = case (hostPort os, unix os) of
     (Just (h,p), _) ->
         createHandle (TCP p h) >>= \s -> run s s
 
@@ -190,19 +195,21 @@
         startPluginThreads startupConf allPlugins >>= \case
             Left e -> do
                 errorM logger $ "Error initializing plugins: " <> e
-                putMVar (Internal.quit conf) $ Internal.Failure e
-                finalizer [ehTid, srTid] conf
+                putMVar (Internal.transitionTo conf) $ Internal.Failure e
+                transitionHandler [ehTid, srTid] conf
 
             Right (funMapEntries, pluginTids) -> do
                 atomically $ putTMVar
                                 (Internal.globalFunctionMap conf)
                                 (Internal.mkFunctionMap funMapEntries)
-                putMVar (Internal.quit conf) $ Internal.InitSuccess
-                finalizer (srTid:ehTid:pluginTids) conf
+                putMVar (Internal.transitionTo conf) $ Internal.InitSuccess
+                transitionHandler (srTid:ehTid:pluginTids) conf
 
 
-finishDyre :: Finalizer ()
-finishDyre threads cfg = takeMVar (Internal.quit cfg) >>= \case
+-- | If the plugin provider is started with dyre, this handler is used to
+-- handle a restart.
+finishDyre :: TransitionHandler ()
+finishDyre threads cfg = takeMVar (Internal.transitionTo cfg) >>= \case
     Internal.InitSuccess -> do
         debugM logger "Waiting for threads to finish."
         finishDyre threads cfg
diff --git a/library/Neovim/Plugin.hs b/library/Neovim/Plugin.hs
--- a/library/Neovim/Plugin.hs
+++ b/library/Neovim/Plugin.hs
@@ -49,6 +49,7 @@
 import           Control.Monad.Catch          (SomeException, try)
 import           Control.Monad.Trans.Resource hiding (register)
 import           Data.ByteString              (ByteString)
+import           Data.ByteString.UTF8         (toString)
 import           Data.Foldable                (forM_)
 import           Data.Map                     (Map)
 import qualified Data.Map                     as Map
@@ -100,8 +101,12 @@
 registerWithNeovim = \case
     Function (F functionName) s -> do
         pName <- getProviderName
-        ret <- vim_call_function "remote#define#FunctionOnHost"
-            [ toObject pName, toObject functionName, toObject s
+        let (defineFunction, host) = either
+                (\n -> ("remote#define#FunctionOnHost", toObject n))
+                (\c -> ("remote#define#FunctionOnChannel", toObject c))
+                pName
+        ret <- vim_call_function defineFunction
+            [ host, toObject functionName, toObject s
             , toObject functionName, toObject (Map.empty :: Dictionary)
             ]
         case ret of
@@ -122,8 +127,12 @@
                     _             -> Sync
 
         pName <- getProviderName
-        ret <- vim_call_function "remote#define#CommandOnHost"
-            [ toObject pName, toObject functionName, toObject sync
+        let (defineFunction, host) = either
+                (\n -> ("remote#define#CommandOnHost", toObject n))
+                (\c -> ("remote#define#CommandOnChannel", toObject c))
+                pName
+        ret <- vim_call_function defineFunction
+            [ host, toObject functionName, toObject sync
             , toObject functionName, toObject copts
             ]
         case ret of
@@ -138,8 +147,12 @@
 
     Autocmd acmdType (F functionName) opts -> do
         pName <- getProviderName
-        ret <- vim_call_function "remote#define#AutocmdOnHost"
-            [ toObject pName, toObject functionName, toObject Async
+        let (defineFunction, host) = either
+                (\n -> ("remote#define#AutocmdOnHost", toObject n))
+                (\c -> ("remote#define#AutocmdOnChannel", toObject c))
+                pName
+        ret <- vim_call_function defineFunction
+            [ host, toObject functionName, toObject Async
             , toObject acmdType , toObject opts
             ]
         case ret of
@@ -202,9 +215,9 @@
   where
     freeFun = \case
         Autocmd event _ AutocmdOptions{..} -> do
-            void . vim_call_function "autocmd!" $ catMaybes
-                    [ toObject <$> acmdGroup, Just (toObject event)
-                    , Just (toObject acmdPattern)
+            void . vim_command . unwords $ catMaybes
+                    [ Just "autocmd!", acmdGroup
+                    , Just (toString event) , Just acmdPattern
                     ]
 
         Command{} ->
diff --git a/library/Neovim/Plugin/Classes.hs b/library/Neovim/Plugin/Classes.hs
--- a/library/Neovim/Plugin/Classes.hs
+++ b/library/Neovim/Plugin/Classes.hs
@@ -47,6 +47,7 @@
 newtype FunctionName = F ByteString
     deriving (Eq, Ord, Show, Read)
 
+
 -- | Functionality specific functional description entries.
 --
 -- All fields which are directly specified in these constructors are not
@@ -176,6 +177,10 @@
     deriving (Eq, Ord, Show, Read)
 
 
+-- | Smart constructor for 'CommandOptions'. This sorts the command options and
+-- removes duplicate entries for semantically the same thing. Note that the
+-- smallest option stays for whatever ordering is defined. It is best to simply
+-- not define the same thing multiple times.
 mkCommandOptions :: [CommandOption] -> CommandOptions
 mkCommandOptions = CommandOptions . map head . groupBy constructor . sort
   where
@@ -210,12 +215,20 @@
         "Did not expect to receive a CommandOptions object: " ++ show o
 
 
-data RangeSpecification = CurrentLine
-                        | WholeFile
-                        | RangeCount Int
-                        deriving (Eq, Ord, Show, Read)
+-- | Specification of a range that acommand can operate on.
+data RangeSpecification
+    = CurrentLine
+    -- ^ The line the cursor is at when the command is invoked.
 
+    | WholeFile
+    -- ^ Let the command operate on every line of the file.
 
+    | RangeCount Int
+    -- ^ Let the command operate on each line in the given range.
+
+    deriving (Eq, Ord, Show, Read)
+
+
 instance NvimObject RangeSpecification where
     toObject = \case
         CurrentLine  -> ObjectBinary ""
@@ -283,6 +296,8 @@
         throwError $ "Expected a map for CommandArguments object, but got: " ++ show o
 
 
+-- | Options that can be used to register an autocmd. See @:h :autocmd@ or any
+-- referenced neovim help-page from the fields of this data type.
 data AutocmdOptions = AutocmdOptions
     { acmdPattern :: String
     -- ^ Pattern to match on. (default: \"*\")
diff --git a/library/Neovim/Plugin/IPC/Classes.hs b/library/Neovim/Plugin/IPC/Classes.hs
--- a/library/Neovim/Plugin/IPC/Classes.hs
+++ b/library/Neovim/Plugin/IPC/Classes.hs
@@ -39,6 +39,13 @@
 -- can be sent to other plugins.
 data SomeMessage = forall msg. Message msg => SomeMessage msg
 
+
+-- | This class allows type safe casting of 'SomeMessage' to an actual message.
+-- The cast is successful if the type you're expecting matches the type in the
+-- 'SomeMessage' wrapper. This way, you can subscribe to an arbitrary message
+-- type withouth having to pattern match on the constructors. This also allows
+-- plugin authors to create their own message types without having to change the
+-- core code of /nvim-hs/.
 class Typeable message => Message message where
     -- | Try to convert a given message to a value of the message type we are
     -- interested in. Will evaluate to 'Nothing' for any other type.
diff --git a/library/Neovim/Quickfix.hs b/library/Neovim/Quickfix.hs
--- a/library/Neovim/Quickfix.hs
+++ b/library/Neovim/Quickfix.hs
@@ -28,8 +28,13 @@
 
 import           Prelude
 
+-- | This is a wrapper around neovim's @setqflist()@. @strType@ can be any
+-- string that you can append to (hence 'Monoid') that is also an instance
+-- of 'NvimObject'. You can e.g. use the plain old 'String'.
 setqflist :: (Monoid strType, NvimObject strType)
-          => [QuickfixListItem strType] -> QuickfixAction -> Neovim r st ()
+          => [QuickfixListItem strType]
+          -> QuickfixAction
+          -> Neovim r st ()
 setqflist qs a =
     void $ vim_call_function "setqflist" [toObject qs, toObject a]
 
@@ -43,16 +48,21 @@
     { bufOrFile     :: Either Int strType
     -- ^ Since the filename is only used if no buffer can be specified, this
     -- field is a merge of @bufnr@ and @filename@.
+
     , lnumOrPattern :: Either Int strType
     -- ^ Line number or search pattern to locate the error.
+
     , col           :: Maybe (Int, Bool)
     -- ^ A tuple of a column number and a boolean indicating which kind of
     -- indexing should be used. 'True' means that the visual column should be
     -- used. 'False' means to use the byte index.
+
     , nr            :: Maybe Int
     -- ^ Error number.
+
     , text          :: strType
     -- ^ Description of the error.
+
     , errorType     :: QuickfixErrorType
     -- ^ Type of error.
     } deriving (Eq, Show)
@@ -120,7 +130,7 @@
         lnumOrPattern <- case (l "lnum", l "pattern") of
             (Right lnum, _) -> return $ Left lnum
             (_, Right pat)  -> return $ Right pat
-            _              -> throwError "No line number of search pattern inside quickfix list item."
+            _              -> throwError "No line number or search pattern inside quickfix list item."
         let l' :: NvimObject o => ByteString -> Either String (Maybe o)
             l' key = case Map.lookup key m of
                 Just o -> Just <$> fromObject o
@@ -139,13 +149,16 @@
         text <- fromMaybe mempty <$> l' "text"
         errorType <- fromMaybe Error <$> l' "type"
         return QFItem{..}
+
     fromObject o = throwError $ "Could not deserialize QuickfixListItem, expected a map but received: " ++ show o
 
+
 data QuickfixAction
     = Append -- ^ Add items to the current list (or create a new one if none exists).
     | Replace -- ^ Replace current list (or create a new one if none exists).
     | New    -- ^ Create a new list.
     deriving (Eq, Ord, Enum, Bounded, Show)
+
 
 instance NvimObject QuickfixAction where
     toObject = \case
diff --git a/library/Neovim/RPC/Common.hs b/library/Neovim/RPC/Common.hs
--- a/library/Neovim/RPC/Common.hs
+++ b/library/Neovim/RPC/Common.hs
@@ -106,6 +106,8 @@
                 error errMsg
 
 
+-- | Close the handle and print a warning if the conduit chain has been
+-- interrupted prematurely.
 cleanUpHandle :: (MonadIO io) => Handle -> Bool -> io ()
 cleanUpHandle h completed = liftIO $ do
     hClose h
diff --git a/library/Neovim/RPC/FunctionCall.hs b/library/Neovim/RPC/FunctionCall.hs
--- a/library/Neovim/RPC/FunctionCall.hs
+++ b/library/Neovim/RPC/FunctionCall.hs
@@ -38,12 +38,19 @@
 
 import           Prelude
 
+-- | Simply fail and call 'error' in case an unexpected exception is thrown.
+-- This fails with a runtime exception. It is used by the Template Haskell API
+-- generator for functions that are defined as not being able to fail. If this
+-- exception occurs, it is a bug in neovim.
 unexpectedException :: String -> err -> a
 unexpectedException fn _ = error $
     "Function threw an exception even though it was declared not to throw one: "
     <> fn
 
 
+-- | Strip the error result from the function call. This should only be used by
+-- the Template Haskell API generated code for functions that declare
+-- themselves as unfailable.
 withIgnoredException :: (Functor f, NvimObject result)
                      => FunctionName -- ^ For better error messages
                      -> f (Either err result)
@@ -70,6 +77,9 @@
             Right r -> Right r
 
 
+
+-- | Helper function similar to 'acall' that throws a runtime exception if the
+-- result is an error object.
 acall' :: (NvimObject result)
        => FunctionName
        -> [Object]
@@ -87,6 +97,8 @@
 scall fn parameters = acall fn parameters >>= atomically'
 
 
+-- | Helper function similar to 'scall' that throws a runtime exception if the
+-- result is an error object.
 scall' :: NvimObject result => FunctionName -> [Object] -> Neovim r st result
 scall' fn = withIgnoredException fn . scall fn
 
diff --git a/nvim-hs.cabal b/nvim-hs.cabal
--- a/nvim-hs.cabal
+++ b/nvim-hs.cabal
@@ -1,14 +1,23 @@
 name:                nvim-hs
-version:             0.0.3
+version:             0.0.5
 synopsis:            Haskell plugin backend for neovim
 description:
   This package provides a plugin provider for neovim. It allows you to write
   plugins for one of the great editors of our time in the best programming
   language of our time! ;-)
   .
-  You should find all the documentation you need inside the "Neovim" module. All
-  other modules are considered internal, so don't be annoyed if using things
-  from there may break your code.
+  You should find all the documentation you need inside the "Neovim" module.
+  Most other modules are considered internal, so don't be annoyed if using
+  things from there may break your code!
+  .
+  The following modules may also be of interest and they should not change
+  their API: "Neovim.Quickfix"
+  .
+  If you want to write unit tests that interact with neovim, "Neovim.Test"
+  provides some useful functions for that.
+  .
+  If you are keen to debug /nvim-hs/ or a module you are writing, take a look
+  at the "Neovim.Debug" module.
   .
   If you spot any errors or if you have great ideas, feel free to open an issue
   on github.
