diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,11 @@
 # Release history for select-rpms
 
+## 0.2.0 (2024-12-01)
+- extend ExistingStrategy with ExistingOnly
+- use sudoLog with --debug, falling back to old sudo_
+- selectRpmsOptions: renamed from selectRpmsOption
+- add existingStrategyOption (for optparse-applicative)
+
 ## 0.1.0 (2024-08-14)
 - initial release for fbrnch and koji-tool
 - original code was taken from koji-tool Install
diff --git a/select-rpms.cabal b/select-rpms.cabal
--- a/select-rpms.cabal
+++ b/select-rpms.cabal
@@ -1,6 +1,6 @@
 cabal-version:       2.2
 name:                select-rpms
-version:             0.1.0
+version:             0.2.0
 synopsis:            Select a subset of RPM packages
 description:
         A library for selecting a subset of RPM (sub)packages.
@@ -29,12 +29,12 @@
 library
   build-depends:       base < 5,
                        directory,
-                       extra >= 1.7.11,
+                       extra,
                        filepath,
                        Glob,
                        rpm-nvr,
                        safe,
-                       simple-cmd,
+                       simple-cmd >= 0.2,
                        simple-cmd-args >= 0.1.8,
                        simple-prompt >= 0.2
   default-language:    Haskell2010
diff --git a/src/SelectRPMs.hs b/src/SelectRPMs.hs
--- a/src/SelectRPMs.hs
+++ b/src/SelectRPMs.hs
@@ -1,9 +1,9 @@
-{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE CPP, TupleSections #-}
 
 module SelectRPMs (
   Select(..),
   selectDefault,
-  selectRpmsOption,
+  selectRpmsOptions,
   installArgs,
   checkSelection,
   rpmsToNVRAs,
@@ -11,6 +11,7 @@
   ExistNVRA,
   Yes(..),
   ExistingStrategy(..),
+  existingStrategyOption,
   decideRPMs,
   nvraToRPM,
   groupOnArch,
@@ -21,12 +22,20 @@
 
 import Control.Monad.Extra (forM_, mapMaybeM, unless, when)
 import Data.Either (partitionEithers)
-import Data.List.Extra (foldl', groupOnKey, isInfixOf, nubOrd, nubSort, sort,
+import Data.List.Extra (foldl', isInfixOf, nubOrd, nubSort, sort,
+#if MIN_VERSION_extra(1,7,11)
+                        groupOnKey,
+#endif
                         (\\))
 import Data.RPM.NVRA (NVRA(..), readNVRA, showNVRA)
 import Safe (headMay)
-import SimpleCmd (cmd_, cmdMaybe, error', sudo_, (+-+))
-import SimpleCmdArgs (Parser, flagLongWith', many, strOptionWith, (<|>))
+import SimpleCmd (cmd_, cmdMaybe, error', sudo_, (+-+),
+#if MIN_VERSION_simple_cmd(0,2,7)
+                  sudoLog
+#endif
+                 )
+import SimpleCmdArgs (Parser, flagWith', flagLongWith', many, strOptionWith,
+                      (<|>))
 import SimplePrompt (yesNoDefault)
 import System.Directory
 import System.FilePath ((</>), (<.>))
@@ -47,8 +56,8 @@
 selectDefault = PkgsReq [] [] [] []
 
 -- | optparse-applicative Parser for Select
-selectRpmsOption :: Parser Select
-selectRpmsOption =
+selectRpmsOptions :: Parser Select
+selectRpmsOptions =
   flagLongWith' All "all" "all subpackages [default if not installed]" <|>
   flagLongWith' Ask "ask" "ask for each subpackage" <|>
   PkgsReq
@@ -110,9 +119,20 @@
 rpmsToNVRAs :: [String] -> [NVRA]
 rpmsToNVRAs = sort . map readNVRA . filter notDebugPkg
 
--- | how to handle already installed packages: re-install or skip
-data ExistingStrategy = ExistingNoReinstall | ExistingSkip
+-- | how to handle already installed packages: re-install, skip, or
+-- default update
+--
+-- The default strategy is to select existing subpackages, otherwise all.
+data ExistingStrategy = ExistingNoReinstall | ExistingSkip | ExistingOnly
+  deriving Eq
 
+existingStrategyOption :: Parser ExistingStrategy
+existingStrategyOption =
+  flagWith' ExistingNoReinstall 'N' "no-reinstall" "Do not reinstall existing NVRs" <|>
+  flagWith' ExistingSkip 'S' "skip-existing" "Ignore already installed subpackages (implies --no-reinstall)" <|>
+  flagWith' ExistingOnly 'O' "only-existing" "Only update existing installed subpackages"
+
+
 -- | sets prompt default behaviour for yes/no questions
 data Yes = No | Yes
   deriving Eq
@@ -147,10 +167,10 @@
     return []
     else
     case select of
-      All -> promptPkgs yes classified
+      All -> promptPkgs mstrategy yes classified
       Ask -> mapMaybeM (rpmPrompt yes) classified
       PkgsReq subpkgs exceptpkgs exclpkgs addpkgs ->
-        promptPkgs yes $
+        promptPkgs mstrategy yes $
         selectRPMs prefix (subpkgs,exceptpkgs,exclpkgs,addpkgs) classified
   where
     installExists :: NVRA -> IO (Maybe ExistNVRA)
@@ -169,6 +189,7 @@
         case mstrategy of
           Just ExistingSkip | existence /= NotInstalled -> Nothing
           Just ExistingNoReinstall | existence == ExistingNVR -> Nothing
+          Just ExistingOnly | existence == NotInstalled -> Nothing
           _ -> Just (existence, nvra)
 
 -- FIXME move to submodule?
@@ -200,10 +221,12 @@
 printInstalled :: ExistNVRA -> IO ()
 printInstalled = putStrLn . renderInstalled
 
-promptPkgs :: Yes -> [ExistNVRA]
-           -> IO [ExistNVRA]
-promptPkgs _ [] = error' "no rpms found"
-promptPkgs yes classified = do
+promptPkgs :: Maybe ExistingStrategy -> Yes -> [ExistNVRA] -> IO [ExistNVRA]
+promptPkgs (Just ExistingOnly) _ [] = do
+  putStrLn "skipped"
+  return []
+promptPkgs _ _ [] = error' "no rpms found"
+promptPkgs _ yes classified = do
   mapM_ printInstalled classified
   ok <- prompt yes "install above"
   return $ if ok then classified else []
@@ -341,7 +364,7 @@
           when debug $ mapM_ (putStrLn . showRpmFile) dirpkgs
           (case mgr of
             OSTREE -> cmd_
-            _ -> sudo_) pkgmgr $
+            _ -> if debug then sudoLog else sudo_) pkgmgr $
             com ++ map showRpmFile dirpkgs ++ ["--assumeyes" | yes == Yes && mgr `elem` [DNF3,DNF5]]
 
     reinstallCommand :: PkgMgr -> [String]
@@ -360,7 +383,7 @@
         RPM -> ["-ivh"]
         OSTREE -> ["install"]
 
--- FIXME replace with export from rpm-nvr
+-- FIXME replace with export from rpm-nvr (once released)
 -- | render a NVRA as rpm file
 nvraToRPM :: NVRA -> FilePath
 nvraToRPM nvra = showNVRA nvra <.> "rpm"
@@ -374,3 +397,19 @@
             -> [ExistNVRA]
             -> [(FilePath,[ExistNVRA])]
 groupOnArch dir = groupOnKey (\(_,p) -> dir </> rpmArch p)
+
+#if !MIN_VERSION_extra(1,7,11)
+groupOnKey :: Eq k => (a -> k) -> [a] -> [(k, [a])]
+groupOnKey _ []     = []
+groupOnKey f (x:xs) = (fx, x:yes) : groupOnKey f no
+    where
+        fx = f x
+        (yes, no) = span (\y -> fx == f y) xs
+#endif
+
+#if !MIN_VERSION_simple_cmd(0,2,7)
+sudoLog :: String -- ^ command
+     -> [String] -- ^ arguments
+     -> IO ()
+sudoLog = sudo_
+#endif
