diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+# 0.4.0 (2020-02-16)
+
+## Enhancements
+
+- Use hpack
+
 # 0.3.0 (2019-02-05)
 
 ## Enhancements
diff --git a/Main.hs b/Main.hs
deleted file mode 100644
--- a/Main.hs
+++ /dev/null
@@ -1,132 +0,0 @@
-{-# 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
-
--- Cabal
-import Distribution.PackageDescription
-import Distribution.Text
-
--- cmdargs
-import System.Console.CmdArgs
-
--- containers
-import qualified Data.Map.Strict as Map
-import qualified Data.Set as Set
-
--- directory
-import System.Directory (doesFileExist)
-
-
--- |
---
---
-
-data LiArgs =
-  LiArgs
-    {
-    }
-  deriving (Data)
-
-
--- |
---
---
-
-liArgs :: String -> Mode (CmdArgs LiArgs)
-liArgs s =
-  cmdArgsMode $
-    LiArgs
-      {
-      }
-  &= program s
-  &= summary (unwords ["licensor", Version.showVersion version])
-  &= verbosity
-
-
--- |
---
---
-
-main :: IO ()
-main = do
-  LiArgs <- cmdArgsRun . liArgs =<< getProgName
-
-  quiet <- fmap not isNormal
-
-  maybePackage <- getPackage
-
-  pid <-
-    case maybePackage of
-      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 $
-          "Package: "
-            <> display package
-            <> " ("
-            <> "License: "
-            <> display license
-            <> ")"
-        return (Just package)
-
-  maybeDependencies <- getDependencies
-  maybeLicenses <- getLicenses
-
-  case maybeDependencies of
-    Nothing ->
-      Exit.die "Error: ..."
-
-    Just dependencies -> do
-      (dependenciesByLicense', failed) <-
-        orderPackagesByLicense quiet pid maybeLicenses dependencies
-
-      let dependenciesByLicense = fmap (Set.map display) dependenciesByLicense'
-
-      forM_ (Map.keys dependenciesByLicense) $
-        \license ->
-          let
-            n = dependenciesByLicense Map.! license
-          in do
-            putStrLn "-----"
-            putStrLn $
-              show (Set.size n)
-                <> (if Set.size n == 1 then " package " else " packages ")
-                <> "licensed under "
-                <> display license
-                <> ": "
-                <> intercalate ", " (Set.toList n)
-
-      unless (null failed) $ do
-        putStr "Failed: "
-        print failed
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,10 +1,5 @@
 # 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=shield
-
 [![][2]](https://www.stackage.org/lts/package/licensor)
 [![][3]](https://www.stackage.org/nightly/package/licensor)
 
@@ -84,7 +79,7 @@
 For more information, run `licensor --help`:
 
 ```
-licensor 0.2.0
+licensor 0.4.0
 
 licensor [OPTIONS]
 
@@ -92,6 +87,8 @@
   -? --help             Display help message
   -V --version          Print version information
      --numeric-version  Print just the version number
+  -v --verbose          Loud verbosity
+  -q --quiet            Quiet verbosity
 ```
 
 ## Notes
@@ -143,30 +140,24 @@
 
 ### License report
 
-Licensor (0.2.2) depends on the following libraries:
+Licensor (0.4.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
 ------------------------- | -------------------------
-BSD2                      | 1
-BSD3                      | 70
-ISC                       | 1
-MIT                       | 11
-UnspecifiedLicense        | 1
+BSD3                      | 20
 
-(Tested with Licensor 0.2.2, Stack 1.6.3, and Stackage Nightly 2018-01-16.)
+(Tested with Licensor 0.4.0, Stack 2.1.3, and LTS Haskell 11.11.)
 
 ## Additional resources
 
diff --git a/Setup.hs b/Setup.hs
deleted file mode 100644
--- a/Setup.hs
+++ /dev/null
@@ -1,11 +0,0 @@
-module Main
-  ( main
-  )
-  where
-
-import Distribution.Simple (defaultMain)
-
-
-main :: IO ()
-main =
-  defaultMain
diff --git a/app/Main.hs b/app/Main.hs
new file mode 100644
--- /dev/null
+++ b/app/Main.hs
@@ -0,0 +1,131 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE NamedFieldPuns #-}
+
+----------------------------------------------------------------------
+-- |
+-- 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
+
+-- Cabal
+import Distribution.PackageDescription
+import Distribution.Text
+
+-- cmdargs
+import System.Console.CmdArgs
+
+-- containers
+import qualified Data.Map.Strict as Map
+import qualified Data.Set as Set
+
+-- directory
+import System.Directory (doesFileExist)
+
+
+-- |
+--
+--
+
+data LiArgs =
+  LiArgs
+    {
+    }
+  deriving (Data)
+
+
+-- |
+--
+--
+
+liArgs :: String -> Mode (CmdArgs LiArgs)
+liArgs s =
+  cmdArgsMode $
+    LiArgs
+      {
+      }
+  &= program s
+  &= summary (unwords ["licensor", Version.showVersion version])
+  &= verbosity
+
+
+-- |
+--
+--
+
+main :: IO ()
+main = do
+  LiArgs <- cmdArgsRun . liArgs =<< getProgName
+
+  quiet <- fmap not isNormal
+
+  maybePackage <- getPackage
+
+  pid <-
+    case maybePackage of
+      Nothing -> do
+        stack <- doesFileExist "stack.yaml"
+        if stack
+          then do
+            putStrLn "Found stack.yaml..."
+            pure Nothing
+          else
+            Exit.die "Error: No Cabal file found."
+
+      Just PackageDescription { license, package } -> do
+        putStrLn $
+          "Package: "
+            <> display package
+            <> " ("
+            <> "License: "
+            <> display license
+            <> ")"
+        pure (Just package)
+
+  maybeDependencies <- getDependencies
+  maybeLicenses <- getLicenses
+
+  case (maybeDependencies, maybeLicenses) of
+    (Just dependencies, Just licenses) -> do
+      (dependenciesByLicense', failed) <-
+        orderPackagesByLicense quiet pid licenses dependencies
+
+      let dependenciesByLicense = fmap (Set.map display) dependenciesByLicense'
+
+      forM_ (Map.keys dependenciesByLicense) $
+        \license ->
+          let
+            n = dependenciesByLicense Map.! license
+          in do
+            putStrLn "-----"
+            putStrLn $
+              show (Set.size n)
+                <> (if Set.size n == 1 then " package " else " packages ")
+                <> "licensed under "
+                <> display license
+                <> ": "
+                <> intercalate ", " (Set.toList n)
+
+      unless (null failed) $ do
+        putStr "Failed: "
+        print failed
+    _ ->
+      Exit.die "Error: ..."
diff --git a/licensor.cabal b/licensor.cabal
--- a/licensor.cabal
+++ b/licensor.cabal
@@ -1,68 +1,61 @@
-name: licensor
-version: 0.3.0
-
-build-type: Simple
-cabal-version: >= 1.10
-
-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
+cabal-version: 1.12
 
-tested-with: GHC == 7.10.3, GHC == 8.0.1, GHC == 8.0.2, GHC == 8.2.1, GHC == 8.2.2
+-- This file has been generated from package.yaml by hpack version 0.31.2.
+--
+-- see: https://github.com/sol/hpack
+--
+-- hash: b5e0234d196e96476a6a70c11798ae1dd4fd24ca9ce1c11ea74d6b3422604fc8
 
-extra-source-files: CHANGELOG.md, README.md
+name:           licensor
+version:        0.4.0
+synopsis:       A license compatibility helper
+description:    A license compatibility helper.
+category:       Distribution
+stability:      Experimental
+homepage:       https://jpvillaisaza.co/licensor
+bug-reports:    https://github.com/jpvillaisaza/licensor/issues
+author:         Juan Pedro Villa Isaza <jpvillaisaza@gmail.com>
+maintainer:     Juan Pedro Villa Isaza <jpvillaisaza@gmail.com>
+copyright:      2016 Juan Pedro Villa Isaza
+license:        MIT
+license-file:   LICENSE.md
+build-type:     Simple
+extra-source-files:
+    CHANGELOG.md
+    README.md
 
+source-repository head
+  type: git
+  location: https://github.com/jpvillaisaza/licensor
 
 library
-  hs-source-dirs:
-      src
   exposed-modules:
       Licensor
   other-modules:
       Paths_licensor
+  hs-source-dirs:
+      src
+  ghc-options: -Wall
   build-depends:
-      base >= 4.8 && < 4.11
-    , bytestring
-    , Cabal >= 1.22 && < 2.1
+      Cabal >=1.22 && <2.1
+    , base >=4.8 && <4.11
     , containers
     , directory
-    , http-conduit >= 2.1 && < 2.4
     , process
-  default-language:
-      Haskell2010
-  ghc-options:
-      -Wall
-
+  default-language: Haskell2010
 
 executable licensor
-  main-is:
-      Main.hs
+  main-is: Main.hs
+  other-modules:
+      Paths_licensor
+  hs-source-dirs:
+      app
+  ghc-options: -Wall -threaded -rtsopts -with-rtsopts=-N
   build-depends:
-      base
-    , Cabal
-    , cmdargs >= 0.10 && < 0.11
+      Cabal >=1.22 && <2.1
+    , base >=4.8 && <4.11
+    , cmdargs >=0.10 && <0.11
     , containers
     , directory
     , licensor
-  default-language:
-      Haskell2010
-  ghc-options:
-      -Wall -threaded -rtsopts -with-rtsopts=-N
-
-
-source-repository head
-  type: git
-  location: https://github.com/jpvillaisaza/licensor
+  default-language: Haskell2010
diff --git a/src/Licensor.hs b/src/Licensor.hs
--- a/src/Licensor.hs
+++ b/src/Licensor.hs
@@ -1,6 +1,4 @@
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
-{-# LANGUAGE NamedFieldPuns #-}
-{-# LANGUAGE RecordWildCards #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 
 ----------------------------------------------------------------------
@@ -26,21 +24,16 @@
 -- base
 import qualified Control.Exception as Exception
 import Control.Monad (unless)
-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
+import Distribution.License (License)
+import Distribution.Package (PackageIdentifier(..), PackageName)
+import Distribution.PackageDescription (PackageDescription, packageDescription)
+import Distribution.PackageDescription.Parse (readGenericPackageDescription)
+import Distribution.Simple.Utils (comparing, findPackageDesc)
+import Distribution.Text (Text, display, simpleParse)
+import Distribution.Verbosity (silent)
 
 -- containers
 import Data.Map.Strict (Map)
@@ -49,16 +42,13 @@
 import qualified Data.Set as Set
 
 -- directory
-import System.Directory
-
--- http-conduit
-import Network.HTTP.Simple (HttpException, getResponseBody, httpLBS, parseRequest)
+import System.Directory (getCurrentDirectory)
 
 -- licensor
 import qualified Paths_licensor
 
 -- process
-import System.Process
+import System.Process (readProcess)
 
 
 -- |
@@ -98,7 +88,7 @@
 getPackage = do
   currentDirectory <- getCurrentDirectory
   fmap getPackageDescription <$> findPackageDesc currentDirectory
-    >>= either (const (return Nothing)) (fmap Just)
+    >>= either (const (pure Nothing)) (fmap Just)
 
 
 -- |
@@ -107,7 +97,7 @@
 
 getPackageDescription :: FilePath -> IO PackageDescription
 getPackageDescription =
-  fmap packageDescription . readPackageDescription silent
+  fmap packageDescription . readGenericPackageDescription silent
 
 
 -- |
@@ -121,10 +111,10 @@
 
   case eitherDeps of
     Left (_ :: IOError) ->
-      return Nothing
+      pure Nothing
 
     Right deps ->
-      return $ fmap Set.fromList $ sequence $ fmap simpleParse (lines deps)
+      pure $ Set.fromList <$> traverse simpleParse (lines deps)
 
 
 getLicenses :: IO (Maybe [(PackageName, License)])
@@ -134,10 +124,10 @@
 
   case eitherDeps of
     Left (_ :: IOError) ->
-      return Nothing
+      pure Nothing
 
     Right deps ->
-      return $ sequence $ fmap toNameLicense (lines deps)
+      pure $ traverse toNameLicense (lines deps)
   where
     toNameLicense dep =
       case words dep of
@@ -155,45 +145,16 @@
 getPackageLicense
   :: Bool
   -> PackageIdentifier
-  -> Maybe [(PackageName, License)]
+  -> [(PackageName, License)]
   -> IO (Maybe LiLicense)
-getPackageLicense quiet p@PackageIdentifier{..} (Just licenses) = do
-  unless quiet (putStr $ display p ++ "...")
-  case lookup pkgName licenses of
+getPackageLicense quiet packageIdentifier licenses = do
+  unless quiet (putStr $ display packageIdentifier ++ "...")
+  case lookup (pkgName packageIdentifier) licenses of
     Just license -> do
       unless quiet (putStrLn $ display license)
-      return $ Just (LiLicense license)
+      pure $ Just (LiLicense license)
     Nothing ->
-      return Nothing
-getPackageLicense quiet p@PackageIdentifier{..} Nothing = do
-  unless quiet (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
-
-      unless quiet (putStrLn $ display license)
-
-      return $ Just (LiLicense license)
+      pure Nothing
 
 
 -- |
@@ -203,19 +164,19 @@
 orderPackagesByLicense
   :: Bool
   -> Maybe PackageIdentifier
-  -> Maybe [(PackageName, License)]
+  -> [(PackageName, License)]
   -> Set PackageIdentifier
   -> IO (Map LiLicense (Set PackageIdentifier), Set PackageIdentifier)
-orderPackagesByLicense quiet maybeP maybeLicenses =
+orderPackagesByLicense quiet maybeP licenses =
   let
     cond =
       maybe (const False) (==) maybeP
 
     insertPackage package orderedPackages' = do
-      maybeLicense <- getPackageLicense quiet package maybeLicenses
+      maybeLicense <- getPackageLicense quiet package licenses
 
       (orderedPackages, failed) <- orderedPackages'
-      return $
+      pure $
         if cond package
           then
             (orderedPackages, failed)
