diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,21 @@
 # Version history of koji-tool
 
+## 1.2 (2024-07-27)
+- allow --unlimited results: useful for open tasks/builds
+- builds: also show owner
+- find: also support noarch
+- find: move --debug to debug arg
+- improve detailed output handling with Maybe Details for tasks and builds
+- improvements to log url logic
+- install: include noarch in getArchs to include noarch rpms
+- lookupArch first checks the label field then arch field
+- progress: use safe maximumMay of sizes
+- tasks: add --children and --parent of taskid
+- tasks: add --install option
+- tasks: also show create time and owner
+- tasks: in addition to buildlog size also print timestamp
+- tasks: ignore subtask limit for Package, ParentOf, ChildrenOf
+
 ## 1.1.1 (2023-10-20)
 - 'builds': reformat short build result to align better
 - 'install': detect ostree with "/sysroot/ostree" not rpm-ostree
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -22,11 +22,13 @@
 
 ## Commands
 `$ koji-tool --version`
+
 ```
-1.1.1
+1.2
 ```
 
 `$ koji-tool --help`
+
 ```
 Query and track Koji tasks, and install rpms from Koji.
 
@@ -49,33 +51,40 @@
   buildlog-sizes           Show buildlog sizes for nvr patterns
   find                     Simple quick common queries using words like: [my,
                            last, fail, complete, current, build, detail,
-                           install, tail, notail, hwinfo, x86_64, PACKAGE,
-                           USER\'s, LIMIT]
+                           install, tail, notail, hwinfo, x86_64, debug,
+                           PACKAGE, USER\'s, LIMIT]
 ```
 
 ## koji-tool builds
 
-Query Koji for builds.
+The `builds` command queries Koji for builds.
 
 Somewhat like `koji list-builds --quiet ...`,
 but it shows duration, and kojiweb urls.
-It uses `date` to parse a specified date string
-and can use an NVR glob pattern to select builds.
 
 Note results are ordered by build_id (not time) for speed.
 
 ### Usage
 
-By default lists up to 10 Fedora Koji builds.
+By default it lists up to 10 Fedora Koji builds -
+this can be changed with the `--limit` or `--unlimited` options.
 
+One can select builds also by time/date options,
+which are parsed by the system `date` utility.
+
+One can also use an NVR glob pattern to select builds.
+
+
 `$ koji-tool builds --help`
+
 ```
-Usage: koji-tool builds [-H|--hub HUB] [(-u|--user USER) | (-M|--mine)]
-                        [(-L|--latest) | (-l|--limit INT)] [-s|--state STATE]
-                        [(-B|--before TIMESTAMP) | (-F|--from TIMESTAMP)]
-                        [-T|--type TYPE] [(-d|--details) | (-t|--tasks)]
-                        [-i|--install INSTALLOPTS] [-D|--debug]
-                        [(-b|--build NVR/BUILDID) | (-p|--pattern NVRPAT) |
+Usage: koji-tool builds [-H|--hub HUB] [(-u|--user USER) | (-M|--mine)] 
+                        [(-L|--latest) | (-U|--unlimited) | (-l|--limit INT)] 
+                        [-s|--state STATE] 
+                        [(-B|--before TIMESTAMP) | (-F|--from TIMESTAMP)] 
+                        [-T|--type TYPE] [(-d|--details) | (-t|--tasks)] 
+                        [-i|--install INSTALLOPTS] [-D|--debug] 
+                        [(-b|--build NVR/BUILDID) | (-p|--pattern NVRPAT) | 
                           PACKAGE]
 
   Query Koji builds (by default lists the most recent builds)
@@ -86,7 +95,8 @@
   -u,--user USER           Koji user
   -M,--mine                Your tasks (krb fasid)
   -L,--latest              Latest build
-  -l,--limit INT           Maximum number of builds to show [default: 10]
+  -U,--unlimited           No limit on number of results
+  -l,--limit INT           Maximum number of builds to show [default: 20]
   -s,--state STATE         Filter builds by state
                            (building,complete,deleted,fail(ed),cancel(ed)
   -B,--before TIMESTAMP    Builds completed before timedate [default: now]
@@ -109,43 +119,58 @@
 lists your recent builds that failed.
 
 List latest build of a package:
-```shellsession
-$ koji-tool builds --pattern redhat-rpm-config*.fc37 --latest
 
-redhat-rpm-config-218-1.fc37 BuildComplete
-https://koji.fedoraproject.org/koji/buildinfo?buildID=1963037
-https://koji.fedoraproject.org/koji/taskinfo?taskID=86677797
-Start: Thu May  5 19:02:33 +08 2022
-End:   Thu May  5 19:04:26 +08 2022
-duration: 0h 1m 53s
+`$ koji-tool builds --pattern redhat-rpm-config*.fc40 --latest`
+
 ```
+redhat-rpm-config-288-1.fc40 BuildComplete (fweimer)
+https://koji.fedoraproject.org/koji/buildinfo?buildID=2460713
+https://koji.fedoraproject.org/koji/taskinfo?taskID=118524958
+start:      Tue Jun  4 03:07:58 +08 2024
+completion: Tue Jun  4 03:12:51 +08 2024
+duration: 4 min 53 sec
+https://kojipkgs.fedoraproject.org/packages/redhat-rpm-config/288/1.fc40
+```
 
 ## koji-tool tasks
 
-Query Koji for tasks.
+The `tasks` command queries Koji for tasks.
 
 Somewhat like `koji list-tasks --quiet --all ...`,
-but it shows duration, kojiweb urls and build.log size,
-and it uses `date` to parse a specified date string
-and can filter task results by package or nvr prefix.
+but it shows duration, kojiweb urls and optionally build.log size.
 
 Note results are ordered by task id (not time) for speed.
 
 ### Usage
 
-By default it lists 10 most recent Fedora Koji buildArch tasks.
+By default it lists 10 most recent Fedora Koji buildArch tasks,
+this can be changed with the `--limit` or `--unlimited` options.
 
+Tasks can be searched by package, task id (including parent and children),
+by build or NVR pattern, also by state, method, and user.
+
+Results can be restricted by date options,
+which are parsed by the `date` utility.
+The received results can be filtered too locally by package or nvr prefix.
+
+Multiple results are listed concisely each on one line by default.
+A single task result is displayed in detail over multiple lines.
+These levels of detail can be controlled with
+the `--details` and `--concise` options.
+
 `$ koji-tool tasks --help`
+
 ```
-Usage: koji-tool tasks [-H|--hub HUB] [(-u|--user USER) | (-M|--mine)]
-                       [(-L|--latest) | (-l|--limit INT)] [-s|--state STATE]
-                       [-a|--arch ARCH]
-                       [(-B|--before TIMESTAMP) | (-F|--from TIMESTAMP)]
-                       [-m|--method METHOD] [-D|--debug]
-                       [(-P|--only-package PKG) | (-N|--only-nvr PREFIX)]
-                       [-d|--details] [-T|--tail] [--hw-info] [-g|--grep STRING]
-                       [(-b|--build BUILD) | (-p|--pattern NVRPAT) |
-                         PACKAGE|TASKID]
+Usage: koji-tool tasks [-H|--hub HUB] [(-u|--user USER) | (-M|--mine)] 
+                       [(-L|--latest) | (-U|--unlimited) | (-l|--limit INT)] 
+                       [-s|--state STATE] [-a|--arch ARCH] 
+                       [(-B|--before TIMESTAMP) | (-F|--from TIMESTAMP)] 
+                       [-m|--method METHOD] [-D|--debug] 
+                       [(-P|--only-package PKG) | (-N|--only-nvr PREFIX)] 
+                       [(-d|--details) | (-c|--concise)] [-T|--tail] [--hw-info]
+                       [-g|--grep STRING] [-i|--install INSTALLOPTS] 
+                       [(-b|--build BUILD) | (-p|--pattern NVRPAT) | 
+                         --children TASKID | --parent TASKID | PACKAGE|TASKID]
 
   Query Koji tasks (by default lists the most recent buildArch tasks)
 
@@ -155,7 +180,8 @@
   -u,--user USER           Koji user
   -M,--mine                Your tasks (krb fasid)
   -L,--latest              Latest build or task
-  -l,--limit INT           Maximum number of tasks to show [default: 10]
+  -U,--unlimited           No limit on number of results
+  -l,--limit INT           Maximum number of tasks to show [default: 20]
   -s,--state STATE         Filter tasks by state
                            (open,close(d),cancel(ed),fail(ed),assigned,free)
   -a,--arch ARCH           Task arch
@@ -166,12 +192,16 @@
   -D,--debug               Pretty-print raw XML result
   -P,--only-package PKG    Filter task results to specified package
   -N,--only-nvr PREFIX     Filter task results by NVR prefix
-  -d,--details             Show more details of builds
+  -d,--details             Show more task details
+  -c,--concise             Compact task output
   -T,--tail                Fetch the tail of build.log
   --hw-info                Fetch hw_info.log
   -g,--grep STRING         Filter matching log lines
+  -i,--install INSTALLOPTS Install the package with 'install' options
   -b,--build BUILD         List child tasks of build
   -p,--pattern NVRPAT      Build tasks of matching pattern
+  --children TASKID        Children tasks of parent
+  --parent TASKID          Parent of task
   -h,--help                Show this help text
 ```
 
@@ -183,27 +213,33 @@
 lists your recent arm64 tasks that failed.
 
 Show latest newRepo task:
-```shellsession
-$ koji-tool tasks --method newrepo --latest
 
-eln-build newRepo TaskClosed
-https://koji.fedoraproject.org/koji/taskinfo?taskID=86821565
-Start: Mon May  9 11:53:53 +08 2022
-End:   Mon May  9 11:57:13 +08 2022
-duration: 0h 3m 20s
+`$ koji-tool tasks --method newrepo --latest`
+
 ```
+eln-build-side-93068 newRepo TaskClosed (kojira)
+https://koji.fedoraproject.org/koji/taskinfo?taskID=121120828
+create:     Sat Jul 27 18:59:06 +08 2024
+start:      Sat Jul 27 19:00:03 +08 2024
+completion: Sat Jul 27 19:03:12 +08 2024
+delay: 57 sec
+duration: 3 min 9 sec
+```
 
 List latest package build's tasks:
-```shellsession
-$ koji-tool tasks --latest redhat-rpm-config
 
-redhat-rpm-config-218-1.eln118.noarch TaskClosed
-https://koji.fedoraproject.org/koji/taskinfo?taskID=86685316 (parent: 86685296)
-Start: Fri May  6 00:11:10 +08 2022
-End:   Fri May  6 00:13:07 +08 2022
-duration: 0h 1m 57s
-https://kojipkgs.fedoraproject.org/work/tasks/5316/86685316/build.log (13kB)
+`$ koji-tool tasks --latest redhat-rpm-config`
+
 ```
+redhat-rpm-config-293-1.eln140.noarch TaskClosed (distrobuildsync-eln/jenkins-continuous-infra.apps.ci.centos.org)
+https://koji.fedoraproject.org/koji/taskinfo?taskID=119218471 (parent: 119209735)
+create:     Tue Jun 18 14:40:53 +08 2024
+start:      Tue Jun 18 19:13:53 +08 2024
+completion: Tue Jun 18 19:15:12 +08 2024
+delay: 4 hours 33 min
+duration: 1 min 19 sec
+https://kojipkgs.fedoraproject.org/packages/redhat-rpm-config/293/1.eln140/data/logs/noarch/build.log (17kB)
+```
 
 It is also possible to install packages from a task using
 `--install "SUBPKG OPTIONS"`.
@@ -217,14 +253,15 @@
 
 ## koji-tool install
 
-Download and install rpms from a Koji build or task.
+Use the `install` command to download and install rpms
+from a Koji build or task.
 
 By default it only downloads binaries of already-installed subpackages,
 but there are options to list and select or exclude specific subpackages.
 
 Note this command is intended for development and testing purposes
 and should not be necessary/used normally on production systems,
-but it can be very helpful for quickly testing an specific package build or
+but it can be very helpful for quickly testing a specific package build or
 update locally.
 
 ### Usage
@@ -234,7 +271,7 @@
 ```
 will download the latest build for your Fedora version,
 and try to install it.
-Use `--disttag` suffix to select a different Fedora version.
+Use `--disttag` suffix to select a different OS version.
 
 ```shellsession
 $ koji-tool install TASKID --except "*-devel"
@@ -268,21 +305,23 @@
 
 `--prefix`: override the subpackage prefix
 
-Subpackage selection has only been tested so far for a single build/task.
+(Subpackage selection has only really been tested so far
+for a single build/task.)
 
 ### Help
 `$ koji-tool install --help`
+
 ```
-Usage: koji-tool install [-n|--dry-run] [-D|--debug] [-y|--yes] [-H|--hub HUB]
-                         [-P|--packages-url URL] [-l|--list] [-L|--latest]
-                         [-t|--check-remote-time]
-                         [--rpm | --rpm-ostree | --dnf5 | --dnf3]
-                         [-a|--arch ARCH]
-                         [(-N|--no-reinstall) | (-S|--skip-existing)]
-                         [-b|--prefix SUBPKGPREFIX]
-                         [--all | --ask | [-p|--package SUBPKG]
-                           [-e|--except SUBPKG] [-x|--exclude SUBPKG]
-                           [-i|--include SUBPKG]] [-d|--disttag DISTTAG]
+Usage: koji-tool install [-n|--dry-run] [-D|--debug] [-y|--yes] [-H|--hub HUB] 
+                         [-P|--packages-url URL] [-l|--list] [-L|--latest] 
+                         [-t|--check-remote-time] 
+                         [--rpm | --rpm-ostree | --dnf5 | --dnf3] 
+                         [-a|--arch ARCH] 
+                         [(-N|--no-reinstall) | (-S|--skip-existing)] 
+                         [-b|--prefix SUBPKGPREFIX] 
+                         [--all | --ask | [-p|--package SUBPKG] 
+                           [-e|--except SUBPKG] [-x|--exclude SUBPKG] 
+                           [-i|--include SUBPKG]] [-d|--disttag DISTTAG] 
                          [(-R|--nvr) | (-V|--nv)] PKG|NVR|TASKID...
 
   Install rpm packages directly from a Koji build task
@@ -329,26 +368,19 @@
 `koji-tool find last complete build` shows the latest completed koji build (equivalent to `koji-tool builds -L -s complete`).
 
 ### Help
-```shellsession
-$ koji-tool find
-koji-tool: find handles these words:
+`$ koji-tool find --help`
 
-my mine
-last latest
-fail failure failed
-complete completed completion close closed finish finished
-current building open
-build builds
-detail details detailed
-install
-tail
-notail
-hwinfo
-x86_64 aarch64 ppc64le s390x i686 armv7hl
-PACKAGE
-USER\'s
-LIMIT
+```
+Usage: koji-tool find [-H|--hub HUB] [PHRASE]
 
+  Simple quick common queries using words like: [my, last, fail, complete,
+  current, build, detail, install, tail, notail, hwinfo, x86_64, debug, PACKAGE,
+  USER\'s, LIMIT]
+
+Available options:
+  -H,--hub HUB             KojiHub shortname or url (HUB = fedora, stream,
+                           rpmfusion, or URL) [default: fedora]
+  -h,--help                Show this help text
 ```
 
 ## koji-tool progress
@@ -365,7 +397,8 @@
 ```shellsession
 $ koji-tool progress
 :
-$ koji-tool progress 93808251  # ← Koji taskid
+:
+$ koji-tool progress 93808251
 21:39:41 webkitgtk-2.38.2-1.eln123 (93808251) 9h 32m
 aarch64  87,669kB (16:50:31)  3h 55m TaskClosed
 i386     88,120kB (16:33:14)  4h 21m TaskClosed
diff --git a/koji-tool.cabal b/koji-tool.cabal
--- a/koji-tool.cabal
+++ b/koji-tool.cabal
@@ -1,5 +1,5 @@
 name:                koji-tool
-version:             1.1.1
+version:             1.2
 synopsis:            Koji CLI tool for querying tasks and installing builds
 description:
         koji-tool is a CLI interface to Koji with commands to query
@@ -10,7 +10,7 @@
 license-file:        LICENSE
 author:              Jens Petersen <petersen@redhat.com>
 maintainer:          Jens Petersen <petersen@redhat.com>
-copyright:           2021-2023  Jens Petersen <petersen@redhat.com>
+copyright:           2021-2024  Jens Petersen <petersen@redhat.com>
 category:            Utility
 homepage:            https://github.com/juhp/koji-tool
 bug-reports:         https://github.com/juhp/koji-tool/issues
@@ -24,8 +24,9 @@
                      || == 8.10.7
                      || == 9.0.2
                      || == 9.2.8
-                     || == 9.4.7
-                     || == 9.6.3
+                     || == 9.4.8
+                     || == 9.6.6
+                     || == 9.8.2
 
 source-repository head
   type:                git
@@ -57,6 +58,7 @@
                        koji >= 0.0.2,
                        pretty-simple,
                        rpm-nvr >= 0.1.2,
+                       safe,
                        simple-cmd >= 0.2.2,
                        simple-cmd-args >= 0.1.8,
                        simple-prompt >=0.2,
diff --git a/src/BuildlogSizes.hs b/src/BuildlogSizes.hs
--- a/src/BuildlogSizes.hs
+++ b/src/BuildlogSizes.hs
@@ -33,7 +33,8 @@
 
 import SimpleCmdArgs
 
-import Common (commonBuildQueryOptions, getBuildState)
+import Common (commonBuildQueryOptions, getBuildState, lookupArch)
+import Utils (buildlogUrlfromTaskId)
 
 -- FIXME split off arch suffix
 -- FIXME show build duration
@@ -49,7 +50,7 @@
           else nvrpat
     results <- listBuilds fedoraKojiHub
                [("pattern", ValueString pat),
-                commonBuildQueryOptions 5]
+                commonBuildQueryOptions (Just 5)]
     if null results
       then if '*' `notElem` pat
            then buildlogSizesCmd $ nvrpat ++ "*"
@@ -92,7 +93,7 @@
 
 buildlogSizes :: Int -> IO ()
 buildlogSizes tid = do
-  children <- sortOn (\t -> lookupStruct "arch" t :: Maybe String) <$>
+  children <- sortOn lookupArch <$>
               getTaskChildren fedoraKojiHub tid True
   mapM_ buildlogSize children
 
@@ -104,10 +105,7 @@
       whenJust (lookupStruct "arch" child) $
         doGetBuildlogSize buildlog
       where
-        buildlog = "https://kojipkgs.fedoraproject.org/work/tasks" +/+ lastFew +/+ show tid +/+ "build.log"
-        lastFew =
-          let few = dropWhile (== '0') $ drop 4 (show tid) in
-            if null few then "0" else few
+        buildlog = buildlogUrlfromTaskId tid
 
 doGetBuildlogSize :: String -> String -> IO ()
 doGetBuildlogSize buildlog arch = do
diff --git a/src/Builds.hs b/src/Builds.hs
--- a/src/Builds.hs
+++ b/src/Builds.hs
@@ -45,13 +45,13 @@
 capitalize "" = ""
 capitalize (h:t) = toUpper h : t
 
-data Details = DetailDefault | Detailed | DetailedTasks
+data Details = Detailed | DetailedTasks
   deriving Eq
 
-buildsCmd :: Maybe String -> Maybe UserOpt -> Int -> [BuildState]
-          -> Maybe Tasks.BeforeAfter -> Maybe String -> Details
-          -> Maybe Tasks.Select -> Bool -> BuildReq -> IO ()
-buildsCmd mhub museropt limit !states mdate mtype details minstall debug buildreq = do
+buildsCmd :: Maybe String -> Maybe UserOpt -> Maybe Int -> [BuildState]
+          -> Maybe Tasks.BeforeAfter -> Maybe String -> Maybe Details
+          -> Maybe Select -> Bool -> BuildReq -> IO ()
+buildsCmd mhub museropt mlimit !states mdate mtype mdetails minstall debug buildreq = do
   when (hub /= fedoraKojiHub && museropt == Just UserSelf) $
     error' "--mine currently only works with Fedora Koji: use --user instead"
   tz <- getCurrentTimeZone
@@ -63,7 +63,7 @@
                     then InfoID (read bld)
                     else InfoString bld
       mbld <- getBuild hub bldinfo
-      whenJust (mbld >>= maybeBuildResult) $ printBuild hub tz details debug minstall
+      whenJust (mbld >>= maybeBuildResult) $ printBuild hub tz mdetails debug minstall
     BuildPackage pkg -> do
       when (head pkg == '-') $
         error' $ "bad combination: not a package: " ++ pkg
@@ -75,21 +75,21 @@
         Just pkgid -> do
           query <- setupQuery
           let fullquery = [("packageID", ValueInt pkgid),
-                          commonBuildQueryOptions limit] ++ query
+                          commonBuildQueryOptions mlimit] ++ query
           when debug $ print fullquery
           builds <- listBuilds hub fullquery
           when debug $ mapM_ pPrintCompact builds
-          if details /= DetailDefault || length builds == 1
-            then mapM_ (printBuild hub tz details debug minstall) $ mapMaybe maybeBuildResult builds
+          if isJust mdetails || length builds == 1
+            then mapM_ (printBuild hub tz mdetails debug minstall) $ mapMaybe maybeBuildResult builds
             else mapM_ putStrLn $ mapMaybe (shortBuildResult tz) builds
     _ -> do
       query <- setupQuery
-      let fullquery = query ++ [commonBuildQueryOptions limit]
+      let fullquery = query ++ [commonBuildQueryOptions mlimit]
       when debug $ print fullquery
       builds <- listBuilds hub fullquery
       when debug $ mapM_ pPrintCompact builds
-      if details /= DetailDefault || length builds == 1
-        then mapM_ (printBuild hub tz details debug minstall) $ mapMaybe maybeBuildResult builds
+      if isJust mdetails || length builds == 1
+        then mapM_ (printBuild hub tz mdetails debug minstall) $ mapMaybe maybeBuildResult builds
         else mapM_ putStrLn $ mapMaybe (shortBuildResult tz) builds
   where
     hub = maybe fedoraKojiHub hubURL mhub
@@ -99,7 +99,7 @@
       nvr <- lookupStruct "nvr" bld
       state <- readBuildState <$> lookupStruct "state" bld
       let date =
-            case lookupBuildTimes bld of
+            case lookupStartEndTimes bld of
               Nothing -> ""
               Just (start,mend) ->
                 compactZonedTime tz $ fromMaybe start mend
@@ -157,23 +157,25 @@
                _buildId :: Int,
                mbuildTaskId :: Maybe Int,
                _buildStartTime :: UTCTime,
-               mbuildEndTime :: Maybe UTCTime
+               mbuildEndTime :: Maybe UTCTime,
+               _buildOwner :: String
               }
 
 maybeBuildResult :: Struct -> Maybe BuildResult
 maybeBuildResult st = do
-  (start,mend) <- lookupBuildTimes st
+  (start,mend) <- lookupStartEndTimes st
   buildid <- lookupStruct "build_id" st
   -- buildContainer has no task_id
   let mtaskid = lookupStruct "task_id" st
   state <- getBuildState st
   nvr <- lookupStruct "nvr" st >>= maybeNVR
+  owner <- lookupStruct "owner_name" st
   return $
-    BuildResult nvr state buildid mtaskid start mend
+    BuildResult nvr state buildid mtaskid start mend owner
 
-printBuild :: String -> TimeZone -> Details -> Bool -> Maybe Tasks.Select
+printBuild :: String -> TimeZone -> Maybe Details -> Bool -> Maybe Select
            -> BuildResult -> IO ()
-printBuild hub tz details debug minstall build = do
+printBuild hub tz mdetails debug minstall build = do
   putStrLn ""
   let mendtime = mbuildEndTime build
   time <- maybe getCurrentTime return mendtime
@@ -181,24 +183,24 @@
   when (buildState build == BuildComplete) $
     putStrLn $ buildOutputURL hub $ buildNVR build
   whenJust (mbuildTaskId build) $ \taskid -> do
-    when (details == DetailedTasks) $ do
+    when (mdetails == Just DetailedTasks) $ do
       putStrLn ""
-      Tasks.tasksCmd (Just hub) (Tasks.QueryOpts Nothing 7 [] [] Nothing Nothing False Nothing) False False False Nothing (Tasks.Parent taskid)
+      Tasks.tasksCmd (Just hub) (Tasks.QueryOpts Nothing (Just 7) [] [] Nothing Nothing False Nothing) Nothing False False Nothing minstall (Tasks.ChildrenOf taskid)
     whenJust minstall $ \installopts -> do
       putStrLn ""
       installCmd False debug No (Just hub) Nothing False False False Nothing [] Nothing Nothing installopts Nothing ReqNVR [showNVR (buildNVR build)]
 
 formatBuildResult :: String -> Bool -> TimeZone -> BuildResult -> [String]
-formatBuildResult hub ended tz (BuildResult nvr state buildid mtaskid start mendtime) =
-  [ showNVR nvr +-+ show state
+formatBuildResult hub ended tz (BuildResult nvr state buildid mtaskid start mendtime owner) =
+  [ showNVR nvr +-+ show state +-+ '(' : owner ++ ")"
   , buildinfoUrl hub buildid]
   ++ [Tasks.taskinfoUrl hub taskid | Just taskid <- [mtaskid]]
-  ++ [formatLocalTime True tz start]
+  ++ [formatLocalTime StartEvent tz start]
   ++
   case mendtime of
     Nothing -> []
     Just end ->
-      [formatLocalTime False tz end | ended]
+      [formatLocalTime CompletionEvent tz end | ended]
 #if MIN_VERSION_time(1,9,1)
       ++
       let dur = diffUTCTime end start
@@ -232,4 +234,4 @@
   mbld <- kojiLatestBuild hub tag pkg
   when debug $ print mbld
   tz <- getCurrentTimeZone
-  whenJust (mbld >>= maybeBuildResult) $ printBuild hub tz Detailed debug Nothing
+  whenJust (mbld >>= maybeBuildResult) $ printBuild hub tz (Just Detailed) debug Nothing
diff --git a/src/Common.hs b/src/Common.hs
--- a/src/Common.hs
+++ b/src/Common.hs
@@ -4,13 +4,15 @@
   commonQueryOptions,
   commonBuildQueryOptions,
   webUrl,
-  getBuildState
+  getBuildState,
+  lookupArch
   )
 where
 
+import Control.Applicative ((<|>))
 import Data.List.Extra (dropSuffix, isPrefixOf)
 import Distribution.Koji (fedoraKojiHub, Value(..), Struct, BuildState,
-                          readBuildState)
+                          lookupStruct, readBuildState)
 import SimpleCmd (error')
 
 -- mbox kojihub is locked
@@ -29,17 +31,22 @@
   then hub
   else error' $ "unknown hub: try " ++ show knownHubs
 
-commonQueryOptions :: Int -> String -> [(String, Value)]
-commonQueryOptions limit order =
-  [("limit",ValueInt limit),
-   ("order",ValueString order)]
+commonQueryOptions :: Maybe Int -> String -> [(String, Value)]
+commonQueryOptions mlimit order =
+  [("limit",ValueInt limit) | Just limit <- [mlimit]] ++
+  [ ("order",ValueString order)]
 
-commonBuildQueryOptions :: Int -> (String, Value)
-commonBuildQueryOptions limit =
-  ("queryOpts", ValueStruct (commonQueryOptions limit "-build_id"))
+commonBuildQueryOptions :: Maybe Int -> (String, Value)
+commonBuildQueryOptions mlimit =
+  ("queryOpts", ValueStruct (commonQueryOptions mlimit "-build_id"))
 
 webUrl :: String -> String
 webUrl = dropSuffix "hub"
 
 getBuildState :: Struct -> Maybe BuildState
 getBuildState st = readBuildState <$> lookup "state" st
+
+-- noarch build tasks usually have arch
+-- see also https://pagure.io/koji/issue/4098
+lookupArch :: Struct -> Maybe String
+lookupArch st = lookupStruct "label" st <|> lookupStruct "arch" st
diff --git a/src/Find.hs b/src/Find.hs
--- a/src/Find.hs
+++ b/src/Find.hs
@@ -10,17 +10,19 @@
 
 import Data.Char ( isDigit, isAsciiLower, isAsciiUpper )
 import Data.List.Extra ((\\), dropSuffix, isSuffixOf)
+import Data.Maybe (listToMaybe)
 import Distribution.Koji
     ( BuildState(BuildBuilding, BuildFailed, BuildComplete),
       TaskState(TaskOpen, TaskFailed, TaskClosed) )
 import SimpleCmd (error', (+-+))
 
 import qualified Builds
+import Install (Select(PkgsReq))
 import qualified Tasks
 import User ( UserOpt(User, UserSelf) )
 
 data Words = Mine | Limit | Failure | Complete | Current | Build | Detail
-           | Install | Tail | NoTail | Hwinfo | Arch
+           | Install | Tail | NoTail | Hwinfo | Arch | Debug
   deriving (Enum,Bounded)
 
 findWords :: Words -> [String]
@@ -37,7 +39,8 @@
 findWords Tail = ["tail"]
 findWords NoTail = ["notail"]
 findWords Hwinfo = ["hwinfo"]
-findWords Arch = ["x86_64", "aarch64", "ppc64le", "s390x", "i686", "armv7hl"]
+findWords Debug = ["debug", "dbg"]
+findWords Arch = ["x86_64", "aarch64", "ppc64le", "s390x", "i686", "armv7hl", "noarch"]
 
 wordsList :: ([String] -> String) -> [String]
 wordsList f =
@@ -50,10 +53,10 @@
 -- FIXME: methods
 -- FIXME: mlt (or mlft)
 -- FIXME: separate last and latest?
-findCmd :: Maybe String -> Bool -> [String] -> IO ()
-findCmd _ _ [] = error' $ "find handles these words:\n\n" ++
+findCmd :: Maybe String -> [String] -> IO ()
+findCmd _ [] = error' $ "find handles these words:\n\n" ++
                   unlines (wordsList unwords)
-findCmd mhub debug args = do
+findCmd mhub args = do
   let user = if hasWord Mine
              then Just UserSelf
              else case filter ("'s" `isSuffixOf`) args of
@@ -63,7 +66,7 @@
                             unwords more
       archs = if hasWord Arch
               then filter (`elem` findWords Arch) args else []
-      defaultlimit = if hasWord Limit then 1 else 10
+      defaultlimit = Just $ if hasWord Limit then 1 else 10
       failure = hasWord Failure
       complete = hasWord Complete
       current = hasWord Current
@@ -73,15 +76,16 @@
       tail' = hasWord Tail
       notail = hasWord NoTail
       hwinfo = hasWord Hwinfo
+      debug = hasWord Debug
       (limit,mpkg) =
         case removeUsers (args \\ allWords) of
           [] -> (defaultlimit, Nothing)
-          [num] | all isDigit num && not (hasWord Limit) ->
-                  let number = read num
-                  in if number < 1000
-                     then (number, Nothing)
-                     else error' $ "is" +-+ num +-+
-                          "an id? Use 'tasks' for very large limits"
+          (num:pkgs) | all isDigit num  && length pkgs < 2 ->
+                       let number = read num
+                       in if number < 1000
+                       then (Just number, listToMaybe pkgs)
+                       else error' $ "is" +-+ num +-+
+                          "an id? Use 'tasks' command for very large limits"
           -- FIXME allow pattern?
           [pkg] | all isPkgNameChar pkg -> (defaultlimit, Just pkg)
           other ->
@@ -89,20 +93,20 @@
             "you can only specify one package - too many unknown words: " ++
             unwords other
       installation = if install
-                     then Just (Tasks.PkgsReq [] [] [] [])
+                     then Just (PkgsReq [] [] [] [])
                      else Nothing
   if build
     then
     let states = [BuildFailed|failure] ++ [BuildComplete|complete] ++
                  [BuildBuilding|current]
         buildreq = maybe Builds.BuildQuery Builds.BuildPackage mpkg
-        detailed = if detail then Builds.Detailed else Builds.DetailDefault
+        detailed = if detail then Just Builds.Detailed else Nothing
     in Builds.buildsCmd mhub user limit states Nothing (Just "rpm") detailed installation debug buildreq
     else
     let states = [TaskFailed|failure] ++ [TaskClosed|complete] ++
                  [TaskOpen|current]
         taskreq = maybe Tasks.TaskQuery Tasks.Package mpkg
-    in Tasks.tasksCmd mhub (Tasks.QueryOpts user limit states archs Nothing Nothing debug Nothing) detail ((tail' || failure) && not notail) hwinfo Nothing taskreq
+    in Tasks.tasksCmd mhub (Tasks.QueryOpts user limit states archs Nothing Nothing debug Nothing) (if detail then Just Tasks.Detailed else Nothing) ((tail' || failure) && not notail) hwinfo Nothing installation taskreq
   where
     hasWord :: Words -> Bool
     hasWord word = any (`elem` findWords word) args
diff --git a/src/Install.hs b/src/Install.hs
--- a/src/Install.hs
+++ b/src/Install.hs
@@ -97,7 +97,7 @@
 -- FIXME autodetect NVR, NV, etc
 -- FIXME support buildid
 -- FIXME specify tag or task
--- FIXME support --latest
+-- FIXME support --latest (last build)
 -- FIXME support enterprise builds
 -- FIXME --debuginfo
 -- FIXME --delete after installing
@@ -169,7 +169,7 @@
                 unless (dryrun || null dlRpms) $ do
                   bld <- kojiGetBuild' huburl nvr
                   -- FIXME should be NVRA ideally
-                  downloadRpms debug checkremotetime (strictLookupTimes lookupBuildTimes bld) subdir (buildURL nvr) dlRpms
+                  downloadRpms debug checkremotetime (lookupStartEndTimes' bld) subdir (buildURL nvr) dlRpms
                 -- FIXME once we check file size - can skip if no downloads
                   printDlDir
               return (subdir,dlRpms)
@@ -209,7 +209,9 @@
                     "build" -> do
                       when debug $ mapM_ print taskinfo >> putStrLn ""
                       Koji.getTaskChildren huburl taskid True
-                    "buildArch" -> return [taskinfo]
+                    "buildArch" -> do
+                      when debug $ print taskinfo >> putStrLn ""
+                      return [taskinfo]
                     _ -> error' $ "unsupport method: " ++ method
   totalarchs <- getArchs archs
   let (archtid,archtask) =
@@ -241,7 +243,7 @@
       when debug $ mapM_ printInstalled dlRpms
       let subdir = show archtid
       unless (dryrun || null dlRpms) $ do
-        downloadRpms debug checkremotetime (strictLookupTimes lookupTaskTimes archtask) subdir (taskRPMURL archtid) dlRpms
+        downloadRpms debug checkremotetime (lookupStartEndTimes' archtask) subdir (taskRPMURL archtid) dlRpms
         printDlDir
       return (subdir,dlRpms)
   where
@@ -268,7 +270,7 @@
 getArchs :: [String] -> IO [String]
 getArchs archs =
   case archs of
-    [] -> cmdLines "rpm" ["--eval", "%{_arch}"]
+    [] -> ("noarch" :) <$> cmdLines "rpm" ["--eval", "%{_arch}"]
     ars -> return ars
 
 data Existence = ExistingNVR | ChangedNVR | NotInstalled
@@ -431,8 +433,8 @@
                   then id
                   else (("pattern", ValueString (if full then pkgpat else dropSuffix "*" pkgpat ++ "*" ++ disttag ++ "*")) :))
                  [("packageID", ValueInt pkgid),
-                  commonBuildQueryOptions
-                  (if listmode && not latest || oldkoji then 20 else 1)]
+                  commonBuildQueryOptions $
+                  Just (if listmode && not latest || oldkoji then 20 else 1)]
       when debug $ print opts
       nvrs <- mapMaybe (lookupStruct "nvr") <$> Koji.listBuilds hub opts
       if null nvrs
diff --git a/src/Main.hs b/src/Main.hs
--- a/src/Main.hs
+++ b/src/Main.hs
@@ -29,14 +29,16 @@
       buildsCmd
       <$> hubOpt
       <*> optional (userOpt False)
-      <*> (flagWith' 1 'L' "latest" "Latest build" <|>
-           optionalWith auto 'l' "limit" "INT" "Maximum number of builds to show [default: 10]" 10)
+      <*> (flagWith' (Just 1) 'L' "latest" "Latest build" <|>
+           flagWith' Nothing 'U' "unlimited" "No limit on number of results" <|>
+           Just <$> optionalWith auto 'l' "limit" "INT" "Maximum number of builds to show [default: 20]" 20)
       <*> many (parseBuildState' <$> strOptionWith 's' "state" "STATE" "Filter builds by state (building,complete,deleted,fail(ed),cancel(ed)")
       <*> optional (Before <$> strOptionWith 'B' "before" "TIMESTAMP" "Builds completed before timedate [default: now]" <|>
                     After <$> strOptionWith 'F' "from" "TIMESTAMP" "Builds completed after timedate")
       <*> (fmap normalizeBuildType <$> optional (strOptionWith 'T' "type" "TYPE" ("Select builds by type: " ++ intercalate "," kojiBuildTypes)))
-      <*> (flagWith' Detailed 'd' "details" "Show more build details" <|>
-           flagWith DetailDefault DetailedTasks 't' "tasks" "Show details and tasks")
+      <*> optional
+      (flagWith' Builds.Detailed 'd' "details" "Show more build details" <|>
+       flagWith' Builds.DetailedTasks 't' "tasks" "Show details and tasks")
       <*> optional (installArgs <$> strOptionWith 'i' "install" "INSTALLOPTS" "Install the package with 'install' options")
       <*> switchWith 'D' "debug" "Pretty-print raw XML result"
       <*> (BuildBuild <$> strOptionWith 'b' "build" "NVR/BUILDID" "Show build" <|>
@@ -49,13 +51,14 @@
       tasksCmd
       <$> hubOpt
       <*> queryOpts False "buildArch"
-      <*> switchWith 'd' "details" "Show more details of builds"
+      <*> optional
+      (flagWith' Tasks.Detailed 'd' "details" "Show more task details" <|>
+       flagWith' Tasks.Concise 'c' "concise" "Compact task output")
       -- FIXME error if integer (eg mistakenly taskid)
       <*> switchWith 'T' "tail" "Fetch the tail of build.log"
       <*> switchLongWith "hw-info" "Fetch hw_info.log"
       <*> optional (strOptionWith 'g' "grep" "STRING" "Filter matching log lines")
-      -- -- FIXME any way to pass --help to install?
-      -- <*> optional (installArgs <$> strOptionWith 'i' "install" "INSTALLOPTS" "Install the package with 'install' options")
+      <*> optional (installArgs <$> strOptionWith 'i' "install" "INSTALLOPTS" "Install the package with 'install' options")
       <*> taskReqOpt
     , Subcommand "latest"
       "Query latest Koji build for tag" $
@@ -103,7 +106,6 @@
        intercalate ", " (wordsList head) ++ "]") $
       findCmd
       <$> hubOpt
-      <*> switchWith 'D' "debug" "Debug output including XML results"
       <*> many (strArg "PHRASE")
     ]
   where
@@ -172,8 +174,9 @@
     queryOpts mine defaultMethod =
       QueryOpts
       <$> optional (userOpt mine)
-      <*> (flagWith' 1 'L' "latest" "Latest build or task" <|>
-           optionalWith auto 'l' "limit" "INT" "Maximum number of tasks to show [default: 10]" 10)
+      <*> (flagWith' (Just 1) 'L' "latest" "Latest build or task" <|>
+           flagWith' Nothing 'U' "unlimited" "No limit on number of results" <|>
+           Just <$> optionalWith auto 'l' "limit" "INT" "Maximum number of tasks to show [default: 20]" 20)
       <*> many (fmap parseTaskState' $! strOptionWith 's' "state" "STATE" "Filter tasks by state (open,close(d),cancel(ed),fail(ed),assigned,free)")
       <*> many archOpt
       <*> optional (Before <$> strOptionWith 'B' "before" "TIMESTAMP" "Tasks completed before timedate [default: now]" <|>
@@ -186,5 +189,7 @@
     taskReqOpt =
       Build <$> strOptionWith 'b' "build" "BUILD" "List child tasks of build"
       <|> Pattern <$> strOptionWith 'p' "pattern" "NVRPAT" "Build tasks of matching pattern"
+      <|> ChildrenOf <$> optionLongWith auto "children" "TASKID" "Children tasks of parent"
+      <|> ParentOf <$> optionLongWith auto "parent" "TASKID" "Parent of task"
       <|> argumentWith (maybeReader readTaskReq) "PACKAGE|TASKID"
       <|> pure TaskQuery
diff --git a/src/Progress.hs b/src/Progress.hs
--- a/src/Progress.hs
+++ b/src/Progress.hs
@@ -33,9 +33,10 @@
 import Data.Text (Text)
 import qualified Data.Text as T
 import Distribution.Koji
+import Safe (maximumMay)
 import SimpleCmd
-import System.FilePath ((</>))
 
+import Common (lookupArch)
 import Tasks
 import Time
 import Utils
@@ -44,7 +45,6 @@
 -- FIXME if failure and no more, then stop
 -- FIXME catch HTTP exception for connection timeout
 -- FIXME pick up new user builds (if none specified)
--- FIXME noarch tasks shown with build arch
 progressCmd :: Bool -> QueryOpts -> TaskReq -> IO ()
 progressCmd modules queryopts@QueryOpts{..} taskreq = do
   tasks <- do
@@ -113,9 +113,10 @@
 
 initialBuildTask :: Struct -> IO BuildTask
 initialBuildTask taskinfo = do
-  let tid = case lookupStruct "id" taskinfo of
-              Just tid' -> TaskId tid'
-              Nothing -> error' $ "no taskid found for:" ++ show taskinfo
+  let tid =
+        case lookupStruct "id" taskinfo of
+          Just tid' -> TaskId tid'
+          Nothing -> error' $ "no taskid found for:" ++ show taskinfo
       parent =
         case lookupStruct "method" taskinfo :: Maybe String of
           Nothing -> error' $ "no method found for " ++ displayID tid
@@ -130,7 +131,7 @@
               -- https://koji.fedoraproject.org/koji/taskinfo?taskID=104446426
               -- https://kojipkgs.fedoraproject.org//work/tasks/6426/104446426/
               _ -> error' $ "unsupported method: " ++ method
-  children <- sortOn (\t -> lookupStruct "arch" t :: Maybe String) <$>
+  children <- sortOn lookupArch <$>
                       kojiGetTaskChildren fedoraKojiHub parent True
   let start =
         case lookupTime CreateEvent taskinfo of
@@ -199,7 +200,7 @@
               (open,closed) = partition (\tis -> getTaskState (taskInfo tis) `elem` map Just openTaskStates) news
               mlargest = if not (any (\tis -> lookupStruct "method" (taskInfo tis) /= Just ("buildSRPMFromSCM" :: String)) closed)
                          then Nothing
-                         else Just $ maximum $ mapMaybe (\t -> taskStatus t >>= tstLog <&> logSize) closed
+                         else maximumMay $ mapMaybe (\t -> taskStatus t >>= tstLog <&> logSize) closed
               mbiggest = max mlargest msize
           if null open
             then runProgress (BuildTask tid start mend mbiggest [])
@@ -212,6 +213,8 @@
 
 buildlogSize :: Bool -> Int -> TaskInfoStatus -> IO TaskInfoStatuses
 buildlogSize debug n (TaskInfoStatus task moldstatus) = do
+  let tid = fromJust (lookupStruct "id" task)
+      buildlog = buildlogUrlfromTaskId tid
   when debug $ putStrLn buildlog
   exists <- if isJust moldstatus
             then return True
@@ -221,7 +224,7 @@
   (msize,mtime) <- if exists
                    then httpFileSizeTime' buildlog
                    else return (Nothing,Nothing)
-  when debug $ print (mtime,moldstatus)
+  when debug $ print (msize,mtime,moldstatus)
   if (mtime == fmap logTime moldlog || isNothing mtime) && n < 5
     then buildlogSize debug (n+1) (TaskInfoStatus task moldstatus)
     else
@@ -229,12 +232,6 @@
             (fromInteger <$> msize, mtime),
             moldstatus)
   where
-    tid = show $ fromJust (readID' task)
-    buildlog = "https://kojipkgs.fedoraproject.org/work/tasks" </> lastFew </> tid </> "build.log"
-    lastFew =
-      let few = dropWhile (== '0') $ takeEnd 4 tid in
-        if null few then "0" else few
-
     moldlog = moldstatus >>= tstLog :: Maybe LogStatus
 
     waitDelay ::  IO ()
@@ -271,7 +268,7 @@
   threadDelay (fromEnum (fromIntegral m :: Micro))
 
 
-data TaskOutput = TaskOut {_outArch :: Text,
+data TaskOutput = TaskOut {_outArch :: String,
                            moutSize :: Maybe Int,
                            moutSizeStep :: Maybe Int,
                            outSizeChanged :: Bool,
@@ -287,15 +284,15 @@
 printLogStatuses header tz tss =
   let (mxsi, mxsp, taskoutputs) = (formatSize . map taskOutput) tss
   in
-    unless (null taskoutputs) $ do
+    unless (null taskoutputs) $
     when (any (\t -> outTimeChanged t || outSizeChanged t || outStateChanged t) taskoutputs) $ do
-      header
-      mapM_ (printTaskOut mxsi mxsp) taskoutputs
-      putChar '\n'
+    header
+    mapM_ (printTaskOut mxsi mxsp) taskoutputs
+    putChar '\n'
   where
     printTaskOut :: Int64 -> Int64 -> TaskOutput -> IO ()
     printTaskOut maxsize maxspd (TaskOut arch msize msizediff _sizechanged mtime mtimediff _timechanged state _statechanged mthd mduration) =
-      fprintLn (rpadded 8 ' ' stext %
+      fprintLn (rpadded 8 ' ' string %
                 lpadded (max 6 (maxsize+2)) ' ' (optioned commas) % "kB" %
                 " " %
                 optioned (parenthesised string % " ") %
@@ -339,7 +336,7 @@
           mstate = getTaskState task
       in
         let method = maybeVal "method not found" (lookupStruct "method") task :: Text
-            arch = maybeVal "arch not found" (lookupStruct "arch") task :: Text
+            arch = maybeVal "arch not found" lookupArch task
             sizediff = liftM2 (-) size oldsize
             timediff = if time == oldtime
                        then Nothing
@@ -358,6 +355,7 @@
   user <- case muser of
             Just user -> return user
             Nothing -> do
+              -- FIXME test for klist
               mfasid <- (removeSuffix "@FEDORAPROJECT.ORG" <$>) . find ("@FEDORAPROJECT.ORG" `isSuffixOf`) . words <$> cmd "klist" ["-l"]
               case mfasid of
                 Just fas -> return fas
diff --git a/src/Tasks.hs b/src/Tasks.hs
--- a/src/Tasks.hs
+++ b/src/Tasks.hs
@@ -7,13 +7,13 @@
   TaskReq(..),
   BeforeAfter(..),
   QueryOpts(..),
+  Details(..),
   tasksCmd,
   getTasks,
   parseTaskState',
   kojiMethods,
   fedoraKojiHub,
   taskinfoUrl,
-  Select(PkgsReq)
   )
 where
 
@@ -43,7 +43,8 @@
 import User
 import Utils
 
-data TaskReq = Task Int | Parent Int | Build String | Package String
+data TaskReq = Task Int | ChildrenOf Int | ParentOf Int
+             | Build String | Package String
              | TaskQuery | Pattern String
 
 data TaskFilter = TaskPackage String | TaskNVR String
@@ -62,16 +63,18 @@
   TaskResult {taskPackage :: Either String NVR,
               taskArch :: String,
               taskMethod :: String,
-              _taskState :: TaskState,
+              taskState :: TaskState,
               _mtaskParent :: Maybe Int,
               taskId :: Int,
+              _taskCreateTime :: UTCTime,
               _mtaskStartTime :: Maybe UTCTime,
-              mtaskEndTime :: Maybe UTCTime
+              mtaskEndTime :: Maybe UTCTime,
+              _mtaskOwner :: Maybe String
              }
 
 data QueryOpts = QueryOpts {
   qmUserOpt :: Maybe UserOpt,
-  qLimit :: Int,
+  qLimit :: Maybe Int,
   qStates :: ![TaskState],
   qArchs :: ![String],
   qmDate :: Maybe BeforeAfter,
@@ -79,24 +82,30 @@
   qDebug :: Bool,
   qmFilter :: Maybe TaskFilter}
 
+data Details = Detailed | Concise
+  deriving Eq
+
+-- FIXME 'koji-tool tasks <taskid> -s fail -m buildarch' should not print build task
 -- FIXME short output option
 -- --sibling
 -- FIXME --tail-size option (eg more that 4000B)
 -- FIXME --output-fields
 -- FIXME default to 'build' for install or try 'build' after 'buildarch'?
--- FIXME parent tasks need not have limit
 -- FIXME `-# 2` etc to select second result
-tasksCmd :: Maybe String -> QueryOpts -> Bool -> Bool -> Bool -> Maybe String
-         -> TaskReq -> IO ()
-tasksCmd mhub queryopts@QueryOpts{..} details tail' hwinfo mgrep taskreq = do
+tasksCmd :: Maybe String -> QueryOpts -> Maybe Details -> Bool -> Bool
+         -> Maybe String -> Maybe Select -> TaskReq -> IO ()
+tasksCmd mhub queryopts@QueryOpts{..} mdetails tail' hwinfo mgrep minstall taskreq = do
   when (hub /= fedoraKojiHub && qmUserOpt == Just UserSelf) $
     error' "--mine currently only works with Fedora Koji: use --user instead"
   tz <- getCurrentTimeZone
   tasks <- getTasks tz hub queryopts taskreq
   when qDebug $ mapM_ pPrintCompact tasks
-  let exact = length tasks == 1
-      detailed = details || exact
-  (mapM_ (printTask detailed tz) . filterResults . mapMaybe maybeTaskResult) tasks
+  let details =
+        case mdetails of
+          Nothing ->
+            if length tasks == 1 then Detailed else Concise
+          Just detail -> detail
+  (mapM_ (printTask details tz) . filterResults . mapMaybe maybeTaskResult) tasks
   where
     hub = maybe fedoraKojiHub hubURL mhub
 
@@ -115,39 +124,46 @@
         isNVR _ (Left _) = False
         isNVR nvr (Right nvr') = nvr `isPrefixOf` showNVR nvr'
 
-    printTask :: Bool -> TimeZone -> TaskResult -> IO ()
-    printTask detailed tz task = do
+    printTask :: Details -> TimeZone -> TaskResult -> IO ()
+    printTask details tz task = do
       let mendtime = mtaskEndTime task
       mtime <- if isNothing  mendtime
                  then Just <$> getCurrentTime
                  else return Nothing
-      if detailed
+      if details == Detailed
         then do
         putStrLn ""
         -- FIX for parent/build method show children (like we do with taskid)
         (mapM_ putStrLn . formatTaskResult hub mtime tz) task
         if taskMethod task == "build"
           then do
-          getTasks tz hub queryopts (Parent $ taskId task) >>=
-            mapM_ (printTask detailed tz) . mapMaybe maybeTaskResult
-          else buildlogSize qDebug tail' hwinfo mgrep hub task
+          when (mdetails == Just Detailed) $
+            getTasks tz hub queryopts (ChildrenOf $ taskId task) >>=
+            mapM_ (printTask details tz) . mapMaybe maybeTaskResult
+          else buildlogSize qDebug tz tail' hwinfo mgrep hub task
         else do
         (putStrLn . compactTaskResult hub tz) task
         when (tail' || hwinfo || isJust mgrep) $
-          buildlogSize qDebug tail' hwinfo mgrep hub task
+          buildlogSize qDebug tz tail' hwinfo mgrep hub task
+      whenJust minstall $ \installopts -> do
+        putStrLn ""
+        installCmd False qDebug No (Just hub) Nothing False False False Nothing [] Nothing Nothing installopts Nothing ReqName [show (taskId task)]
 
 maybeTaskResult :: Struct -> Maybe TaskResult
 maybeTaskResult st = do
-  arch <- lookupStruct "arch" st
-  let mstart_time = lookupTime CreateEvent st
-      mend_time = lookupTime CompletionEvent st
+  arch <- lookupArch st
+  let (create,mstart,mend) = lookupTaskTimes st
   taskid <- lookupStruct "id" st
   method <- lookupStruct "method" st
   state <- getTaskState st
   let pkgnvr = kojiTaskRequestNVR st
       mparent' = lookupStruct "parent" st :: Maybe Int
+  -- FIXME filter long names like
+  -- "koschei/koschei-backend01.iad2.fedoraproject.org"
+  -- "bpeck/jenkins-continuous-infra.apps.ci.centos.org"
+      mowner = lookupStruct "owner_name" st
   return $
-    TaskResult pkgnvr arch method state mparent' taskid mstart_time mend_time
+    TaskResult pkgnvr arch method state mparent' taskid create mstart mend mowner
 
 pPrintCompact :: Struct -> IO ()
 pPrintCompact =
@@ -175,11 +191,11 @@
         error' "cannot use taskid together with filter"
       mtask <- kojiGetTaskInfo hub (TaskId taskid)
       case mtask of
-        Nothing -> error $ "taskid not found: " ++ show taskid
+        Nothing -> error $ "taskid not found:" +-+ show taskid
         Just task -> do
           when qDebug $ pPrintCompact task
           case maybeTaskResult task of
-            Nothing -> error' $ "failed to read task: " ++ show task
+            Nothing -> error' $ "failed to read task:" +-+ show task
             -- FIXME maybe should have way to list parent or children
             Just _res -> return [task]
     Build bld -> do
@@ -191,17 +207,17 @@
                       getBuild hub (InfoID (read bld))
                  else kojiGetBuildTaskID hub bld
       case mtaskid of
-        Just (TaskId taskid) -> getTasks tz hub queryopts $ Parent taskid
-        Nothing -> error' $ "no taskid found for build " ++ bld
+        Just (TaskId taskid) -> getTasks tz hub queryopts $ ChildrenOf taskid
+        Nothing -> error' $ "no taskid found for build" +-+ bld
     Package pkg -> do
       when (head pkg == '-') $
-        error' $ "bad combination: not a package " ++ pkg
+        error' $ "bad combination: not a package" +-+ pkg
       when (isJust qmDate || isJust qmFilter) $
         -- FIXME why not?
         error' "cannot use package together with timedate or filter"
       mpkgid <- getPackageID hub pkg
       case mpkgid of
-        Nothing -> error' $ "no package id found for " ++ pkg
+        Nothing -> error' $ "no package id found for" +-+ pkg
         Just pkgid -> do
           builds <- listBuilds hub
                     [("packageID", ValueInt pkgid),
@@ -211,8 +227,17 @@
             let mtaskid = (fmap TaskId . lookupStruct "task_id") bld
             case mtaskid of
               -- FIXME gives too many tasks (parent builds):
-              Just (TaskId taskid) -> getTasks tz hub queryopts $ Parent taskid
+              Just (TaskId taskid) -> getTasks tz hub queryopts {qLimit = Nothing} $ ChildrenOf taskid
               Nothing -> return []
+    ParentOf taskid -> do
+      mtask <- kojiGetTaskInfo hub (TaskId taskid)
+      case mtask of
+        Nothing -> error $ "taskid not found:" +-+ show taskid
+        Just task -> do
+          when qDebug $ pPrintCompact task
+          case lookupStruct "parent" task of
+            Nothing -> error' $ "no parent of" +-+ show taskid
+            Just tid -> getTasks tz hub queryopts {qLimit = Nothing} $ Task tid
     Pattern pat -> do
       let buildquery = [("pattern", ValueString pat),
                         commonBuildQueryOptions qLimit]
@@ -223,7 +248,7 @@
         forM builds $ \bld -> do
         let mtaskid = (fmap TaskId . lookupStruct "task_id") bld
         case mtaskid of
-          Just (TaskId taskid) -> getTasks tz hub queryopts $ Parent taskid
+          Just (TaskId taskid) -> getTasks tz hub (queryopts {qLimit = Nothing}) $ ChildrenOf taskid
           Nothing -> return []
     _ -> do
       query <- setupQuery
@@ -233,7 +258,7 @@
   where
     setupQuery = do
       case req of
-        Parent parent ->
+        ChildrenOf parent ->
           return $ ("parent", ValueInt parent) : commonParams
         _ -> do
           mdatestring <-
@@ -271,11 +296,11 @@
             let timedate = getTimedate beforeAfter
             in case words timedate of
                  [t] | t `elem` ["hour", "day", "week", "month", "year"] ->
-                       "last " ++ t
+                       "last" +-+ t
                  [t] | t `elem` ["today", "yesterday"] ->
                        t ++ " 00:00"
                  [t] | any (lower t `isPrefixOf`) ["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"] ->
-                       "last " ++ t ++ " 00:00"
+                       "last" +-+ t ++ " 00:00"
                  [n,_unit] | all isDigit n -> timedate ++ " ago"
                  _ -> timedate
 
@@ -285,7 +310,7 @@
 
 -- FIXME option to hide url (take terminal width into consideration?)
 compactTaskResult :: String -> TimeZone -> TaskResult -> String
-compactTaskResult hub tz (TaskResult pkg arch method state _mparent taskid mstart mend) =
+compactTaskResult hub tz (TaskResult pkg arch method state _mparent taskid _create mstart mend _mowner) =
   let time =
         case mend of
           Just end -> compactZonedTime tz end
@@ -298,8 +323,6 @@
     [show state,
      showPackage pkg ++ if method == "buildArch" then '.' : arch ++ replicate (8 - length arch) ' ' else ' ' : method]
 
-
--- FIXME show task owner
 formatTaskResult :: String -> Maybe UTCTime -> TimeZone -> TaskResult -> [String]
 formatTaskResult hub
 #if MIN_VERSION_time(1,9,1)
@@ -307,19 +330,21 @@
 #else
   _mtime
 #endif
-  tz (TaskResult pkg arch method state mparent taskid mstart mend) =
-  [ showPackage pkg ++ (if method == "buildArch" then '.' : arch else ' ' : method) +-+ show state
-  , taskinfoUrl hub taskid +-+ maybe "" (\p -> "(parent: " ++ show p ++ ")") mparent] ++
-  [formatLocalTime True tz start | Just start <- [mstart]] ++
-  [formatLocalTime False tz end | Just end <- [mend]]
+  tz (TaskResult pkg arch method state mparent taskid create mstart mend mowner) =
+  [ showPackage pkg ++ (if method == "buildArch" then '.' : arch else ' ' : method) +-+ show state +-+ maybe "" (\o -> '(' : o ++ ")") mowner
+  , taskinfoUrl hub taskid +-+ maybe "" (\p -> "(parent:" +-+ show p ++ ")") mparent
+  , formatLocalTime CreateEvent tz create] ++
+  [formatLocalTime StartEvent tz start | Just start <- [mstart]] ++
+  [formatLocalTime CompletionEvent tz end | Just end <- [mend]]
 #if MIN_VERSION_time(1,9,1)
-      ++
+    ++
+    ["delay:" +-+ renderDuration False dur | Just start <- [mstart], let dur = diffUTCTime start create]
+    ++
     case mtime of
       Just now ->
-        ["current duration: " ++ renderDuration False dur | Just start <- [mstart], let dur = diffUTCTime now start]
+        ["current duration:" +-+ renderDuration False dur | Just start <- [mstart], let dur = diffUTCTime now start]
       Nothing ->
-        ["duration: " ++ renderDuration False dur | Just start <- [mstart], Just end <- [mend], let dur = diffUTCTime end start]
-
+        ["duration:" +-+ renderDuration False dur | Just start <- [mstart], Just end <- [mend], let dur = diffUTCTime end start]
 #endif
 
 showPackage :: Either String NVR -> String
@@ -343,7 +368,7 @@
     "assigned" -> TaskAssigned
     "fail" -> TaskFailed
     "failed" -> TaskFailed
-    _ -> error' $! "unknown task state: " ++ s ++
+    _ -> error' $! "unknown task state:" +-+ s ++
          "\nknown states: free, open, closed, canceled, assigned, failed"
 
 data LogFile = BuildLog | RootLog | HWInfo
@@ -354,7 +379,7 @@
 outputUrl :: String -> TaskResult -> OutputLocation -> Maybe String
 outputUrl hub task loc =
   case loc of
-    WorkOutput -> Just $ taskOutputUrl task
+    WorkOutput -> Just $ worktaskDirUrlfromTaskID $ taskId task
     PackagesOutput ->
       case taskPackage task of
         Left _ -> Nothing
@@ -364,26 +389,23 @@
 findOutputURL :: String -> TaskResult -> IO (Maybe String)
 findOutputURL hub task =
   case outputUrl hub task PackagesOutput of
-    Just burl -> urlExistsOr (taskOutputUrl task) $
-                 urlExistsOr burl $ return Nothing
-    Nothing -> urlExistsOr (taskOutputUrl task) $ return Nothing
+    Just burl -> urlMayExist (worktaskDirUrlfromTaskID $ taskId task) <||>
+                 urlMayExist burl
+    Nothing -> urlMayExist (worktaskDirUrlfromTaskID $ taskId task)
   where
-    urlExistsOr :: String -> IO (Maybe String) -> IO (Maybe String)
-    urlExistsOr url alt = do
+    urlMayExist :: String -> IO (Maybe String)
+    urlMayExist url = do
       exists <- httpExists' url
-      if exists
-        then return $ Just url
-        else alt
-
-taskOutputUrl :: TaskResult -> String
-taskOutputUrl task =
-  "https://kojipkgs.fedoraproject.org/work/tasks" </> lastFew </> tid
-  where
-    tid = show (taskId task)
+      return $
+        if exists
+        then Just url
+        else Nothing
 
-    lastFew =
-      let few = dropWhile (== '0') $ takeEnd 4 tid
-      in if null few then "0" else few
+    mact1 <||> mact2 = do
+      ma1 <- mact1
+      if isJust ma1
+        then return ma1
+        else mact2
 
 tailLogUrl :: String -> Int -> LogFile -> String
 tailLogUrl hub taskid file =
@@ -394,35 +416,37 @@
 logFile BuildLog = "build.log"
 logFile HWInfo = "hw_info.log"
 
-buildlogSize :: Bool -> Bool -> Bool -> Maybe String -> String -> TaskResult
-             -> IO ()
-buildlogSize _debug tail' hwinfo mgrep hub task = do
+buildlogSize :: Bool -> TimeZone -> Bool -> Bool -> Maybe String -> String
+             -> TaskResult -> IO ()
+buildlogSize _debug tz tail' hwinfo mgrep hub task = do
   murl <- findOutputURL hub task
   whenJust murl $ \ url -> do
     let buildlog = url +/+ logFile BuildLog
     exists <- httpExists' buildlog
     if exists
       then do
-      putStr $ buildlog ++ " "
-      msize <- httpFileSize' buildlog
-      case msize of
-        Nothing -> putChar '\n'
-        Just size -> do
-          fprintLn ("(" % commas % "kB)") (size `div` 1000)
-          -- FIXME check if short build.log ends with srpm
-          file <-
-            if hwinfo
+      putStr buildlog
+      (msize,mtime) <- httpFileSizeTime' buildlog
+      whenJust msize $ \size -> do
+        fprint (" (" % commas % "kB)") (size `div` 1000)
+        when (taskState task == TaskOpen) $
+          whenJust mtime $ \time ->
+          putStr $ " (" ++ compactZonedTime tz time ++ ")"
+        putChar '\n'
+        -- FIXME check if short build.log ends with srpm
+        file <-
+          if hwinfo
+          then do
+            putStr $ url +/+ logFile HWInfo
+            return HWInfo
+          else
+            -- for buildroot failure build.log could be ~3082 bytes
+            if size < 4000
             then do
-              putStrLn $ url +/+ logFile HWInfo
-              return HWInfo
-            else
-              -- for buildroot failure build.log could be ~3082 bytes
-              if size < 4000
-              then do
-                putStrLn $ url +/+ logFile RootLog
-                return RootLog
-              else return BuildLog
-          when (tail' || hwinfo || isJust mgrep) $ displayLog url file
+              putStr $ url +/+ logFile RootLog
+              return RootLog
+            else return BuildLog
+        when (tail' || hwinfo || isJust mgrep) $ displayLog url file
       else do
       let rootlog = url +/+ logFile RootLog
       whenM (httpExists' rootlog) $
diff --git a/src/Time.hs b/src/Time.hs
--- a/src/Time.hs
+++ b/src/Time.hs
@@ -4,9 +4,9 @@
   compactZonedTime,
   TimeEvent(..),
   lookupTime,
-  lookupBuildTimes,
+  lookupStartEndTimes,
+  lookupStartEndTimes',
   lookupTaskTimes,
-  strictLookupTimes,
   durationOfTask,
   formatLocalTime,
   renderDuration,
@@ -46,39 +46,40 @@
         lookupStruct (ev ++ "_time") str >>=
         parseTimeM False defaultTimeLocale "%Y-%m-%d %H:%M:%S%Q%EZ"
 
-lookupTaskTimes :: Struct -> Maybe (UTCTime, Maybe UTCTime)
-lookupTaskTimes str = do
-  start <- lookupTime CreateEvent str
-  let mend = lookupTime CompletionEvent str
-  return (start,mend)
+lookupTime' :: TimeEvent -> Struct -> UTCTime
+lookupTime' event str =
+  case lookupTime event str of
+    Nothing -> error $ "no " ++ showEvent event -- for build/task
+    Just t -> t
 
-lookupBuildTimes :: Struct -> Maybe (UTCTime, Maybe UTCTime)
-lookupBuildTimes str = do
+lookupTaskTimes :: Struct -> (UTCTime, Maybe UTCTime, Maybe UTCTime)
+lookupTaskTimes str =
+  let create = lookupTime' CreateEvent str
+      mstart = lookupTime StartEvent str
+      mend = lookupTime CompletionEvent str
+  in (create,mstart,mend)
+
+lookupStartEndTimes :: Struct -> Maybe (UTCTime, Maybe UTCTime)
+lookupStartEndTimes str = do
   start <- lookupTime StartEvent str
   let mend = lookupTime CompletionEvent str
   return (start,mend)
 
-strictLookupTimes :: (Struct -> Maybe (UTCTime, Maybe UTCTime))
-                  -> Struct -> (UTCTime, UTCTime)
-strictLookupTimes lf st =
-  case lf st of
-    Nothing -> error "no start time" -- for build/task
-    Just (start,mend) ->
-      case mend of
-        Nothing -> error "no end time" -- for build/task
-        Just end -> (start,end)
+lookupStartEndTimes' :: Struct -> (UTCTime, UTCTime)
+lookupStartEndTimes' st =
+  (lookupTime' StartEvent st, lookupTime' CompletionEvent st)
 
 durationOfTask :: Struct -> Maybe NominalDiffTime
 durationOfTask str = do
-  (start,mend) <- lookupTaskTimes str
+  let (create,_mstart,mend) = lookupTaskTimes str
   end <- mend
-  return $ diffUTCTime end start
+  return $ diffUTCTime end create
 
-formatLocalTime :: Bool -> TimeZone -> UTCTime -> String
-formatLocalTime start tz t =
+formatLocalTime :: TimeEvent -> TimeZone -> UTCTime -> String
+formatLocalTime event tz t =
   -- FIXME format time with formatting
   formatTime defaultTimeLocale
-  (formatToString (rpadded 11 ' ' string % "%c") (if start then "Created:" else "Completed:")) $
+  (formatToString (rpadded 12 ' ' string % "%c") (showEvent event ++ ":")) $
   utcToZonedTime tz t
 
 renderDuration :: Bool -> NominalDiffTime -> String
@@ -95,5 +96,5 @@
     hrs = if short then "h" else " hours"
 #else
 renderDuration short dur =
-  show dur ++ if short then "" else "ec"
+  show dur ++ if short then "" else "sec"
 #endif
diff --git a/src/Utils.hs b/src/Utils.hs
--- a/src/Utils.hs
+++ b/src/Utils.hs
@@ -4,12 +4,14 @@
   kojiGetBuild',
   showValue,
   buildOutputURL,
-  hubToPkgsURL
+  hubToPkgsURL,
+  buildlogUrlfromTaskId,
+  worktaskDirUrlfromTaskID
   )
 where
 
 import Data.List.Extra (dropSuffix, isInfixOf, isPrefixOf, isSuffixOf, replace,
-                        takeWhileEnd)
+                        takeEnd, takeWhileEnd)
 import Data.RPM (dropArch)
 import Data.RPM.NVR
 import Data.RPM.NVRA
@@ -78,3 +80,17 @@
       if "kojihub" `isSuffixOf` url
       then replace "kojihub" "kojifiles" url +/+ "packages"
       else error' $ "use --files-url to specify kojifiles url for " ++ url
+
+buildlogUrlfromTaskId :: Int -> String
+buildlogUrlfromTaskId tid =
+  worktaskDirUrlfromTaskID tid +/+ "build.log"
+
+worktaskDirUrlfromTaskID :: Int -> String
+worktaskDirUrlfromTaskID tid =
+  "https://kojipkgs.fedoraproject.org/work/tasks" +/+ lastFew +/+ taskid
+  where
+    taskid = show tid
+
+    lastFew =
+      let few = dropWhile (== '0') $ takeEnd 4 taskid in
+        if null few then "0" else few
diff --git a/test/tests.hs b/test/tests.hs
--- a/test/tests.hs
+++ b/test/tests.hs
@@ -16,7 +16,7 @@
     (["builds"],
      [["-L", "rust"]
      ,["-l", "3"]
-     ,["-L", "-p", "rpm-ostree*.fc37"]])
+     ,["-L", "-p", "rpm-ostree*.fc40"]])
   ,
     (["tasks"],
      [["-L"]
@@ -32,7 +32,7 @@
     (["install", "-n", "-y"],
      [["podman", "-p", "podman"] ++ sysdist
      ,["-l", "coreutils"] ++ sysdist
-     ,["-l", "-R", "rpmlint-2.4.0-3.fc37"]
+     ,["-l", "-R", "rpmlint-2.5.0-5.fc40"]
      ,["-H", "https://kojihub.stream.centos.org/kojihub", "-d", "el9", "bash", "-p", "bash"]
      ,["-H", "stream", "-d", "el9", "kernel", "-x", "kernel-devel*", "-x", "*-debug*"]
      ,["-l", "-H", "stream", "-d", "el9", "grep"]
@@ -49,7 +49,7 @@
     )
   ]
   where
-    sysdist = if havedist then [] else ["-d", "fc37"]
+    sysdist = if havedist then [] else ["-d", "fc40"]
 
 main :: IO ()
 main = do
