diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -3,13 +3,49 @@
 [![Hackage](https://img.shields.io/hackage/v/commander-cli.svg)](https://hackage.haskell.org/package/commander-cli)
 [![Build Status](https://travis-ci.org/SamuelSchlesinger/commander-cli.svg?branch=master)](https://travis-ci.org/SamuelSchlesinger/commander-cli)
 
-This library is meant to allow Haskell programs to quickly and easily construct
-command line interfaces which are easy to use, especially as a Haskell user. To
-learn, I suggest viewing/playing with the task-manager application which
-comes with this repository. Here, we'll display a simpler example:
+This library is meant to allow Haskell programmers to quickly and easily construct
+command line interfaces with decent documentation.
 
+One extension I use in these examples is `-XTypeApplications`, which uses the `@param`
+syntax to apply an type-level argument explicitly to a function with a `forall x ...` in its
+type, rather than implicitly, we do when we write `fmap (+ 1) [1, 2, 3]` applying the type `[]`
+to `fmap`. It's because of type inference in Haskell that we don't always have to apply our
+types explicitly, as many other languages force you to do using a syntax typically like `fmap<[], Int> (+ 1) [1, 2, 3]`.`.
+
+We can go to the command line and try out this example:
+
+```
+> :set -XTypeApplications
+> :t fmap @[]
+fmap @[] :: (a -> b) -> [a] -> [b]
+> :t fmap @[] @Int
+fmap @[] @Int :: (Int -> b) -> [Int] -> [b]
+> :t fmap @[] @Int @Bool
+fmap @[] @Int @Bool :: (Int -> Bool) -> [Int] -> [Bool]
+```
+
+The API of `commander-cli` allows for very profitable usage of type
+applications, because the description of our command line program will live
+at the type level. 
+
+Another extension we will use is `-XDataKinds`, which is only for the ability
+to use strings, or the kind `Symbol`, at the type level. Kinds are just the
+type of types, and so `-XDataKinds` allows us to have kinds which are actually
+data in their own right, like lists, strings, numbers, and custom Haskell
+data types. For us, we will use strings to represent the documentation of our
+program at the type level, as well as the names of options, flags, and arguments
+we want to parse. This allows us to generate documentation programs simply from
+the type signature of the CLI program we build.
+
+Our first example will show a basic command line application,
+complete with help messages that display reasonable messages to the user.
+
 ```haskell
-main = command_ . toplevel @"argument-taker" . arg @"example-argument" $ raw . putStrLn
+main = command_
+  . toplevel @"argument-taker"
+  . arg @"example-argument" $ \arg ->
+    raw $ do
+      putStrLn arg
 ```
 
 When you run this program with `argument-taker help`, you will see:
@@ -23,21 +59,24 @@
 `- argument: example-argument :: [Char]
 ```
 
-The meaning of this is that every path in the tree is a unique command. The one
-we've used is the help command. If we run this program with `argument-taker hello`
+The meaning of this documentation is that every path in the tree is a unique command.
+The one we've used is the help command. If we run this program with `argument-taker hello`
 we will see:
 
 ```
 hello
 ```
 
-Okay, so we've made a program with hardly any scaffolding that gives us a
-decent help message, and pipes through our argument correctly. Naturally, we
-might want to expand on the documentation of this program, as its not quite
+Naturally, we might want to expand on the documentation of this program, as its not quite
 obvious enough what it does.
 
-```
-main = command_ . toplevel @"argument-taker" . arg @"example-argument" $ (description @"Takes the argument and prints it" . raw . putStrLn)
+```haskell
+main = command_
+  . toplevel @"argument-taker"
+  . arg @"example-argument" $ \arg ->
+    description @"Takes the argument and prints it"
+  . raw $ do
+      putStrLn arg
 ```
 
 Printing out the documentation again with `argument-taker help`, we see:
@@ -55,12 +94,14 @@
 
 Okay, so we can expand the documentation. But what if I have an option to pass to the same program? Well, we can pass an option like so:
 
-```
-main = command_ . toplevel @"argument-taker" $
-  opt @"m" @"mode" \mode ->
+```haskell
+main = command_
+  . toplevel @"argument-taker"
+  . optDef @"m" @"mode" "Print" $ \mode ->
     arg @"example-argument" $ \arg ->
-      description @"Takes the argument and prints it or not, depending on the mode" . raw $ do
-        if mode == "Print" then putStrLn arg else pure ()
+    description @"Takes the argument and prints it or not, depending on the mode" 
+  . raw $ do
+      if mode == "Print" then putStrLn arg else pure ()
 ```
 
 Now, when we run `argument-taker help` we will see:
@@ -76,6 +117,176 @@
    `- argument: example-argument :: [Char]
       |
       `- description: Takes the argument and prints it or not, depending on the mode
+```
+
+Okay! So we can now create programs which take arguments and options, so what
+else do we want in a command line program? Flags! Lets add a flag to our
+example program:
+
+```haskell
+main = command_
+  . toplevel @"argument-taker"
+  . optDef @"m" @"mode" "Print" $ \mode ->
+    arg @"example-argument" $ \arg ->
+    flag @"loud" $ \loud ->
+    description @"Takes the argument and prints it or not, depending on the mode and possibly loudly" 
+  . raw $ do
+      let msg = if loud then map toUpper arg <> "!" else arg
+      if mode == "Print" then putStrLn msg else pure ()
+```
+
+Running this with `argument-taker help`, we see:
+
+```
+usage:
+name: argument-taker
+|
++- subprogram: help
+|
+`- option: -m <mode :: [Char]>
+   |
+   `- argument: example-argument :: [Char]
+      |
+      `- flag: ~loud
+         |
+         `- description: Takes the argument and prints it or not, depending on the mode and possibly loudly
+```
+
+Okay, so we've added all of the normal command line things, but we haven't yet shown how to add a new command
+to our program, so lets do that. To do this, we can write:
+
+```haskell
+main = command_
+  . toplevel @"argument-taker"
+  $ defaultProgram <+> sub @"shriek" (raw (putStrLn "AHHHHH!!"))
+  where
+  defaultProgram = 
+      optDef @"m" @"mode" "Print" $ \mode ->
+      arg @"example-argument" $ \arg ->
+      flag @"loud" $ \loud ->
+      description @"Takes the argument and prints it or not, depending on the mode and possibly loudly" 
+    . raw $ do
+        let msg = if loud then map toUpper arg <> "!" else arg
+        if mode == "Print" then putStrLn msg else pure ()
+```
+
+Running this program with `argument-taker help`, we can see the docs yet again:
+
+```
+usage:
+name: argument-taker
+|
++- subprogram: help
+|
++- option: -m <mode :: [Char]>
+|  |
+|  `- argument: example-argument :: [Char]
+|     |
+|     `- flag: ~loud
+|        |
+|        `- description: Takes the argument and prints it or not, depending on the mode and possibly loudly
+|
+`- subprogram: shriek
+```
+
+Awesome! So we have now shown how to use the primitives of CLI programs, as well as how to
+add new subprograms. One more thing I would like to show that is different from normal CLI
+libraries is that I added the ability to automatically search for environment variables and
+pass them to your program. I just liked this, as sometimes when I use a CLI program I forget
+this or that environment variable, and the documentation generation makes this self documenting
+in commander-cli. We can add this to our program by writing:
+
+```haskell
+main = command_
+  . toplevel @"argument-taker"
+  $ env @"ARGUMENT_TAKER_DIRECTORY" \argumentTakerDirectory ->
+      defaultProgram argumentTakerDirectory
+  <+> sub @"shriek" (raw $ do
+        setCurrentDirectory argumentTakerDirectory 
+        putStrLn "AHHH!"
+      )
+  where
+  defaultProgram argumentTakerDirectory = 
+      optDef @"m" @"mode" "Print" $ \mode ->
+      arg @"example-argument" $ \arg ->
+      flag @"loud" $ \loud ->
+      description @"Takes the argument and prints it or not, depending on the mode and possibly loudly" 
+    . raw $ do
+        setCurrentDirectory argumentTakerDirectory
+        let msg = if loud then map toUpper arg <> "!" else arg
+        if mode == "Print" then putStrLn msg else pure ()
+```
+
+Now, we will see `argument-taker help` as:
+
+```
+usage:
+name: argument-taker
+|
++- subprogram: help
+|
+`- required env: ARGUMENT_TAKER_DIRECTORY :: [Char]
+   |
+   +- option: -m <mode :: [Char]>
+   |  |
+   |  `- argument: example-argument :: [Char]
+   |     |
+   |     `- flag: ~loud
+   |        |
+   |        `- description: Takes the argument and prints it or not, depending on the mode and possibly loudly
+   |
+   `- subprogram: shriek
+```
+
+We can see that it documents the usage of this environment variable in a
+reasonable way, but its not clear where exactly what it does exactly. First,
+you might think to use the `description` combinator, but it isn't exactly made
+for describing an input, but for documenting a path of a program. We can fix this
+using the `annotated` combinator, which was made for describing inputs to our
+program:
+
+```haskell
+main :: IO ()
+main = command_
+  . toplevel @"argument-taker"
+  . annotated @"the directory we will go to for the program"
+  $ env @"ARGUMENT_TAKER_DIRECTORY" \argumentTakerDirectory ->
+      defaultProgram argumentTakerDirectory
+  <+> sub @"shriek" (raw $ do
+        setCurrentDirectory argumentTakerDirectory 
+        putStrLn "AHHH!"
+      )
+  where
+  defaultProgram argumentTakerDirectory = 
+      optDef @"m" @"mode" "Print" $ \mode ->
+      arg @"example-argument" $ \arg ->
+      flag @"loud" $ \loud ->
+      description @"Takes the argument and prints it or not, depending on the mode" 
+    . raw $ do
+        setCurrentDirectory argumentTakerDirectory
+        let msg = if loud then map toUpper arg <> "!" else arg
+        if mode == "Print" then putStrLn msg else pure ()
+```
+
+Running `argument-taker help` will result in:
+
+```
+usage:
+name: argument-taker
+|
++- subprogram: help
+|
+`- required env: ARGUMENT_TAKER_DIRECTORY :: [Char], the directory we will go to for the program
+   |
+   +- option: -m <mode :: [Char]>
+   |  |
+   |  `- argument: example-argument :: [Char]
+   |     |
+   |     `- flag: ~loud
+   |        |
+   |        `- description: Takes the argument and prints it or not, depending on the mode
+   |
+   `- subprogram: shriek
 ```
 
 ## Design
diff --git a/app/Main.hs b/app/Main.hs
--- a/app/Main.hs
+++ b/app/Main.hs
@@ -10,6 +10,7 @@
 {-# LANGUAGE TypeOperators #-}
 module Main where
 
+import Data.Char (toUpper)
 import Control.Monad
 import Options.Commander 
 import Prelude
@@ -162,16 +163,4 @@
       False -> Context home [] <$ createDirectory tasksFilePath
   
 main :: IO ()
-main = command_ . toplevel @"file" $
- (sub @"maybe-read" $
-  arg @"filename" \filename ->
-  flag @"read" \b -> raw $
-    if b
-      then putStrLn =<< readFile filename
-      else pure ())
-  <+>
- (sub @"maybe-write" $
-  opt @"file" @"file-to-write" \mfilename -> raw $
-    case mfilename of
-      Just filename -> putStrLn =<< readFile filename
-      Nothing -> pure ())
+main = command_ taskManager
diff --git a/commander-cli.cabal b/commander-cli.cabal
--- a/commander-cli.cabal
+++ b/commander-cli.cabal
@@ -1,7 +1,7 @@
 cabal-version:       2.4
 
 name:                commander-cli
-version:             0.10.0.1
+version:             0.10.1.0
 synopsis:            A command line argument/option parser library
 description:         A command line argument/option parser library.
 homepage:            https://github.com/SamuelSchlesinger/commander-cli
diff --git a/src/Options/Commander.hs b/src/Options/Commander.hs
--- a/src/Options/Commander.hs
+++ b/src/Options/Commander.hs
@@ -88,7 +88,7 @@
     variables as well. We also have a convenience combinator, 'toplevel',
     which lets you add a name and a help command to your program using the 'usage' combinator.
   -}
-  arg, opt, optDef, raw, sub, named, flag, toplevel, (<+>), usage, env, envOpt, envOptDef, description,
+  arg, opt, optDef, raw, sub, named, flag, toplevel, (<+>), usage, env, envOpt, envOptDef, description, annotated,
   -- ** Run CLI Programs
   {- |
     To run a 'ProgramT' (a specification of a CLI program), you will 
@@ -99,7 +99,7 @@
     Each 'ProgramT' has a type level description, build from these type level
     combinators.
   -}
-  type (&), type (+), Arg, Opt, Named, Raw, Flag, Env, Optionality(Required, Optional), Description,
+  type (&), type (+), Arg, Opt, Named, Raw, Flag, Env, Optionality(Required, Optional), Description, Annotated,
   -- ** Interpreting CLI Programs
   {- |
     The 'HasProgram' class forms the backbone of this library, defining the
@@ -116,6 +116,7 @@
            EnvProgramT'Optional, unEnvProgramT'Optional, unEnvDefault,
            EnvProgramT'Required, unEnvProgramT'Required,
            DescriptionProgramT,
+           AnnotatedProgramT,
            (:+:)
            ),
   -- ** The CommanderT Monad
@@ -221,36 +222,39 @@
 instance Unrender Char where
   unrender = find (const True)
 
--- | The type level naming combinator, giving your program a name for the
--- sake of documentation.
+-- | The type level combinator for constructing 'named' programs, giving your
+-- program a name at the toplevel for the sake of documentation.
 data Named :: Symbol -> *
 
--- | The type level argument combinator, with a 'Symbol' designating the
+-- | The type level 'arg'ument combinator, with a 'Symbol' designating the
 -- name of that argument.
 data Arg :: Symbol -> * -> *
 
--- | The type level option combinator, with a 'Symbol' designating the
+-- | The type level 'opt'ion combinator, with a 'Symbol' designating the
 -- option's name and another representing the metavariables name for
 -- documentation purposes.
 data Opt :: Symbol -> Symbol -> * -> *
 
--- | The type level flag combinator, taking a name as input, allowing your
+-- | The type level 'flag' combinator, taking a name as input, allowing your
 -- program to take flags with the syntax @~flag@.
 data Flag :: Symbol -> *
 
--- | The type level environment variable combinator, taking a name as
+-- | The type level 'env'ironment variable combinator, taking a name as
 -- input, allowing your program to take environment variables as input
 -- automatically.
 data Env :: Optionality -> Symbol -> * -> *
 
--- | The type level raw monadic program combinator, allowing a command line
+-- | The type level 'raw' monadic program combinator, allowing a command line
 -- program to just do some computation.
 data Raw :: *
 
--- | The type level description combinator, allowing a command line program
+-- | The type level 'description' combinator, allowing a command line program
 -- to have better documentation.
 data Description :: Symbol -> *
 
+-- | The type level 'annotated' combinator, allowing a command line 
+data Annotated :: Symbol -> * -> *
+
 -- | The type level tag for whether or not a variable is required or not.
 data Optionality = Required | Optional
 
@@ -387,7 +391,7 @@
     (documentation @p)]
 
 instance (KnownSymbol name, HasProgram p) => HasProgram (Named name & p) where
-  newtype ProgramT (Named name &p) m a = NamedProgramT { unNamedProgramT :: ProgramT p m a }
+  newtype ProgramT (Named name & p) m a = NamedProgramT { unNamedProgramT :: ProgramT p m a }
   run = run . unNamedProgramT 
   hoist n = NamedProgramT . hoist n . unNamedProgramT
   documentation = [Node
@@ -395,13 +399,19 @@
     (documentation @p)]
 
 instance (KnownSymbol description, HasProgram p) => HasProgram (Description description & p) where
-  newtype ProgramT (Description description &p) m a = DescriptionProgramT { unDescriptionProgramT :: ProgramT p m a }
+  newtype ProgramT (Description description & p) m a = DescriptionProgramT { unDescriptionProgramT :: ProgramT p m a }
   run = run . unDescriptionProgramT 
   hoist n = DescriptionProgramT . hoist n . unDescriptionProgramT
   documentation = [Node
     ("description: " <> symbolVal (Proxy @description))
     []] <> documentation @p
 
+instance (KnownSymbol annotation, HasProgram (combinator & p)) => HasProgram (Annotated annotation combinator & p) where
+  newtype ProgramT (Annotated annotation combinator & p) m a = AnnotatedProgramT { unAnnotatedProgramT :: ProgramT (combinator & p) m a }
+  run = run . unAnnotatedProgramT 
+  hoist n = AnnotatedProgramT . hoist n . unAnnotatedProgramT
+  documentation = fmap (\(Node x s) -> Node (x <> ", " <> symbolVal (Proxy @annotation)) s) (documentation @(combinator & p))
+
 instance (KnownSymbol sub, HasProgram p) => HasProgram (sub & p) where
   newtype ProgramT (sub & p) m a = SubProgramT { unSubProgramT :: ProgramT p m a }
   run s = Action $ \State{..} -> do 
@@ -534,6 +544,11 @@
 usage = raw $ do
   liftIO $ putStrLn "usage:"
   liftIO $ putStrLn (document @p)
+
+-- | A combinator which augments the documentation of the next element, by
+-- adding a description after its name and type.
+annotated :: forall annotation combinator p m a. ProgramT (combinator & p) m a -> ProgramT (Annotated annotation combinator & p) m a
+annotated = AnnotatedProgramT
 
 -- | A combinator which takes a program, and a type-level 'Symbol'
 -- description of that program, and produces a program here the
