diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,22 @@
 
 ## Unreleased
 
+## 0.2.0.0 - 2026-08-14
+
+### Added
+
+- Documentation about where to obtain this library
+
+### Changed
+
+- Loosen bounds on dependency versions so the project can be built
+  against a wider range of snapshots
+- Change the error message type for TextParsers from 'Builder' to 'Text'
+- Fix missing help options in help output
+- Fix unit test builds when using cabal
+- Make minor code quality improvements
+- Add strictness annotations to simple values in constructors
+
 ## 0.1.0.0 - 2026-08-12
 
 ### Added
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,5 +1,6 @@
-# Mangrove
+# Mangrove (mangrove-cli)
 
+[![Hackage](https://img.shields.io/hackage/v/mangrove-cli.svg)](https://hackage.haskell.org/package/mangrove-cli)
 [![Unit Tests](https://github.com/quytelda/mangrove/actions/workflows/unit-tests.yml/badge.svg)](https://github.com/quytelda/mangrove/actions/workflows/unit-tests.yml)
 
 Mangrove is a library for building command line argument parsers using
@@ -8,6 +9,17 @@
 and commands, as well as complex subparameters and suboptions (e.g.
 `--mount src=/webroot,dst=/var/www,rw`). It is also extensible, so you
 can define alternative command line syntaxes.
+
+## Obtaining
+
+Mangrove is available on Hackage as `mangrove-cli`:
+<https://hackage.haskell.org/package/mangrove-cli>
+
+__NOTE__: This project is not related to the `mangrove` package on
+Hackage. Make sure to use the package name `mangrove-cli`.
+
+The source code for Mangrove is hosted on GitHub:
+<https://github.com/quytelda/mangrove>
 
 ## Building
 
diff --git a/mangrove-cli.cabal b/mangrove-cli.cabal
--- a/mangrove-cli.cabal
+++ b/mangrove-cli.cabal
@@ -5,7 +5,7 @@
 -- see: https://github.com/sol/hpack
 
 name:           mangrove-cli
-version:        0.1.0.0
+version:        0.2.0.0
 synopsis:       Build CLI argument parsers using Applicative.
 description:    Please see the README on GitHub at <https://github.com/quytelda/mangrove#readme>
 category:       CLI, Options, Parsing
@@ -46,10 +46,10 @@
   ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints
   build-depends:
       base >=4.7 && <5
-    , containers >=0.6.7 && <0.9
-    , mtl >=2.3.1 && <2.4
-    , text >=2.0.2 && <2.2
-    , transformers >=0.6.1 && <0.7
+    , containers >=0.6.4 && <0.9
+    , mtl >=2.2.2 && <2.4
+    , text >=1.2.5 && <2.2
+    , transformers >=0.5.6 && <0.7
   default-language: Haskell2010
 
 test-suite mangrove-cli-test
@@ -66,12 +66,14 @@
   hs-source-dirs:
       test
   ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N
+  build-tool-depends:
+      hspec-discover:hspec-discover >=2.8.5 && <3
   build-depends:
       base >=4.7 && <5
-    , containers >=0.6.7 && <0.9
-    , hspec >=2.9 && <3
+    , containers >=0.6.4 && <0.9
+    , hspec >=2.8.5 && <3
     , mangrove-cli
-    , mtl >=2.3.1 && <2.4
-    , text >=2.0.2 && <2.2
-    , transformers >=0.6.1 && <0.7
+    , mtl >=2.2.2 && <2.4
+    , text >=1.2.5 && <2.2
+    , transformers >=0.5.6 && <0.7
   default-language: Haskell2010
diff --git a/src/Mangrove.hs b/src/Mangrove.hs
--- a/src/Mangrove.hs
+++ b/src/Mangrove.hs
@@ -75,7 +75,7 @@
 deriving instance Show r => Show (Result s r)
 deriving instance Eq r => Eq (Result s r)
 
--- | Create a default initial 'StreamState' from a list of arguments.
+-- | Create a default initial t'StreamState' from a list of arguments.
 argsToState :: [Text] -> StreamState s
 argsToState args = StreamState args [] False
 
@@ -89,7 +89,7 @@
 runSilentParser tree = runSilentParser' tree . argsToState
 
 -- | A more general form of 'runSilentParser' that accepts a custom
--- 'StreamState' as the starting state.
+-- stream starting state.
 runSilentParser'
   :: (Scheme s, HelpSupport s ~ 'Silent)
   => ParseTree s r -- ^ Argument parser
@@ -109,7 +109,7 @@
 runHelpfulParser info tree = runHelpfulParser' info tree . argsToState
 
 -- | A more general form of 'runHelpfulParser' that accepts a custom
--- 'StreamState' as the starting state.
+-- stream starting state.
 runHelpfulParser'
   :: SupportsHelp s
   => ProgramInfo -- ^ Program metadata
@@ -171,15 +171,10 @@
   -> (Text -> a) -- ^ Failure handler
   -> HelpHandler s a -- ^ Help request handler
   -> a
-runArgumentParser tree args =
-  runArgumentParser' tree StreamState
-  { streamContent = args
-  , streamContext = []
-  , streamEscaped = False
-  }
+runArgumentParser tree = runArgumentParser' tree . argsToState
 
 -- | A more general form of 'runArgumentParser' that accepts a custom
--- 'StreamState' as the starting state.
+-- stream starting state.
 runArgumentParser'
   :: Scheme s
   => ParseTree s r -- ^ Argument parser
diff --git a/src/Mangrove/Parser.hs b/src/Mangrove/Parser.hs
--- a/src/Mangrove/Parser.hs
+++ b/src/Mangrove/Parser.hs
@@ -101,15 +101,15 @@
   -- | Terminal node with no value (abstracts 'empty')
   EmptyNode :: ParseTree scheme r
   -- | A terminal node with a resolved value (abstracts 'pure')
-  ValueNode :: r -> ParseTree scheme r
+  ValueNode :: !r -> ParseTree scheme r
   -- | A parser awaiting input
   ParseNode :: scheme r -> ParseTree scheme r
   -- | Abstracts 'liftA2' and by extension '(<*>)'
-  ProdNode :: (u -> v -> r) -> ParseTree scheme u -> ParseTree scheme v -> ParseTree scheme r
+  ProdNode :: !(u -> v -> r) -> ParseTree scheme u -> ParseTree scheme v -> ParseTree scheme r
   -- | Abstracts '(<|>)'
   SumNode :: ParseTree scheme r -> ParseTree scheme r -> ParseTree scheme r
   -- | Abstracts 'many' (@MaybeNode False@) and 'some' (@MaybeNode True@)
-  ManyNode :: Bool -> ParseTree scheme r -> ParseTree scheme [r]
+  ManyNode :: !Bool -> ParseTree scheme r -> ParseTree scheme [r]
 
 instance Functor p => Functor (ParseTree p) where
   fmap _ EmptyNode          = EmptyNode
@@ -319,9 +319,9 @@
 -- arguments to be interpreted as positional arguments, even if they
 -- would normally be interpreted as options or commands.
 data StreamState s = StreamState
-  { streamContent :: [Text]    -- ^ A sequence of 'Text' values
-  , streamContext :: [Token s] -- ^ A stack representing current parsing context
-  , streamEscaped :: Bool      -- ^ Escaped mode
+  { streamContent :: ![Text]    -- ^ A sequence of 'Text' values
+  , streamContext :: ![Token s] -- ^ A stack representing current parsing context
+  , streamEscaped :: !Bool      -- ^ Escaped mode
   }
 
 deriving instance Scheme s => Show (StreamState s)
diff --git a/src/Mangrove/Resolve.hs b/src/Mangrove/Resolve.hs
--- a/src/Mangrove/Resolve.hs
+++ b/src/Mangrove/Resolve.hs
@@ -29,8 +29,8 @@
 -- and didn't find it, and (2) the parser resolved to an empty value.
 data ResolveM a
   = EmptyError
-  | ExpectedError [Builder]
-  | Value a
+  | ExpectedError ![Builder]
+  | Value !a
   deriving (Functor)
 
 instance Applicative ResolveM where
diff --git a/src/Mangrove/Scheme/Sub.hs b/src/Mangrove/Scheme/Sub.hs
--- a/src/Mangrove/Scheme/Sub.hs
+++ b/src/Mangrove/Scheme/Sub.hs
@@ -34,7 +34,7 @@
 -- | Parsers for subarguments of an option (e.g. @--option key=value@).
 data SubScheme r
   = Parameter (TextParser r) -- ^ Parses freeform arguments
-  | Option Text (TextParser r) -- ^ Suboptions have the form "KEY=VALUE"
+  | Option !Text (TextParser r) -- ^ Suboptions have the form "KEY=VALUE"
   deriving (Functor)
 
 instance Valency SubScheme where
diff --git a/src/Mangrove/Scheme/Unix.hs b/src/Mangrove/Scheme/Unix.hs
--- a/src/Mangrove/Scheme/Unix.hs
+++ b/src/Mangrove/Scheme/Unix.hs
@@ -68,8 +68,8 @@
 -- Thus, you can write @"--flop"@ instead of @LongFlag "flop"@ and
 -- @"-c"@ instead of @ShortFlag \'c\'@.
 data Flag
-  = LongFlag Text
-  | ShortFlag Char
+  = LongFlag !Text
+  | ShortFlag !Char
   deriving (Eq, Ord, Show)
 
 instance IsString Flag where
@@ -85,8 +85,8 @@
 
 -- | A description of a CLI option.
 data OptionInfo = OptionInfo
-  { optFlags :: NonEmpty Flag -- ^ A list of flags that trigger this option.
-  , optHelp  :: Text -- ^ A description displayed in help output.
+  { optFlags :: !(NonEmpty Flag) -- ^ A list of flags that trigger this option.
+  , optHelp  :: !Text -- ^ A description displayed in help output.
   } deriving (Eq, Ord, Show)
 
 -- | Get a representative flag for this option (e.g. the first one).
@@ -95,8 +95,8 @@
 
 -- | A description of a CLI command.
 data CommandInfo = CommandInfo
-  { cmdNames :: NonEmpty Text -- ^ Command Names
-  , cmdHelp  :: Text -- ^ A description displayed in help output.
+  { cmdNames :: !(NonEmpty Text) -- ^ Command Names
+  , cmdHelp  :: !Text -- ^ A description displayed in help output.
   } deriving (Eq, Ord, Show)
 
 -- | Get a representative command name for this command (e.g. the
@@ -109,11 +109,11 @@
   -- | A freeform positional parameter
   = Parameter (TextParser r)
   -- | A subcommand with its own parse tree
-  | Command CommandInfo (ParseTree UnixScheme r)
+  | Command !CommandInfo (ParseTree UnixScheme r)
   -- | A named option that might support suboptions
-  | Option OptionInfo (ParseTree SubScheme r)
+  | Option !OptionInfo (ParseTree SubScheme r)
   -- | A special option that requests help information
-  | HelpOption OptionInfo
+  | HelpOption !OptionInfo
   deriving (Functor)
 
 instance Valency UnixScheme where
@@ -344,10 +344,10 @@
     go node = node
 
 data OptionHelp = OptionHelp
-  { colShorts :: TL.Text -- Column 1
-  , colLongs  :: TL.Text -- Column 2
-  , colArg    :: TL.Text -- Column 3
-  , colDesc   :: TL.Text -- Column 4
+  { colShorts :: !TL.Text -- Column 1
+  , colLongs  :: !TL.Text -- Column 2
+  , colArg    :: !TL.Text -- Column 3
+  , colDesc   :: !TL.Text -- Column 4
   } deriving (Eq, Ord, Show)
 
 makeOptionHelp :: OptionInfo -> ParseTree SubScheme r -> OptionHelp
@@ -376,6 +376,8 @@
        -> Map [CommandInfo] [OptionHelp]
     go (ParseNode (Option info subtree)) =
       Map.insertWith (<>) [] [makeOptionHelp info subtree]
+    go (ParseNode (HelpOption info)) =
+      Map.insertWith (<>) [] [makeOptionHelp info empty]
     go (ParseNode (Command info subtree)) =
       Map.union $ Map.mapKeys (info :) $ collectOptions subtree
     go (ProdNode _ l r) = go r . go l
diff --git a/src/Mangrove/Separable.hs b/src/Mangrove/Separable.hs
--- a/src/Mangrove/Separable.hs
+++ b/src/Mangrove/Separable.hs
@@ -24,7 +24,7 @@
 -- input. This can happen because the parsing context changed (for
 -- example, when a command is recognized) or when the parsing is
 -- exited entirely (for example, when a help option is encountered).
-data Modal a = Modal Bool a
+data Modal a = Modal !Bool a
   deriving (Functor)
 
 instance Applicative Modal where
@@ -39,7 +39,7 @@
 usesTerseOutput :: Modal a -> Bool
 usesTerseOutput (Modal terseOutput _) = terseOutput
 
--- | An 'Exhibit' represents an object whose modal sub-components have
+-- | A representation of an object whose modal sub-components have
 -- been split off for the purpose of better help output.
 --
 -- Every parser and parse tree can be decomposed into one regular tree
@@ -47,7 +47,7 @@
 data Exhibit a = Exhibit (Maybe a) [Modal a]
   deriving (Functor)
 
--- | Convert an 'Exhibit' to a regular list of regular and modal
+-- | Convert an t'Exhibit' to a regular list of regular and modal
 -- components.
 exhibitToList :: Exhibit a -> [a]
 exhibitToList (Exhibit mnorm modals) =
@@ -61,7 +61,7 @@
 -- significantly easier to read.
 --
 -- NOTE: Decomposed subparsers are intended for display purposes
--- (hence the 'Exhibit' type). Trying to parse input with them is
+-- (hence the t'Exhibit' type). Trying to parse input with them is
 -- likely to fail.
 class Functor s => Separable (s :: Type -> Type) where
   separate :: s r -> Exhibit (s r)
diff --git a/src/Mangrove/TextParser.hs b/src/Mangrove/TextParser.hs
--- a/src/Mangrove/TextParser.hs
+++ b/src/Mangrove/TextParser.hs
@@ -21,6 +21,7 @@
   ) where
 
 import           Control.Monad.Except
+import           Data.Bifunctor
 import           Data.Text              (Text)
 import qualified Data.Text              as T
 import qualified Data.Text.Lazy.Builder as TLB
@@ -28,31 +29,31 @@
 
 import           Mangrove.Text
 
--- | A 'TextParser' is the most atomic client-defined parsing unit. It
+-- | A @TextParser@ is the most basic client-defined parsing unit. It
 -- parses textual data that is not otherwise part of the parsing
 -- scheme into the actual results that will be combined and returned
 -- once parsing completes.
 data TextParser r = TextParser
-  { parserHint :: Text -- ^ A hint about the type of input this parser expects
-  , parserRun  :: Text -> Either Builder r -- ^ An actual parsing function
+  { parserHint :: !Text -- ^ A hint about the type of input this parser expects
+  , parserRun  :: Text -> Either Text r -- ^ An actual parsing function
   } deriving (Functor)
 
--- | Lift a 'TextParser' into some 'MonadError'.
+-- | A more general function for running t'TextParser's.
 runTextParser :: MonadError Builder m => TextParser r -> Text -> m r
-runTextParser tp = liftEither . parserRun tp
+runTextParser tp = liftEither . first TLB.fromText . parserRun tp
 
 -- | A typeclass for types that have a convenient default
--- 'TextParser'.
+-- t'TextParser' implementation.
 class DefaultParser r where
   -- | A reasonable default TextParser implementation.
   defaultParser :: TextParser r
 
-exactly :: TR.Reader a -> Text -> Either Builder a
+exactly :: TR.Reader a -> Text -> Either Text a
 exactly reader text =
   case reader text of
-    Left err            -> throwError $ TLB.fromString err
+    Left err            -> throwError $ T.pack err
     Right (result, "")  -> pure result
-    Right (_, leftover) -> throwError $ "unexpected input: " <> render leftover
+    Right (_, leftover) -> throwError $ "unexpected input: " <> leftover
 
 instance DefaultParser Bool where
   defaultParser = TextParser
diff --git a/src/Mangrove/Unix.hs b/src/Mangrove/Unix.hs
--- a/src/Mangrove/Unix.hs
+++ b/src/Mangrove/Unix.hs
@@ -45,7 +45,7 @@
 --------------------------------------------------------------------------------
 -- Tree-building Combinators
 
--- | Create a parameter parser from a 'TextParser'.
+-- | Create a parameter parser from a t'TextParser'.
 parameter
   :: TextParser r
   -> UnixParser r
diff --git a/test/Mangrove/ParserSpec.hs b/test/Mangrove/ParserSpec.hs
--- a/test/Mangrove/ParserSpec.hs
+++ b/test/Mangrove/ParserSpec.hs
@@ -174,6 +174,6 @@
       let (finalState, result) = runStreamParser' pop (initState_singleton @UnixScheme)
       it "gets the first item without replacement" $ do
         result `shouldBe` SSuccess "asdf"
-        streamContent finalState `shouldBe` tail (streamContent initState_singleton)
+        streamContent finalState `shouldBe` drop 1 (streamContent initState_singleton)
       it "preserves the context" $ do
         streamContext initState_singleton `shouldBe` streamContext finalState
