diff --git a/System/Console/CmdLib.hs b/System/Console/CmdLib.hs
--- a/System/Console/CmdLib.hs
+++ b/System/Console/CmdLib.hs
@@ -44,6 +44,14 @@
 module System.Console.CmdLib (
   -- * News
   --
+  -- | Since version 0.3: "dispatchR" no longer takes a cmd argument, as it was
+  -- never used for anything and was simply confusing. A new function,
+  -- "dispatchOr" has been added to allow the program to continue despite
+  -- otherwise fatal errors (unknown command, unknown flags).  New function,
+  -- "commandNames", has been added, to go from [CommandWrap] to [String]. The
+  -- "CommandWrap" type is now exported (opaque).  The "RecordCommand" class
+  -- now has a mode_help method. "RecordMode" is no longer exported.
+  --
   -- | Since version 0.2: The Positional arguments are no longer required to be
   -- strings. A default (fallback) command may be provided to
   -- "dispatch"/"dispatchR" (this has also incompatibly changed their
@@ -66,21 +74,21 @@
 
   -- | Flags (commandline options) can be represented in two basic styles,
   -- either as a plain ADT (algebraic data type) or as a record type. These two
-  -- styles are implemented using "ADTFlag" and "ADT" for the former and
-  -- "RecordFlag" and "Record" for the latter. The *Flag classes can be used to
-  -- attach attributes to flags and to override the parser for option
-  -- arguments. However, an empty instance is valid for both cases. The "ADT"
-  -- and "Record" newtype wrappers are then used in a "Command" or
-  -- "RecordCommand" instance declaration.
+  -- styles are implemented using the "ADT" wrapper for the former and and a
+  -- "Record" wrapper for the latter. You need to make your type an instance of
+  -- the "Attributes" class, which can be used to attach attributes to the
+  -- flags.
 
   , ADT, Record, Attributes(..)
 
   -- * Commands
-  , (%:), commandGroup, Command(..), dispatch, execute, helpCommands, helpOptions
+  , (%:), commandGroup, Command(..), dispatch, dispatchOr, execute, helpCommands, helpOptions
   , noHelp, defaultCommand, OptionStyle(..)
+  , CommandWrap -- just the type (for signatures in users code)
+  , commandNames
 
   -- * Record-based commands
-  , RecordCommand(..), RecordMode(..), recordCommands, dispatchR, executeR
+  , RecordCommand(..), recordCommands, dispatchR, executeR
 
   -- * Utilities
   , globalFlag, readCommon, (<+<), HelpCommand(..), die
@@ -109,11 +117,11 @@
 -- > data Flag = Wibblify Int | Verbose Bool
 -- > (setVerbose, isVerbose) = globalFlag False
 -- >
--- > instance ADTFlag Flag where
--- >     adt_attrs _ = Verbose %> Global setVerbose
+-- > instance Attributes Flag where
+-- >     attributes _ = Verbose %> Global setVerbose
 -- >
 -- > putVerbose str = isVerbose >>= flip when (putStrLn str)
-globalFlag :: a -> (a -> IO (), IO a)
+globalFlag :: Typeable a => a -> (a -> IO (), IO a)
 globalFlag def = unsafePerformIO $ do ref <- newIORef def
                                       return (writeIORef ref, readIORef ref)
 {-# NOINLINE globalFlag #-}
diff --git a/System/Console/CmdLib/Command.hs b/System/Console/CmdLib/Command.hs
--- a/System/Console/CmdLib/Command.hs
+++ b/System/Console/CmdLib/Command.hs
@@ -114,6 +114,16 @@
         one (CommandGroup name l) = "\n" ++ name ++ ":\n" ++ helpCommands l
         pad str = (take 15 $ str ++ replicate 15 ' ') ++ " "
 
+-- | This could be used to implement a disambiguation function
+--
+-- Note that there isn't presently a notion of hidden commands,
+-- but we're taking them into account now for future API stability
+commandNames :: Bool -- ^ show hidden commands too
+             -> [CommandWrap] -> [String]
+commandNames _ x = concatMap one x
+  where one (CommandWrap c) = [cmdname c]
+        one (CommandGroup _ cs) = concatMap one cs
+
 execute' :: forall cmd f. (Command cmd f) => cmd -> [String] -> IO (Maybe (Folded f, [String]))
 execute' cmd opts
   | "--help" `elem` opts && not (supercommand cmd) = printHelp cmd >> return Nothing
@@ -191,11 +201,12 @@
 printHelp c = putStr $ helpOptions c
 printCommands comms = putStr $ helpCommands comms
 
-dispatch' :: [DispatchOpt] -> [CommandWrap] -> [String] -> IO (Maybe (CommandWrap, [String]))
-dispatch' dopt comms' args = case args of
+dispatch' :: (String -> IO ()) -- ^ fail
+          -> [DispatchOpt] -> [CommandWrap] -> [String] -> IO (Maybe (CommandWrap, [String]))
+dispatch' diefn dopt comms' args = case args of
   [] | isNothing def -> dieHelp "Command required."
      | otherwise -> return $ Just (fromJust def, [])
-  ("--help":_) -> printCommands comms >> return Nothing
+  ("--help":x) -> dispatch' diefn dopt comms' ("help":x)
   (cmd:args') -> case findCommand cmd comms of
     Nothing -> case def of
       Nothing -> dieHelp $ "No such command " ++ cmd
@@ -203,7 +214,7 @@
     Just x -> return $ Just (x, args')
   where comms | null [ () | NoHelp <- dopt ] = HelpCommand comms %: comms'
               | otherwise = comms'
-        dieHelp msg = printCommands comms >> die msg >> return Nothing
+        dieHelp msg = printCommands comms >> diefn msg >> return Nothing
         def | (DefaultCommand n:_) <- [ o | o@(DefaultCommand _) <- dopt ] = Just n
             | otherwise = Nothing
 
@@ -217,9 +228,16 @@
 -- and transfer control to the command.  This function also implements the
 -- @help@ pseudocommand.
 dispatch :: [DispatchOpt] -> [CommandWrap] -> [String] -> IO ()
-dispatch dopt comms opts = dispatch' dopt comms opts >>= \c -> case c of
+dispatch = dispatchOr die
+
+-- | Like 'dispatch' but with the ability to control what happens when there
+--   is an error on user input
+dispatchOr :: (String -> IO ()) -- ^ eg. 'die'
+           -> [DispatchOpt] -> [CommandWrap] -> [String] -> IO ()
+dispatchOr die dopt comms opts = dispatch' die dopt comms opts >>= \c -> case c of
   Nothing -> return ()
   Just (CommandWrap c, opts') -> execute c opts'
+
 
 -- | Helper for dying with an error message (nicely, at least compared to
 -- "fail" in IO).
diff --git a/System/Console/CmdLib/Record.hs b/System/Console/CmdLib/Record.hs
--- a/System/Console/CmdLib/Record.hs
+++ b/System/Console/CmdLib/Record.hs
@@ -38,7 +38,7 @@
 -- TODO: List-based option types should be accumulated instead of overriden.
 data (Attributes rec) => Record rec = Record rec String deriving Eq
 
-instance (Eq (Record rec), Data rec, Attributes rec) => FlagType (Record rec) where
+instance (Eq rec, Eq (Record rec), Data rec, Attributes rec) => FlagType (Record rec) where
   type Folded (Record rec) = rec
 
   flag_attrkey (Record _ f) = KeyF (typeOf (undefined :: rec)) f
@@ -68,7 +68,8 @@
 
   flag_value (Record _ field) folded = getField field folded
   flag_set (Record _ field) v = \x -> setField field x (errcast v)
-     where errcast x = case cast x of
+     where errcast :: (Typeable a, Typeable b) => a -> b
+           errcast x = case cast x of
                            Just x -> x
                            Nothing -> error "BUG: flag_set in Record used with wrong value type"
 
@@ -112,21 +113,26 @@
   rec_options :: cmd -> AttributeMap Key
   rec_options _ = EmptyMap
 
-  -- | Provide a help string for each mode. Used in help output. Again, pattern
-  -- match like in @run'@.
+  -- | Provide a summary help string for each mode. Used in help output. Again,
+  -- pattern match like in @run'@.
   mode_summary :: cmd -> String
   mode_summary _ = ""
 
+  -- | Provide a help blurb for each mode. Use patterns like in @run'@.
+  mode_help :: cmd -> String
+  mode_help _ = ""
+
 data RecordMode cmd = RecordMode { rec_cmdname :: String
                                  , rec_initial :: Constr }
                     deriving (Typeable)
 
-instance (Eq (Record cmd), RecordCommand cmd, Data cmd, Attributes cmd)
+instance (Eq cmd, Eq (Record cmd), RecordCommand cmd, Data cmd, Attributes cmd)
          => Command (RecordMode cmd) (Record cmd) where
   cmdname = rec_cmdname
   run _ = run'
 
   summary cmd = mode_summary $ (fromConstr $ rec_initial cmd :: cmd)
+  help cmd = mode_help $ (fromConstr $ rec_initial cmd :: cmd)
 
   options cmd = rec_options ctor %% available %% everywhere disable
     where available = [ (KeyF (typeOf (undefined :: cmd)) opt, [enable])
@@ -136,8 +142,10 @@
   cmd_flag_empty cmd = fromConstr $ rec_initial cmd
 
 -- | Construct a command list (for "dispatch"/"helpCommands") from a
--- multi-constructor record data type. See also "RecordCommand".
-recordCommands :: forall cmd. (Eq (Record cmd), Data cmd, RecordCommand cmd, Attributes cmd) => cmd -> [CommandWrap]
+-- multi-constructor record data type. See also "RecordCommand". Alternatively,
+-- you can use "dispatchR" directly.
+recordCommands :: forall cmd. (Eq cmd, Eq (Record cmd), Data cmd, RecordCommand cmd, Attributes cmd)
+               => cmd -> [CommandWrap]
 recordCommands _ = go $ dataTypeConstrs $ dataTypeOf (undefined :: cmd)
     where go = map $ CommandWrap . rec_cmd
           rec_cmd :: Constr -> RecordMode cmd
@@ -166,10 +174,16 @@
           errcast :: forall a b. (Typeable a, Typeable b) => a -> b
           errcast = fromMaybe (error $ "BUG: getField used with wrong type on " ++ field) . cast
 
-dispatchR :: forall cmd f. (Eq (Record cmd), Attributes cmd, RecordCommand cmd,
+-- | A command parsing & dispatch entry point for record-based
+-- commands. Ex. (see "RecordCommand"):
+--
+-- > main = getArgs >>= dispatchR [] >>= \x -> case x of
+-- >   Foo {} -> putStrLn $ "You asked for foo. Wibble = " ++ show (wibble x)
+-- >   Bar {} -> putStrLn $ "You asked for bar. ..."
+dispatchR :: forall cmd f. (Eq cmd, Eq (Record cmd), Attributes cmd, RecordCommand cmd,
                             Command (RecordMode cmd) f,
-                            Folded f ~ cmd) => [DispatchOpt] -> cmd -> [String] -> IO cmd
-dispatchR dopt _ opts = dispatch' dopt (recordCommands (undefined :: cmd)) opts >>= \c -> case c of
+                            Folded f ~ cmd) => [DispatchOpt] -> [String] -> IO cmd
+dispatchR dopt opts = dispatch' die dopt (recordCommands (undefined :: cmd)) opts >>= \c -> case c of
   Nothing -> exitWith ExitSuccess >> return undefined
   Just (CommandWrap x, opts') -> execute' x opts' >>= \c -> case c of
     Just (command, opts') -> case (cast command) of
@@ -177,7 +191,17 @@
       Nothing -> execute x opts' >> exitWith ExitSuccess >> return undefined
     Nothing -> exitWith ExitSuccess >> return undefined
 
-executeR :: forall cmd. (Eq (Record cmd), Attributes cmd, RecordCommand cmd) => cmd -> [String] -> IO cmd
+-- | Like "execute", but you get the flags as a return value. This is useful to
+-- implement non-modal applications with record-based flags, eg.:
+--
+-- > data Main = Main { greeting :: String, again :: Bool }
+-- >     deriving (Typeable, Data, Eq)
+-- > instance Attributes Main where -- (...)
+-- > instance RecordCommand Main
+-- > main = getArgs >>= executeR Main {} >>= \opts -> do
+-- >    putStrLn (greeting opts) -- (...)
+executeR :: forall cmd. (Eq cmd, Eq (Record cmd), Attributes cmd, RecordCommand cmd)
+         => cmd -> [String] -> IO cmd
 executeR cmd opts = execute' cmd' opts >>= \c -> case c of
   Just (command, _) -> return command
   Nothing -> exitWith ExitSuccess >> return undefined
diff --git a/cmdlib.cabal b/cmdlib.cabal
--- a/cmdlib.cabal
+++ b/cmdlib.cabal
@@ -1,12 +1,30 @@
-name:                cmdlib
-version:             0.2.1
-synopsis:            a library for command line parsing & online help
+name:        cmdlib
+version:     0.3
+synopsis:    a library for command line parsing & online help
 
-description: An alternative to cmdargs, based on getopt. Comes with a powerful
-             attribute system. Supports complex interfaces with many options
-             and commands, with option & command grouping, while at the same
-             time keeping simple things simple.
+description: A commandline parsing library, based on getopt. Comes with a
+             powerful attribute system. Supports complex interfaces with many
+             options and commands, with option & command grouping, with simple
+             and convenient API. Even though quite powerful, it strives to keep
+             simple things simple. The library uses "System.Console.GetOpt" as
+             its backend.
+             .
+             In comparison to the other commandline handling libraries:
+             .
+             Compared to cmdargs, cmdlib has a pure attribute system and is
+             based on GetOpt for help formatting & argument parsing. Cmdlib may
+             also be more extendable due to typeclass design, and can use
+             user-supplied types for option arguments.
+             .
+             Cmdargs >= 0.4 can optionally use a pure attribute system,
+             although this is clearly an add-on and the API is a second-class
+             citizen in relation to the impure version.
+             .
+             GetOpt and parseargs both require explicit flag representation, so
+             they live a level below cmdlib. GetOpt is in fact used as a
+             backend by cmdlib.
 
+
 -- The license under which the package is released.
 -- copyright:
 license:             BSD3
@@ -35,7 +53,7 @@
                  System.Console.CmdLib.ADTs
                  System.Console.CmdLib.Record
 
-  build-depends: base < 5, syb, mtl, split
+  build-depends: base >= 4 && < 5, syb, mtl, split
 
 flag test
   default:     False
