diff --git a/ChangeLog b/ChangeLog
deleted file mode 100644
--- a/ChangeLog
+++ /dev/null
@@ -1,9 +0,0 @@
-* 0.2 (2018-08-17)
-- error if no spec file
-- filter out hidden files from deps search
-- add --version
-- generate manpage with help2man
-
-* 0.1 (2018-07-18)
-- initial release with sort, deps and rdeps (reverse dependencies) commands
-
diff --git a/ChangeLog.md b/ChangeLog.md
new file mode 100644
--- /dev/null
+++ b/ChangeLog.md
@@ -0,0 +1,15 @@
+# 0.3 (2019-10-10)
+- check package provides instead of rpms
+- use ByteString for packages (provides)
+- move to simple-cmd-args (optparse-applicative)
+- add --lenient for rpmspec failures
+
+# 0.2 (2018-08-17)
+- error if no spec file
+- filter out hidden files from deps search
+- add --version
+- generate manpage with help2man
+
+# 0.1 (2018-07-18)
+- initial release with sort, deps and rdeps (reverse dependencies) commands
+
diff --git a/Main.hs b/Main.hs
new file mode 100644
--- /dev/null
+++ b/Main.hs
@@ -0,0 +1,198 @@
+import Data.Graph.Inductive.Query.DFS (xdfsWith, topsort', scc, components)
+import Data.Graph.Inductive.Tree (Gr)
+import qualified Data.Graph.Inductive.Graph as Graph
+
+import qualified Data.Set as Set
+import Control.Applicative (some,
+#if (defined(MIN_VERSION_base) && MIN_VERSION_base(4,8,0))
+#else
+                            (<$>), (<*>)
+#endif
+                           )
+import Control.Monad (guard, when, unless)
+import qualified Data.ByteString.Char8 as B
+import Data.Maybe (catMaybes, fromMaybe, mapMaybe)
+import Data.List (delete)
+import Options.Applicative (str)
+import System.Directory (doesDirectoryExist, doesFileExist,
+#if (defined(MIN_VERSION_directory) && MIN_VERSION_directory(1,2,5))
+                         listDirectory
+#else
+                         getDirectoryContents
+#endif
+  )
+import System.Exit (ExitCode (..), exitFailure)
+import System.FilePath
+-- replace with warning
+import System.IO (hPutStrLn, stderr)
+import System.Process (readProcessWithExitCode)
+
+import SimpleCmdArgs
+import Paths_rpmbuild_order (version)
+
+#if (defined(MIN_VERSION_directory) && MIN_VERSION_directory(1,2,5))
+#else
+listDirectory :: FilePath -> IO [FilePath]
+listDirectory path =
+  filter f <$> getDirectoryContents path
+  where f filename = filename /= "." && filename /= ".."
+#endif
+
+main :: IO ()
+main =
+  simpleCmdArgs (Just version) "Order packages by build dependencies"
+  "Sort package sources (spec files) in build dependency order" $
+  subcommands
+  [ Subcommand "sort" "sort packages" $
+    sortSpecFiles <$> verboseOpt <*> lenientOpt <*> parallelOpt <*> subdirOpt <*> pkgArgs
+  , Subcommand "deps" "sort dependencies" $
+    depsSpecFiles False <$> verboseOpt <*> lenientOpt <*> parallelOpt <*> subdirOpt <*> pkgArgs
+  , Subcommand "rdeps" "sort dependents" $
+    depsSpecFiles True <$> verboseOpt <*> lenientOpt <*> parallelOpt <*> subdirOpt <*> pkgArgs
+  ]
+  where
+    verboseOpt = switchWith 'v' "verbose" "Verbose output for debugging"
+    lenientOpt = switchWith 'l' "lenient" "Ignore rpmspec errors"
+    parallelOpt = switchWith 'p' "parallel" "Separate independent packages"
+    subdirOpt = optional (strOptionWith 'd' "dir" "SUBDIR" "Branch directory")
+    pkgArgs = some (argumentWith str "PKG...")
+
+findSpec :: Maybe FilePath -> FilePath -> IO (Maybe FilePath)
+findSpec mdir file =
+  if takeExtension file == ".spec"
+    then checkFile file
+    else do
+    dirp <- doesDirectoryExist file
+    if dirp
+      then
+      let dir = maybe file (file </>) mdir
+          pkg = takeBaseName file in
+        checkFile $ dir </> pkg ++ ".spec"
+      else error $ "No spec file found for " ++ file
+  where
+    checkFile :: FilePath -> IO (Maybe FilePath)
+    checkFile f = do
+      e <- doesFileExist f
+      if e
+        then return $ Just f
+        else return Nothing
+
+type Package = B.ByteString
+
+data SourcePackage =
+   SourcePackage {
+      location :: FilePath,
+      package :: Package,
+      dependencies :: [Package]
+   }
+   deriving (Show, Eq)
+
+createGraphNodes :: Bool -> Bool -> Maybe FilePath -> [Package] -> [Package] ->
+                    IO (Gr SourcePackage (), [Graph.Node])
+createGraphNodes verbose lenient mdir pkgs subset = do
+  unless (all (`elem` pkgs) subset) $
+    error "Packages must be in the current directory"
+  specPaths <- catMaybes <$> mapM (findSpec mdir . B.unpack) pkgs
+  let names = map (B.pack . takeBaseName) specPaths
+  resolves <- catMaybes <$> mapM (readProvides verbose lenient) specPaths
+  deps <- catMaybes <$> mapM (getDepsSrcResolved verbose lenient resolves) specPaths
+  let spkgs = zipWith3 SourcePackage specPaths names deps
+      graph = getBuildGraph spkgs
+  checkForCycles graph
+  let nodes = Graph.labNodes graph
+      subnodes = mapMaybe (pkgNode nodes) subset
+  return (graph, subnodes)
+  where
+    pkgNode [] _ = Nothing
+    pkgNode ((i,l):ns) p = if p == package l then Just i else pkgNode ns p
+
+sortSpecFiles :: Bool -> Bool -> Bool -> Maybe FilePath -> [Package] -> IO ()
+sortSpecFiles verbose lenient parallel mdir pkgs = do
+      (graph, _) <- createGraphNodes verbose lenient mdir pkgs []
+      if parallel then
+        mapM_ ((B.putStrLn . B.cons '\n' . B.unwords . map package) . topsort' . subgraph graph) (components graph)
+        else mapM_ (B.putStrLn . package) $ topsort' graph
+ 
+depsSpecFiles :: Bool -> Bool -> Bool -> Bool -> Maybe FilePath -> [Package] -> IO ()
+depsSpecFiles rev verbose lenient parallel mdir pkgs = do
+  allpkgs <- map B.pack . filter (\ f -> head f /= '.') <$> listDirectory "."
+  (graph, nodes) <- createGraphNodes verbose lenient mdir allpkgs pkgs
+  let direction = if rev then Graph.suc' else Graph.pre'
+  sortSpecFiles verbose lenient parallel mdir $ map package $ xdfsWith direction third nodes graph
+  where
+    third (_, _, c, _) = c
+
+readProvides :: Bool -> Bool -> FilePath -> IO (Maybe (Package,[Package]))
+readProvides verbose lenient file = do
+  when verbose $ hPutStrLn stderr file
+  mpkgs <- rpmspecQuery lenient ["-q", "--provides", "--define", "ghc_version any"] file
+  case mpkgs of
+    Nothing -> return Nothing
+    Just pkgs ->
+      let pkg = B.pack $ takeBaseName file in
+        return $ Just (pkg, delete pkg pkgs)
+
+getDepsSrcResolved :: Bool -> Bool -> [(Package,[Package])] -> FilePath -> IO (Maybe [Package])
+getDepsSrcResolved verbose lenient provides file = do
+  when verbose $ hPutStrLn stderr file
+  fmap (map resolveBase) <$>
+    rpmspecQuery lenient ["--buildrequires", "--define", "ghc_version any"] file
+  where
+    resolveBase :: Package -> Package
+    resolveBase br =
+      case mapMaybe (\ (pkg,subs) -> if br `elem` subs then Just pkg else Nothing) provides of
+        [] -> br
+        [p] -> p
+        ps -> error $ B.unpack br ++ " is provided by: " ++ (B.unpack . B.unwords) ps
+
+getBuildGraph :: [SourcePackage] -> Gr SourcePackage ()
+getBuildGraph srcPkgs =
+   let nodes = zip [0..] srcPkgs
+       nodeDict = zip (map package srcPkgs) [0..]
+       edges = do
+          (srcNode,srcPkg) <- nodes
+          dstNode <- mapMaybe (`lookup` nodeDict) (dependencies srcPkg)
+          guard (dstNode /= srcNode)
+          return (dstNode, srcNode, ())
+   in Graph.mkGraph nodes edges
+
+checkForCycles :: Monad m => Gr SourcePackage () -> m ()
+checkForCycles graph =
+   case getCycles graph of
+      [] -> return ()
+      cycles ->
+        error $ unlines $
+        "Cycles in dependencies:" :
+        map (unwords . map location . nodeLabels graph) cycles
+
+nodeLabels :: Gr a b -> [Graph.Node] -> [a]
+nodeLabels graph =
+   map (fromMaybe (error "node not found in graph") .
+        Graph.lab graph)
+
+subgraph :: Gr a b -> [Graph.Node] -> Gr a b
+subgraph graph nodes =
+   let nodeSet = Set.fromList nodes
+       edges = do
+           from <- nodes
+           (to, lab) <- Graph.lsuc graph from
+           guard $ Set.member from nodeSet && Set.member to nodeSet
+           return (from,to,lab)
+   in  Graph.mkGraph (zip nodes $ nodeLabels graph nodes) edges
+
+getCycles :: Gr a b -> [[Graph.Node]]
+getCycles =
+   filter (\ x -> length x == 3) . scc
+
+-- returns the first word for each line
+rpmspecQuery :: Bool -> [String] -> FilePath -> IO (Maybe [B.ByteString])
+rpmspecQuery lenient args spec = do
+  (res, out, err) <- readProcessWithExitCode "rpmspec" (["-q"] ++ args ++ [spec]) ""
+  unless (null err) $ hPutStrLn stderr err
+  case res of
+    ExitFailure _ -> if lenient then return Nothing else exitFailure
+    ExitSuccess -> return $ Just $ map takeFirst $ B.lines (B.pack out)
+  where
+    -- ignore version bounds
+    takeFirst :: B.ByteString -> B.ByteString
+    takeFirst = head . B.words
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -22,13 +22,19 @@
 from the current set of checked out package sources.
 
 ## Known problems
-Given packages A, B, C, where C depends on B, and B depends on A,
+1. Given packages A, B, C, where C depends on B, and B depends on A,
 and you call
 
-    rpmbuild-order C.spec A.spec
+    rpmbuild-order sort C.spec A.spec
 
 then the output may be wrong if C does not have a direct dependency on A.
 Even if the order is correct, B is missing in the output
 and thus in this case the list of packages cannot be reliably used
 for a sequence of builds.
 
+However `rpmbuild-order deps` and `rpmbuild-order rdeps` take
+other neighbouring package directories into account.
+
+2. repoquery is not used to resolve Requires or filelists for Provides.
+So if a package BuildRequires: /usr/bin/sometool it will not be resolved.
+This may get addressed in a future version.
diff --git a/RpmbuildOrder.hs b/RpmbuildOrder.hs
deleted file mode 100644
--- a/RpmbuildOrder.hs
+++ /dev/null
@@ -1,324 +0,0 @@
-{-# LANGUAGE LambdaCase #-}
-
-module Main where
-
-import System.Console.GetOpt
-          (getOpt, ArgOrder(..), OptDescr(..), ArgDescr(..), usageInfo)
-import System.Exit (exitSuccess, exitFailure)
-import qualified System.Environment as Env
-import System.FilePath
-
-import System.Directory (doesDirectoryExist, doesFileExist,
-#if (defined(MIN_VERSION_directory) && MIN_VERSION_directory(1,2,5))
-                         listDirectory
-#else
-                         getDirectoryContents
-#endif
-  )
-import System.IO (hPutStrLn, stderr)
-import System.Process (readProcess)
-
-import Data.Graph.Inductive.Query.DFS (xdfsWith, topsort', scc, components)
-import Data.Graph.Inductive.Tree (Gr)
-import qualified Data.Graph.Inductive.Graph as Graph
-
-import qualified Control.Monad.Exception.Synchronous as E
-import qualified Control.Monad.Trans.Class as T
-
-import qualified Data.Set as Set
-import Control.Monad (guard, when, unless)
-import Data.Maybe (catMaybes, fromMaybe, mapMaybe)
-import Data.List (delete, intersperse, stripPrefix)
-import Data.Version  (showVersion)
-
-import Paths_rpmbuild_order (version)
-
-#if (defined(MIN_VERSION_base) && MIN_VERSION_base(4,8,2))
-#else
-import Control.Applicative ((<$>))
-#endif
-
-#if (defined(MIN_VERSION_directory) && MIN_VERSION_directory(1,2,5))
-#else
-listDirectory :: FilePath -> IO [FilePath]
-listDirectory path =
-  filter f <$> getDirectoryContents path
-  where f filename = filename /= "." && filename /= ".."
-#endif
-
-main :: IO ()
-main =
-  E.resolveT handleException $ do
-  argv <- T.lift Env.getArgs
-  let (opts, args, errors) = getOpt Permute options argv
-  flags <-
-    E.ExceptionalT $ return $
-        foldr (=<<)
-           (return
-            Flags {optHelp = False,
-                   optVersion = False,
-                   optVerbosity = False,
-                   optFormat = package,
-                   optParallel = Nothing,
-                   optBranch = Nothing})
-           opts
-  if optHelp flags
-    then T.lift $ help >> exitSuccess
-    else
-    if optVersion flags
-    then T.lift $ putStrLn $ showVersion version
-    else
-      if length args < 2
-      then T.lift $ help >> exitFailure
-      else do
-        let (com:pkgs) = args
-        unless (null errors) $ E.throwT $ concat errors
-        unless (com `elem` ["sort", "deps", "rdeps"]) $
-          E.throwT $ "Unknown command " ++ com
-        runCommand flags com $ map (removeSuffix "/") pkgs
-  where
-    help =
-      Env.getProgName >>= \programName ->
-        putStrLn
-             (usageInfo ("Usage: " ++ programName ++
-                         " [OPTIONS] [sort|deps|rdeps] PKG-SPEC-OR-DIR ...") options)
-
-handleException :: String -> IO ()
-handleException msg = do
-   putStrLn $ "Aborted: " ++ msg
-   exitFailure
-
-findSpec :: Maybe FilePath -> FilePath -> IO (Maybe FilePath)
-findSpec mdir file =
-  if takeExtension file == ".spec"
-    then checkFile file
-    else do
-    dirp <- doesDirectoryExist file
-    if dirp
-      then
-      let dir = maybe file (file </>) mdir
-          pkg = takeBaseName file in
-        checkFile $ dir </> pkg ++ ".spec"
-      else error $ "No spec file found for " ++ file
-  where
-    checkFile :: FilePath -> IO (Maybe FilePath)
-    checkFile f = do
-      e <- doesFileExist f
-      if e
-        then return $ Just f
-        else return Nothing
-
-data Flags =
-   Flags {
-      optHelp :: Bool,
-      optVersion :: Bool,
-      optVerbosity :: Bool,
-      optFormat :: SourcePackage -> String,
-      optParallel :: Maybe String,
-      optBranch :: Maybe FilePath
-   }
-
-options :: [OptDescr (Flags -> E.Exceptional String Flags)]
-options =
-  [
-    Option ['h'] ["help"]
-      (NoArg (\flags -> return $ flags{optHelp = True}))
-      "Show options"
-  , Option ['V'] ["version"]
-      (NoArg (\flags -> return $ flags{optVersion = True}))
-      "Show version"
-  , Option ['p'] ["parallel"]
-      (OptArg
-        (\mstr flags ->
-            fmap (\cs -> flags{optParallel = Just cs})
-            (E.Success (fromMaybe "" mstr)))
-         "SEPARATOR")
-      "Display independently buildable groups of packages, optionally with separator"
-  , Option ['b'] ["branch"]
-      (ReqArg
-         (\str flags ->
-            fmap (\mb -> flags{optBranch = mb})
-            (E.Success (Just str)))
-         "BRANCHDIR")
-    "branch directory"
-  , Option ['f'] ["format"]
-      (ReqArg
-         (\str flags ->
-            fmap (\select -> flags{optFormat = select}) $
-            case str of
-               "package" -> E.Success package
-               "spec" -> E.Success location
-               "dir"  -> E.Success (takeDirectory . location)
-               _ ->
-                  E.Exception $
-                  "unknown info type " ++ str)
-         "KIND")
-      "output format: 'package' (default), 'spec', or 'dir'"
-  , Option ['v'] ["verbose"]
-      (NoArg
-         (\flags ->
-            return flags{optVerbosity = True}))
-      "verbose output"
-  ]
-
-type Package = String
-
-data SourcePackage =
-   SourcePackage {
-      location :: FilePath,
-      package :: Package,
-      dependencies :: [Package]
-   }
-   deriving (Show, Eq)
-
-type Command = String
-
-runCommand :: Flags -> Command -> [Package] -> E.ExceptionalT String IO ()
-runCommand flags "sort" pkgs = sortSpecFiles flags pkgs
-runCommand flags "deps" pkgs = depsSpecFiles False flags pkgs
-runCommand flags "rdeps" pkgs = depsSpecFiles True flags pkgs
-runCommand _ _ _ = E.throwT "impossible happened"
-
-createGraphNodes :: Flags -> [Package] -> [Package] ->
-               E.ExceptionalT String IO (Gr SourcePackage (), [Graph.Node])
-createGraphNodes flags pkgs subset = do
-  unless (all (`elem` pkgs) subset) $
-    E.throwT "Packages must be in the current directory"
-  specPaths <- T.lift $ catMaybes <$> mapM (findSpec (optBranch flags)) (filter (/= fromMaybe "" (optParallel flags)) pkgs)
-  let names = map takeBaseName specPaths
-  provs <-
-     T.lift $
-     mapM (readProvides (optVerbosity flags)) specPaths
-  let resolves = zip names provs
-  deps <-
-     T.lift $
-     mapM (getDepsSrcResolved (optVerbosity flags) resolves) specPaths
-  let spkgs = zipWith3 SourcePackage specPaths names deps
-      graph = getBuildGraph spkgs
-  checkForCycles graph
-  let nodes = Graph.labNodes graph
-      subnodes = mapMaybe (pkgNode nodes) subset
-  return (graph, subnodes)
-  where
-    pkgNode [] _ = Nothing
-    pkgNode ((i,l):ns) p = if p == package l then Just i else pkgNode ns p
-
-sortSpecFiles :: Flags -> [Package] -> E.ExceptionalT String IO ()
-sortSpecFiles flags pkgs = do
-      (graph, _) <- createGraphNodes flags pkgs []
-      T.lift $
-         case optParallel flags of
-           Just s ->
-             mapM_ ((putStrLn . unwords . (if null s then id else intersperse s) . map (optFormat flags)) . topsort' . subgraph graph)
-                 (components graph)
-           Nothing ->
-             mapM_ (putStrLn . optFormat flags) $ topsort' graph
- 
-depsSpecFiles :: Bool -> Flags -> [Package] -> E.ExceptionalT String IO ()
-depsSpecFiles rev flags pkgs = do
-  allpkgs <- T.lift $ filter (\ f -> head f /= '.') <$> listDirectory "."
-  (graph, nodes) <- createGraphNodes flags allpkgs pkgs
-  let dir = if rev then Graph.suc' else Graph.pre'
-  sortSpecFiles flags $ map package $ xdfsWith dir third nodes graph
-  where
-    third (_, _, c, _) = c
-
-readProvides :: Bool -> FilePath -> IO [String]
-readProvides verbose file = do
-  when verbose $ hPutStrLn stderr file
-  pkgs <- lines <$>
-    rpmspec ["--rpms", "--qf=%{name}\n", "--define", "ghc_version any"] Nothing file
-  let pkg = takeBaseName file
-  return $ delete pkg pkgs
-
-getDepsSrcResolved :: Bool -> [(String,[String])] -> FilePath -> IO [String]
-getDepsSrcResolved verbose provides file =
-  map (resolveBase provides) <$> do
-      when verbose $ hPutStrLn stderr file
-      -- ignore version bounds
-      map (head . words) . lines <$>
-        rpmspec ["--buildrequires", "--define", "ghc_version any"] Nothing file
-  where
-    resolveBase :: [(String,[String])] -> String -> String
-    resolveBase provs br =
-      case mapMaybe (\ (pkg,subs) -> if br `elem` subs then Just pkg else Nothing) provs of
-        [] -> br
-        [p] -> p
-        ps -> error $ br ++ "is provided by: " ++ unwords ps
-
-removeSuffix :: String -> String -> String
-removeSuffix suffix orig =
-  fromMaybe orig $ stripSuffix suffix orig
-  where
-    stripSuffix sf str = reverse <$> stripPrefix (reverse sf) (reverse str)
-
-cmdStdIn :: String -> [String] -> String -> IO String
-cmdStdIn c as inp = removeTrailingNewline <$> readProcess c as inp
-  where
-    removeTrailingNewline :: String -> String
-    removeTrailingNewline "" = ""
-    removeTrailingNewline str =
-      if last str == '\n'
-      then init str
-      else str
-
-cmd :: String -> [String] -> IO String
-cmd c as = cmdStdIn c as ""
-
-rpmspec :: [String] -> Maybe String -> FilePath -> IO String
-rpmspec args mqf spec = do
-  let qf = maybe [] (\ q -> ["--queryformat", q]) mqf
-  cmd "rpmspec" (["-q"] ++ args ++ qf ++ [spec])
-
-getDeps :: Gr SourcePackage () -> [(SourcePackage, [SourcePackage])]
-getDeps gr =
-    let c2dep :: Graph.Context SourcePackage () -> (SourcePackage, [SourcePackage])
-        c2dep ctx =
-           (Graph.lab' ctx,
-            map (Graph.lab' . Graph.context gr) (Graph.pre gr . Graph.node' $ ctx))
-    in  Graph.ufold (\ctx ds -> c2dep ctx : ds) [] gr
-
-getBuildGraph :: [SourcePackage] -> Gr SourcePackage ()
-getBuildGraph srcPkgs =
-   let nodes = zip [0..] srcPkgs
-       nodeDict = zip (map package srcPkgs) [0..]
-       edges = do
-          (srcNode,srcPkg) <- nodes
-          dstNode <- mapMaybe (`lookup` nodeDict) (dependencies srcPkg)
-          guard (dstNode /= srcNode)
-          return (dstNode, srcNode, ())
-   in Graph.mkGraph nodes edges
-
-checkForCycles ::
-   Monad m =>
-   Gr SourcePackage () ->
-   E.ExceptionalT String m ()
-checkForCycles graph =
-   case getCycles graph of
-      [] -> return ()
-      cycles ->
-         E.throwT $ unlines $
-         "Cycles in dependencies:" :
-         map (unwords . map location . nodeLabels graph) cycles
-
-nodeLabels :: Gr a b -> [Graph.Node] -> [a]
-nodeLabels graph =
-   map (fromMaybe (error "node not found in graph") .
-        Graph.lab graph)
-
-subgraph :: Gr a b -> [Graph.Node] -> Gr a b
-subgraph graph nodes =
-   let nodeSet = Set.fromList nodes
-       edges = do
-           from <- nodes
-           (to, lab) <- Graph.lsuc graph from
-           guard $ Set.member from nodeSet && Set.member to nodeSet
-           return (from,to,lab)
-   in  Graph.mkGraph (zip nodes $ nodeLabels graph nodes) edges
-
-getCycles :: Gr a b -> [[Graph.Node]]
-getCycles =
-   filter (\case
-              _:_:_ -> True
-              _ -> False)
-   . scc
diff --git a/TODO b/TODO
--- a/TODO
+++ b/TODO
@@ -1,1 +1,2 @@
-add leaf command
+- add leaf command
+- better graph output
diff --git a/rpmbuild-order.1 b/rpmbuild-order.1
--- a/rpmbuild-order.1
+++ b/rpmbuild-order.1
@@ -1,26 +1,28 @@
-.\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.47.6.
-.TH RPMBUILD-ORDER "1" "August 2018" "rpmbuild-order 0.2" "User Commands"
+.\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.47.11.
+.TH RPMBUILD-ORDER "1" "October 2019" "rpmbuild-order 0.3" "User Commands"
 .SH NAME
-rpmbuild-order \- manual page for rpmbuild-order 0.2
+rpmbuild-order \- manual page for rpmbuild-order 0.3
 .SH SYNOPSIS
 .B rpmbuild-order
-[\fI\,OPTIONS\/\fR] [\fI\,sort|deps|rdeps\/\fR] \fI\,PKG-SPEC-OR-DIR \/\fR...
+[\fI\,--version\/\fR] \fI\,COMMAND\/\fR
 .SH DESCRIPTION
+Order packages by build dependencies
+.IP
+Sort package sources (spec files) in build dependency order
+.SS "Available options:"
 .TP
-\fB\-h\fR             \fB\-\-help\fR
-Show options
+\fB\-h\fR,\-\-help
+Show this help text
 .TP
-\fB\-V\fR             \fB\-\-version\fR
+\fB\-\-version\fR
 Show version
-.TP
-\fB\-p[SEPARATOR]\fR  \fB\-\-parallel\fR[=\fI\,SEPARATOR\/\fR]
-Display independently buildable groups of packages, optionally with separator
+.SS "Available commands:"
 .TP
-\fB\-b\fR BRANCHDIR   \fB\-\-branch\fR=\fI\,BRANCHDIR\/\fR
-branch directory
+sort
+sort packages
 .TP
-\fB\-f\fR KIND        \fB\-\-format\fR=\fI\,KIND\/\fR
-output format: 'package' (default), 'spec', or 'dir'
+deps
+sort dependencies
 .TP
-\fB\-v\fR             \fB\-\-verbose\fR
-verbose output
+rdeps
+sort dependents
diff --git a/rpmbuild-order.cabal b/rpmbuild-order.cabal
--- a/rpmbuild-order.cabal
+++ b/rpmbuild-order.cabal
@@ -1,11 +1,11 @@
 Name:             rpmbuild-order
-Version:          0.2.1
+Version:          0.3
 License:          BSD3
 License-File:     LICENSE
 Author:           Henning Thielemann <haskell@henning-thielemann.de>
 Maintainer:       Jens Petersen <petersen@redhat.com>
 Copyright:        2010-2018  Henning Thielemann,
-                  2018 Jens Petersen <petersen@redhat.com>
+                  2018-2019 Jens Petersen <petersen@redhat.com>
 Category:         Distribution
 Homepage:         https://github.com/juhp/rpmbuild-order
 Bug-reports:      https://github.com/juhp/rpmbuild-order/issues
@@ -17,32 +17,32 @@
   The code originates from cabal-sort by Henning Thielemann.
   It can also output the ordered dependencies or reverse depends
   for one or more packages, provided all the packages are checked out
-  in neighbouring directories. This is also useful to see what packages
+  in neighboring directories. This is also useful to see what packages
   are affected when a low-level package changes.
 Tested-with:       GHC == 7.4.2, GHC == 7.6.3, GHC == 7.8.4,
                    GHC == 7.10.3, GHC == 8.0.2, GHC == 8.2.2,
-                   GHC == 8.4.3
+                   GHC == 8.4.4, GHC == 8.6.5, GHC == 8.8.1
 Cabal-Version:     >=1.6
 Build-Type:        Simple
-Extra-source-files: README.md TODO ChangeLog rpmbuild-order.1
+Extra-source-files: README.md TODO ChangeLog.md rpmbuild-order.1
 
 source-repository head
   type:     git
   location: https://github.com/juhp/rpmbuild-order
 
 Executable rpmbuild-order
-  Build-Depends:
-    base < 5,
-    Cabal,
-    containers,
-    directory,
-    explicit-exception,
-    filepath,
-    fgl, 
-    process,
-    transformers
+  Build-Depends: base < 5,
+                 bytestring,
+                 Cabal,
+                 containers,
+                 directory,
+                 filepath,
+                 fgl,
+                 optparse-applicative,
+                 process,
+                 simple-cmd-args
 
   GHC-Options:      -Wall
-  Main-Is:          RpmbuildOrder.hs
+  Main-Is:          Main.hs
   Extensions:       CPP
   Other-modules:    Paths_rpmbuild_order
