diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,11 @@
+# 0.2.0 (2016-09-18)
+
+## Enhancements
+
+- Allow use in multi-package project (f545a4c)
+- Handle exceptions (ec640bb)
+- Replace HTTP with http-conduit (f6735cb)
+- Add command line arguments (2558a05)
+- Add a library (835ac70)
+
+# 0.1.0 (2016-08-13)
diff --git a/Main.hs b/Main.hs
--- a/Main.hs
+++ b/Main.hs
@@ -1,63 +1,69 @@
-{-# LANGUAGE GeneralizedNewtypeDeriving #-}
-{-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE DeriveDataTypeable #-}
 {-# LANGUAGE RecordWildCards #-}
 
+----------------------------------------------------------------------
+-- |
+-- Module: Main
+-- Description:
+--
+--
+--
+----------------------------------------------------------------------
+
 module Main
   ( main
   )
   where
 
+-- licensor
+import Licensor
+
 -- base
 import Control.Monad
 import Data.List
 import Data.Monoid ((<>))
+import qualified Data.Version as Version
+import System.Environment
 import qualified System.Exit as Exit
-import System.IO
 
 -- Cabal
-import Distribution.License
-import Distribution.Package
 import Distribution.PackageDescription
-import Distribution.PackageDescription.Parse
-import Distribution.Simple.Utils
 import Distribution.Text
-import Distribution.Verbosity
 
+-- cmdargs
+import System.Console.CmdArgs
+
 -- containers
-import Data.Map.Strict (Map)
 import qualified Data.Map.Strict as Map
-import Data.Set (Set)
 import qualified Data.Set as Set
 
 -- directory
-import System.Directory
-
--- HTTP
-import Network.HTTP
-  ( getRequest
-  , getResponseBody
-  , simpleHTTP
-  )
-
--- process
-import System.Process
+import System.Directory (doesFileExist)
 
 
 -- |
 --
 --
 
-newtype License' = License' { _getLicense :: License }
-  deriving (Eq, Read, Show, Text)
+data LiArgs =
+  LiArgs
+    {
+    }
+  deriving (Data)
 
 
 -- |
 --
 --
 
-instance Ord License' where
-  compare =
-    comparing display
+liArgs :: String -> Mode (CmdArgs LiArgs)
+liArgs s =
+  cmdArgsMode $
+    LiArgs
+      {
+      }
+  &= program s
+  &= summary (unwords ["licensor", Version.showVersion version])
 
 
 -- |
@@ -66,12 +72,20 @@
 
 main :: IO ()
 main = do
+  LiArgs <- cmdArgsRun . liArgs =<< getProgName
+
   maybePackage <- getPackage
 
   pid <-
     case maybePackage of
-      Nothing ->
-        Exit.die "Error: No Cabal file found."
+      Nothing -> do
+        stack <- doesFileExist "stack.yaml"
+        if stack
+          then do
+            putStrLn "Found stack.yaml..."
+            return Nothing
+          else
+            Exit.die "Error: No Cabal file found."
 
       Just PackageDescription{..} -> do
         putStrLn $
@@ -81,7 +95,7 @@
             <> "License: "
             <> display license
             <> ")"
-        return package
+        return (Just package)
 
   maybeDependencies <- getDependencies
 
@@ -90,9 +104,11 @@
       Exit.die "Error: ..."
 
     Just dependencies -> do
-      dependenciesByLicense <-
-        fmap (Set.map display) <$> orderPackagesByLicense pid dependencies
+      (dependenciesByLicense', failed) <-
+        orderPackagesByLicense pid dependencies
 
+      let dependenciesByLicense = fmap (Set.map display) dependenciesByLicense'
+
       forM_ (Map.keys dependenciesByLicense) $
         \license ->
           let
@@ -107,82 +123,6 @@
                 <> ": "
                 <> intercalate ", " (Set.toList n)
 
-
--- |
---
---
-
-getPackage :: IO (Maybe PackageDescription)
-getPackage = do
-  currentDirectory <- getCurrentDirectory
-  fmap getPackageDescription <$> findPackageDesc currentDirectory
-    >>= either (const (return Nothing)) (fmap Just)
-
-
--- |
---
---
-
-getPackageDescription :: FilePath -> IO PackageDescription
-getPackageDescription =
-  fmap packageDescription . readPackageDescription silent
-
-
--- |
---
---
-
-getDependencies :: IO (Maybe (Set PackageIdentifier))
-getDependencies =
-  fmap Set.fromList . sequence . fmap simpleParse . lines
-    <$> readProcess "stack" ["list-dependencies", "--separator", "-"] ""
-
-
--- |
---
---
-
-getPackageLicense :: PackageIdentifier -> IO License'
-getPackageLicense p@PackageIdentifier{..} = do
-  let
-    url =
-      "http://hackage.haskell.org/package/"
-        <> display p
-        <> "/"
-        <> unPackageName pkgName
-        <> ".cabal"
-  pd <- simpleHTTP (getRequest url) >>= getResponseBody
-  (file, handle) <- openTempFile "/tmp" "licensor"
-  hClose handle
-  writeFile file pd
-  PackageDescription{license} <- getPackageDescription file
-  hClose handle
-  removeFile file
-  return (License' license)
-
-
--- |
---
---
-
-orderPackagesByLicense
-  :: PackageIdentifier
-  -> Set PackageIdentifier
-  -> IO (Map License' (Set PackageIdentifier))
-orderPackagesByLicense p =
-  let
-    insertPackage package orderedPackages' = do
-      license <- getPackageLicense package
-      orderedPackages <- orderedPackages'
-      return $
-        if p == package
-          then
-            orderedPackages
-          else
-            Map.insertWith
-              Set.union
-              license
-              (Set.singleton package)
-              orderedPackages
-  in
-    foldr insertPackage (pure mempty)
+      unless (null failed) $ do
+        putStr "Failed: "
+        print failed
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,1 +1,176 @@
-# licensor
+# The not so great automatic Haskell licensor
+
+[![][1]][0]
+
+[0]: https://circleci.com/gh/jpvillaisaza/licensor
+[1]: https://circleci.com/gh/jpvillaisaza/licensor.svg?style=svg
+
+![][2]
+![][3]
+
+[2]: https://www.stackage.org/package/licensor/badge/lts
+[3]: https://www.stackage.org/package/licensor/badge/nightly
+
+Licensor is a program that generates a report of the dependencies and
+transitive dependencies of a Haskell project and their licenses.
+
+## Description
+
+Choosing a license for a software project or determining whether a
+particular dependency can be added to a project can be projects
+themselves. Unless starting from scratch, programmers should consider
+the licenses of the dependencies and transitive dependencies of their
+projects to make informed decisions and avoid license compatibility
+issues.
+
+Of course, this is just a starting point. "Beyond (...) general
+observations, it is difficult, if not impossible, to provide precise
+guidance about what licenses may or may not be compatible with each
+other. (...) Programmers who are considering combining code governed
+by two or more different licenses should proceed cautiously" (Andrew
+M. St. Laurent).
+
+## Disclaimer
+
+Licensor is not a lawyer and does not provide legal advice.
+
+For more information about licenses and license compatibility issues,
+read the text of the licenses or consult with a lawyer before making
+any decision.
+
+## Related programs
+
+Licensor is not the only license compatibility helper for Haskell:
+
+- Licensor uses a Cabal library and Stack program approach for
+  detecting licenses and listing dependencies, respectively. For a
+  Cabal library and program approach, consider using
+  the [cabal-dependency-licenses][rp-01] program.
+
+[rp-01]: https://hackage.haskell.org/package/cabal-dependency-licenses
+
+## Installation and usage
+
+To install Licensor, use Cabal:
+
+```
+$ cabal update && cabal install licensor
+```
+
+Then, run the `licensor` executable inside a Haskell project:
+
+```
+$ licensor
+```
+
+To see the license report for Licensor, clone the repository:
+
+```
+$ git clone https://github.com/jpvillaisaza/licensor
+```
+
+And run `licensor` inside the project:
+
+```
+$ cd licensor/ && licensor
+```
+
+Or build and run `licensor` inside the project:
+
+```
+$ cd licensor/ && stack build --exec licensor
+```
+
+For more information, run `licensor --help`:
+
+```
+licensor 0.2.0
+
+licensor [OPTIONS]
+
+Common flags:
+  -? --help             Display help message
+  -V --version          Print version information
+     --numeric-version  Print just the version number
+```
+
+## Notes
+
+### Dependencies
+
+Licensor uses the Stack program to list dependencies for a Haskell
+project. A future enhancement could be to use the Stack library.
+
+### Licenses and license detection
+
+Licensor uses the Cabal library to detect the license of a Haskell
+project and its dependencies (including transitive dependencies). To
+do so, it uses the license field in the package description. A future
+enhancement could be to use both the license and licence file fields
+in the package description.
+
+Cabal provides an enumeration of common open source and free software
+licenses. These are the licenses that appear in the reports generated
+by Licensor:
+
+License                   | Description
+------------------------- | -------------------------
+GPL                       | GNU General Public License
+AGPL                      | GNU Affero General Public License
+LGPL                      | GNU Lesser General Public License
+BSD2                      | BSD 2-Clause License
+BSD3                      | BSD 3-Clause License
+BSD4                      | BSD 4-Clause License
+MIT                       | MIT License
+ISC                       | ISC License
+MPL                       | Mozilla Public License
+Apache                    | Apache License
+PublicDomain              | Public domain
+AllRightsReserved         | All rights reserved
+UnspecifiedLicense        | Unspecified license (All rights reserved)
+OtherLicense              | Other license
+UnknownLicense            | Unknown license
+
+## Contribution guidelines
+
+Feel free to create issues for reporting bugs and suggesting
+enhancements, or to fork the repository and open a pull request.
+
+## License
+
+Licensor is licensed under the MIT License.
+See [LICENSE.md](LICENSE.md).
+
+### License report
+
+Licensor (0.2.0) depends on the following libraries:
+
+Library                   | License
+------------------------- | -------------------------
+base                      | BSD3
+bytestring                | BSD3
+Cabal                     | BSD3
+cmdargs                   | BSD3
+containers                | BSD3
+directory                 | BSD3
+http-conduit              | BSD3
+process                   | BSD3
+
+And the following licenses (including transitive dependencies):
+
+License                   | Number of libraries
+------------------------- | -------------------------
+BSD3                      | 68
+MIT                       | 7
+
+(Tested with Licensor 0.2.0, Stack 1.2.0, and LTS 7.0.)
+
+## Additional resources
+
+- [Choose a License](http://choosealicense.com/)
+- [License compatibility][ar-01]
+- [Understanding open source and free software licensing][ar-02]
+  (Andrew M. St. Laurent)
+
+[ar-01]: https://en.wikipedia.org/wiki/License_compatibility
+[ar-02]: http://www.oreilly.com/openbook/osfreesoft/book/
diff --git a/licensor.cabal b/licensor.cabal
--- a/licensor.cabal
+++ b/licensor.cabal
@@ -1,33 +1,67 @@
-name:                licensor
-version:             0.1.0
-synopsis:            A license compatibility helper
-description:         A license compatibility helper.
-homepage:            https://github.com/jpvillaisaza/licensor
-bug-reports:         https://github.com/jpvillaisaza/licensor/issues
-license:             MIT
-license-file:        LICENSE.md
-author:              Juan Pedro Villa Isaza <jpvillaisaza@gmail.com>
-maintainer:          Juan Pedro Villa Isaza <jpvillaisaza@gmail.com>
-copyright:           2016 Juan Pedro Villa Isaza
-category:            Distribution
-extra-source-files:  README.md
-build-type:          Simple
-cabal-version:       >= 1.10
+name: licensor
+version: 0.2.0
 
+build-type: Simple
+cabal-version: >= 1.21
+
+license: MIT
+license-file: LICENSE.md
+
+copyright: 2016 Juan Pedro Villa Isaza
+author: Juan Pedro Villa Isaza <jpvillaisaza@gmail.com>
+maintainer: Juan Pedro Villa Isaza <jpvillaisaza@gmail.com>
+
+stability: Experimental
+
+homepage: https://github.com/jpvillaisaza/licensor
+bug-reports: https://github.com/jpvillaisaza/licensor/issues
+
+synopsis: A license compatibility helper
+description: A license compatibility helper.
+
+category: Distribution
+
+tested-with: GHC == 7.10.3, GHC == 8.0.1
+
+extra-source-files: CHANGELOG.md, README.md
+
+
+library
+  hs-source-dirs:
+      src
+  exposed-modules:
+      Licensor
+  other-modules:
+      Paths_licensor
+  build-depends:
+      base >= 4.8 && < 4.10
+    , bytestring
+    , Cabal >= 1.22 && < 1.25
+    , containers
+    , directory
+    , http-conduit >= 2.1 && < 2.3
+    , process
+  default-language:
+      Haskell2010
+  ghc-options:
+      -Wall
+
+
 executable licensor
   main-is:
       Main.hs
   build-depends:
       base >= 4.8 && < 5.0
     , Cabal >= 1.22 && < 1.25
+    , cmdargs >= 0.10 && < 0.11
     , containers
     , directory
-    , HTTP >= 4000.3 && < 4000.4
-    , process
+    , licensor
   default-language:
       Haskell2010
   ghc-options:
       -Wall -threaded -rtsopts -with-rtsopts=-N
+
 
 source-repository head
   type: git
diff --git a/src/Licensor.hs b/src/Licensor.hs
new file mode 100644
--- /dev/null
+++ b/src/Licensor.hs
@@ -0,0 +1,210 @@
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+----------------------------------------------------------------------
+-- |
+-- Module: Licensor
+-- Description:
+--
+--
+--
+----------------------------------------------------------------------
+
+module Licensor
+  ( LiLicense(..)
+  , LiPackage(..)
+  , getDependencies
+  , getPackage
+  , orderPackagesByLicense
+  , version
+  )
+  where
+
+-- base
+import qualified Control.Exception as Exception
+import Data.Monoid ((<>))
+import Data.Version (Version)
+import System.IO
+
+-- bytestring
+import qualified Data.ByteString.Lazy as ByteString
+
+-- Cabal
+import Distribution.License
+import Distribution.Package
+import Distribution.PackageDescription
+import Distribution.PackageDescription.Parse
+import Distribution.Simple.Utils
+import Distribution.Text
+import Distribution.Verbosity
+
+-- containers
+import Data.Map.Strict (Map)
+import qualified Data.Map.Strict as Map
+import Data.Set (Set)
+import qualified Data.Set as Set
+
+-- directory
+import System.Directory
+
+-- http-conduit
+--import Network.HTTP.Client.Conduit
+import Network.HTTP.Simple
+
+-- licensor
+import qualified Paths_licensor
+
+-- process
+import System.Process
+
+
+-- |
+--
+--
+
+newtype LiLicense = LiLicense { getLicense :: License }
+  deriving (Eq, Read, Show, Text)
+
+
+-- |
+--
+--
+
+instance Ord LiLicense where
+  compare =
+    comparing display
+
+
+-- |
+--
+--
+
+data LiPackage =
+  LiPackage
+    { liPackageId :: PackageIdentifier
+    , liPackageDependencies :: Set LiPackage
+    , liPackageLicense :: License
+    }
+
+
+-- |
+--
+--
+
+getPackage :: IO (Maybe PackageDescription)
+getPackage = do
+  currentDirectory <- getCurrentDirectory
+  fmap getPackageDescription <$> findPackageDesc currentDirectory
+    >>= either (const (return Nothing)) (fmap Just)
+
+
+-- |
+--
+--
+
+getPackageDescription :: FilePath -> IO PackageDescription
+getPackageDescription =
+  fmap packageDescription . readPackageDescription silent
+
+
+-- |
+--
+--
+
+getDependencies :: IO (Maybe (Set PackageIdentifier))
+getDependencies = do
+  eitherDeps <-
+    Exception.try $ readProcess "stack" ["list-dependencies", "--separator", "-"] ""
+
+  case eitherDeps of
+    Left (_ :: IOError) ->
+      return Nothing
+
+    Right deps ->
+      return $ fmap Set.fromList $ sequence $ fmap simpleParse (lines deps)
+
+
+-- |
+--
+--
+
+getPackageLicense :: PackageIdentifier -> IO (Maybe LiLicense)
+getPackageLicense p@PackageIdentifier{..} = do
+  putStr $ display p ++ "..."
+  let
+    url =
+      "GET https://hackage.haskell.org/package/"
+        <> display p
+        <> "/"
+        <> unPackageName pkgName
+        <> ".cabal"
+
+  req <- parseRequest url
+  eitherPd <- Exception.try $ fmap getResponseBody (httpLBS req)
+
+  case eitherPd of
+    Left (_ :: HttpException) ->
+      return Nothing
+
+    Right pd -> do
+
+      (file, handle) <- openTempFile "/tmp" "licensor"
+      hClose handle
+      ByteString.writeFile file pd
+      PackageDescription{license} <- getPackageDescription file
+      hClose handle
+      removeFile file
+
+      putStrLn $ display license
+
+      return $ Just (LiLicense license)
+
+
+-- |
+--
+--
+
+orderPackagesByLicense
+  :: Maybe PackageIdentifier
+  -> Set PackageIdentifier
+  -> IO (Map LiLicense (Set PackageIdentifier), Set PackageIdentifier)
+orderPackagesByLicense maybeP =
+  let
+    cond =
+      maybe (const False) (==) maybeP
+
+    insertPackage package orderedPackages' = do
+      maybeLicense <- getPackageLicense package
+
+      (orderedPackages, failed) <- orderedPackages'
+      return $
+        if cond package
+          then
+            (orderedPackages, failed)
+          else
+            case maybeLicense of
+              Nothing ->
+                ( orderedPackages, Set.insert package failed
+                )
+
+              Just license ->
+                ( Map.insertWith
+                    Set.union
+                    license
+                    (Set.singleton package)
+                    orderedPackages
+                , failed
+                )
+  in
+    foldr insertPackage (pure (mempty, mempty))
+
+
+-- |
+--
+--
+
+version :: Version
+version =
+  Paths_licensor.version
