diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2018, Peter Simons
+Copyright (c) 2018 Peter Simons of SUSE Linux GmbH.
 
 All rights reserved.
 
@@ -13,9 +13,10 @@
       disclaimer in the documentation and/or other materials provided
       with the distribution.
 
-    * Neither the name of Peter Simons nor the names of other
-      contributors may be used to endorse or promote products derived
-      from this software without specific prior written permission.
+    * Neither the name of Peter Simons, SUSE Linux GmbH, nor the names
+      of other contributors may be used to endorse or promote products
+      derived from this software without specific prior written
+      permission.
 
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
diff --git a/README.md b/README.md
deleted file mode 100644
--- a/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-distribution-opensuse
-=====================
-
-[![hackage release](https://img.shields.io/hackage/v/distribution-opensuse.svg?label=hackage)](http://hackage.haskell.org/package/distribution-opensuse)
-[![stackage LTS package](http://stackage.org/package/distribution-opensuse/badge/lts)](http://stackage.org/lts/package/distribution-opensuse)
-[![stackage Nightly package](http://stackage.org/package/distribution-opensuse/badge/nightly)](http://stackage.org/nightly/package/distribution-opensuse)
-[![travis build status](https://img.shields.io/travis/peti/distribution-opensuse/master.svg?label=travis+build)](https://travis-ci.org/peti/distribution-opensuse)
-
-Types, functions, and tools to manipulate the openSUSE distribution.
diff --git a/distribution-opensuse.cabal b/distribution-opensuse.cabal
--- a/distribution-opensuse.cabal
+++ b/distribution-opensuse.cabal
@@ -1,7 +1,9 @@
 name:               distribution-opensuse
-version:            1.1.0
+version:            1.1.1
 synopsis:           Types, functions, and tools to manipulate the openSUSE distribution
-description:        Types, functions, and tools to manipulate the openSUSE distribution.
+description:        This library is a loose collection of types, functions, and tools that
+                    users and developers of the
+                    <https://opensuse.org/ openSUSE Linux distribution> might find useful.
 license:            BSD3
 license-file:       LICENSE
 author:             Peter Simons
@@ -9,8 +11,9 @@
 tested-with:        GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.3
 category:           Distribution
 homepage:           https://github.com/peti/distribution-opensuse/
+bug-reports:        https://github.com/peti/distribution-opensuse/issues
 build-type:         Simple
-extra-source-files: README.md
+extra-source-files: guess-changelog.md
                     tests/run-tests
                     tests/guess-changelog/*.test
 cabal-version:      >= 1.10
diff --git a/guess-changelog.md b/guess-changelog.md
new file mode 100644
--- /dev/null
+++ b/guess-changelog.md
@@ -0,0 +1,77 @@
+% GUESS-CHANGELOG(1) Guess change descriptions between releases
+
+# NAME
+
+guess-changelog -- Extract additions to change log file between releases
+
+# SYNOPSIS
+
+**guess-changelog** OLD-DIR NEW-DIR
+
+# DESCRIPTION
+
+Many free software authors include a (manually maintained) change log file in
+their release tarballs that describes important changes from one version to the
+next, and it's good practice for distribution packagers to include that
+information in meta sections of their packaging efforts so that the package
+managing software can easily display it to users during updates, etc. In the
+rpm(8) world, this is usually accomplished by adding a `pkg-name.changes` file
+next to the `pkg-name.spec` file that mentions relevant bits of the upstream
+change log.
+
+Now, this tools makes tries to extract the necessary information from upstream
+releases automatically. Given to release tarballs `foo-X.tar.gz` and
+`foo-Y.tar.gz`, just extract those tarballs and run `guess-changelog` with the
+appropriate directories as arguments:
+
+    $ guess-changelog foo-X foo-Y
+
+If `guess-changelog` can determine the part of the change log that was added
+between the two releases, it will write the text to standard output. On some
+occasions, however, `guess-changelog` will fail:
+
+* Neither release contains a change log file.
+
+* A change log file exists, but it's identical in both releases. In other
+  words, upstream probably forgot to document the release.
+
+* Both releases contain a set of files that look like they might be a change
+  log, but their intersection is empty! This happens, for example, when
+  upstream has renamed the file.
+
+* Multiple change log files exists in both directories. Now, it would probably
+  work out okay if we'd just look at the diffs of both of them, respectively,
+  but it felt like a good idea to err on the side of caution. This case is rare
+  anyways.
+
+* `guess-changelog` accepts up to 10 lines of unmodified text at the top of the
+  upstream change log file because some people like to have a short
+  introduction text there etc. If that header becomes too large, however, an
+  error is returned because we expect upstream to add text at the *top*, not in
+  the middle of the file.
+
+* Upstream has edited the file in some non-trivial way other than just adding
+  at the top. Sometimes people re-format old entries or rewrite URLs or fix
+  typos, and in such a case it feels to risky to trust the diff.
+
+# RETURN VALUES
+
+`guess-changelog` returns a non-zero exit code only if some kind of
+system-level error ocurred, such as a permission error while trying to access
+the given directories. In all other cases, the tool exists with 0.
+
+If a change log entry was detected successfully, it will be written to standard
+output. In no change log entry could be detected, the tool writes a brief
+explanation of the issue to the standard error stream, but it won't write to
+standard output.
+
+# AUTHOR
+
+ShellCheck is written and maintained by Peter Simons. Please report any bugs
+you may find at <https://github.com/peti/distribution-opensuse/>.
+
+# COPYRIGHT
+
+Copyright 2018 by Peter Simons of SUSE Linux GmbH.
+
+Licensed under the terms of the [BSD-3-Clause license](https://opensource.org/licenses/BSD-3-Clause).
diff --git a/src/OpenSuse/GuessChangeLog.hs b/src/OpenSuse/GuessChangeLog.hs
--- a/src/OpenSuse/GuessChangeLog.hs
+++ b/src/OpenSuse/GuessChangeLog.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE ApplicativeDo #-}
 {-# LANGUAGE OverloadedStrings #-}
 
 module OpenSuse.GuessChangeLog ( guessChangeLog, GuessedChangeLog(..) ) where
@@ -12,8 +11,27 @@
 import qualified Data.Set as Set
 import qualified Data.Text as Text
 import Prelude hiding ( FilePath )
-import Turtle hiding ( l, x )
+import Turtle hiding ( l, x, stderr, stdout )
 
+-- | Automatically guess the differences between to releases of a package by
+-- looking at the change log file provided by upstream. The function as
+-- arguments the paths of two directories that contain the extracted release
+-- tarballs. The first arguments ought to point to the older release, the
+-- second paths ought to point to the updated version.
+--
+-- The function uses the following algorithm to detect the relevant changes:
+--
+--   1. Scan both directories for files that look like they might be change
+--      logs.
+--
+--   2. If both directories contain the same candidate file, e.g. @ChangeLog@,
+--      then use that.
+--
+--   3. Compute the differences between the change log files and check that all
+--      modifications are additions at the top of the file.
+--
+--   4. Return those additions as 'Text'.
+
 guessChangeLog :: FilePath -> FilePath -> IO GuessedChangeLog
 guessChangeLog oldDir = fmap (either id id) . guessChangeLog' oldDir
 
@@ -38,13 +56,41 @@
   unless topAddOnly (throwError (NotJustTopAdditions clf))
   return (GuessedChangeLog clf (stripSpace (Text.unlines (map unDiff add))))
 
-data GuessedChangeLog = GuessedChangeLog FilePath Text
-                      | NoChangeLogFiles
-                      | UndocumentedUpdate FilePath
-                      | NoCommonChangeLogFiles (Set FilePath) (Set FilePath)
-                      | MoreThanOneChangeLogFile (Set FilePath)
-                      | UnmodifiedTopIsTooLarge FilePath Word
-                      | NotJustTopAdditions FilePath
+--
+
+data GuessedChangeLog
+    = GuessedChangeLog FilePath Text
+        -- ^ Both releases contained the given change log file, and these files
+        -- differed so that the given text was added at the top of the new one.
+        -- The text undergoes some amount of cleanup, i.e. we'll trim leading
+        -- empty lines at the top, trailing whitespace, and trailing empty
+        -- lines at the end.
+    | NoChangeLogFiles
+        -- ^ Neither release contains a change log file.
+    | UndocumentedUpdate FilePath
+        -- ^ A change log file exists (and its name is returned), but it's
+        -- identical in both releases. In other words, upstream probably forgot
+        -- to document the release.
+    | NoCommonChangeLogFiles (Set FilePath) (Set FilePath)
+        -- ^ Both releases contain a set of files that look like they might be
+        -- a change log, but their intersection is empty! This happens, for
+        -- example, when upstream has renamed the file.
+    | MoreThanOneChangeLogFile (Set FilePath)
+        -- ^ Multiple change log files exists in both directories. Now, it
+        -- would probably work out okay if we'd just look at the diffs of both
+        -- of them, respectively, but it felt like a good idea to err on the
+        -- side of caution. This case is rare anyways.
+    | UnmodifiedTopIsTooLarge FilePath Word
+        -- ^ 'guessChangelog' accepts up to 10 lines of unmodified text at the
+        -- top of the upstream change log file because some people like to have
+        -- a short introduction text there etc. If that header becomes too
+        -- large, however, then we return this error because we expect upstream
+        -- to add text at the top, not in the middle of the file.
+    | NotJustTopAdditions FilePath
+        -- ^ This happens when upstream edits the file in ways other than just
+        -- adding at the top. Sometimes people re-format old entries or rewrite
+        -- URLs or fix typos, and in such a case it feels to risky to trust the
+        -- diff.
   deriving (Show)
 
 cleanupEmptyLines :: [Diff Text] -> [Diff Text]
diff --git a/src/OpenSuse/StripSpace.hs b/src/OpenSuse/StripSpace.hs
--- a/src/OpenSuse/StripSpace.hs
+++ b/src/OpenSuse/StripSpace.hs
@@ -16,9 +16,9 @@
 --
 -- * Consecutive empty lines between paragraphs are collapsed into one.
 --
--- * @\r\n@ line endings are normalized into @\n@.
+-- * @\\r\\n@ line endings are normalized into @\\n@.
 --
--- * If the buffer is not empty, then its last line is terminated by @\n@.
+-- * If the buffer is not empty, then its last line is terminated by @\\n@.
 --
 -- * If the buffer is empty (i.e. it contains only white space), then it comes
 --   out as the empty string.
