diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,14 @@
 # Changelog
 
+## 2.1 (2025-08-30)
+- unbreak bash-completion by reading rawhide and current release versions later
+- add --qemu option to specify how to run iso (overrides $DLFEDORA_QEMU)
+- help: print releases after editions
+- only try http directory twice
+- warn and rename if checksum filesize changed and small locally (unsigned)
+- add Cosmic to liveRespin map
+- MATE missing from F43+ and no MiracleWM respin
+
 ## 2.0.1 (2025-03-11)
 - 'stage' and 'test' releases also need to follow Kiwi editions
 
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -12,17 +12,18 @@
 
 `dl-fedora rawhide` : downloads the latest Fedora Rawhide Workstation Live iso
 
-`dl-fedora 42 silverblue` : downloads the Fedora Silverblue iso
+`dl-fedora 43 silverblue` : downloads the Fedora Silverblue iso
 
 `dl-fedora respin kde` : downloads the latest KDE Live respin
 
-`dl-fedora 41 --list` : list editions for version
+`dl-fedora 42 --list` : list editions for version
 
-`dl-fedora 42 kde workstation` : download both KDE and Workstation editions
+`dl-fedora 43 kde workstation` : download both KDE and Workstation editions
 
-`dl-fedora 41 server --arch aarch64` : will download the Server iso for armv8
+`dl-fedora 42 server --arch aarch64` : will download the Server iso for armv8
 
-`dl-fedora --run 42` : will download Fedora Workstation and boot the Live image with qemu-kvm.
+`dl-fedora --run 43` : will download Fedora Workstation and boot the Live image with qemu-kvm.
+(Set `DLFEDORA_QEMU` or `--qemu` to specify a command or script to run instead of the default "qemu-kvm")
 
 `dl-fedora --check respin` : checks if there is a newer respin iso image
 available.
@@ -72,29 +73,28 @@
 `$ dl-fedora --version`
 
 ```
-2.0.1
+2.1
 ```
 `$ dl-fedora --help`
 
 ```
 Fedora iso downloader
 
-Usage: dl-fedora [--version] [-g|--gpg-keys] [--no-checksum | --checksum] 
-                 [--debug] [-T|--no-http-timeout] 
-                 [(-c|--check) | (-l|--local) | --list | (-R|--replace)] 
-                 [-d|--dir DIRECTORY] [-n|--dry-run] [-r|--run] 
-                 [(-L|--latest) | --dl | (-k|--koji) | (-m|--mirror URL)] 
-                 [--dvd] [--cs-devel | --cs-test | --cs-production] 
+Usage: dl-fedora [--version] [-g|--gpg-keys] [--no-checksum | --checksum]
+                 [--debug] [-T|--no-http-timeout]
+                 [(-c|--check) | (-l|--local) | --list | (-R|--replace)]
+                 [-d|--dir DIRECTORY] [-n|--dry-run] [-r|--run] [-q|--qemu QEMU]
+                 [(-L|--latest) | --dl | (-k|--koji) | (-m|--mirror URL)]
+                 [--dvd] [--cs-devel | --cs-test | --cs-production]
                  [--alt-cs-extra-edition ('MAX'|'MIN')] [-a|--arch ARCH] RELEASE
                  [--all-desktops | --all-spins | --all-editions | [-x|--exclude]
                    [EDITION...]]
 
   Tool for downloading Fedora iso file images.
-  RELEASE = release number, respin, rawhide, test (Beta), stage (RC), eln, c9s, c10s, c9s-live
   EDITION = {cloud,container,everything,kde,server,workstation,budgie,cinnamon,
              cosmic,i3,kdemobile,lxde,lxqt,mate,miracle,soas,sway,xfce,
              silverblue,kinoite,onyx,sericea,iot} [default: workstation]
-
+  RELEASE = release number, respin, rawhide, test (Beta), stage (RC), eln, c9s, c10s, c9s-live
   See <https://github.com/juhp/dl-fedora/#readme>
 
 Available options:
@@ -113,6 +113,8 @@
   -d,--dir DIRECTORY       Download directory [default: ~/Downloads/iso]
   -n,--dry-run             Don't actually download anything
   -r,--run                 Boot image in QEMU
+  -q,--qemu QEMU           specify QEMU command for --run (overrides
+                           $DLFEDORA_QEMU, defaults to qemu-kvm)
   -L,--latest              Get latest image either from mirror or dl.fp.o if
                            newer
   --dl                     Use dl.fedoraproject.org (dl.fp.o)
@@ -143,4 +145,4 @@
 ## Contribution
 dl-fedora is distributed under the GPL license version 3 or later.
 
-Please report issues or pull requests at <https://github.com/juhp/dl-fedora>.
+Please report issues or contribute at <https://github.com/juhp/dl-fedora>.
diff --git a/dl-fedora.cabal b/dl-fedora.cabal
--- a/dl-fedora.cabal
+++ b/dl-fedora.cabal
@@ -1,6 +1,6 @@
 cabal-version:       1.18
 name:                dl-fedora
-version:             2.0.1
+version:             2.1
 synopsis:            Fedora image download tool
 description:
             Tool to download Fedora and Centos Stream iso and image files.
@@ -31,7 +31,6 @@
                        DownloadDir
 
   build-depends:       base < 5,
-                       ansi-wl-pprint,
                        bytestring,
                        directory >= 1.2.5,
                        extra,
diff --git a/src/Main.hs b/src/Main.hs
--- a/src/Main.hs
+++ b/src/Main.hs
@@ -16,6 +16,7 @@
 import qualified Data.ByteString.Char8 as B
 import Data.Char (isAlphaNum, isDigit)
 import Data.List.Extra
+import Data.List.NonEmpty (NonEmpty(..), nonEmpty)
 import Data.Ord (comparing, Down(Down))
 import Data.Maybe
 import qualified Data.Text as T
@@ -27,11 +28,8 @@
 import Network.HTTP.Client.TLS
 import Network.HTTP.Directory
 import Numeric.Natural
-
 import Options.Applicative (fullDesc, header, progDescDoc)
-
-import Paths_dl_fedora (version)
-
+import qualified Options.Applicative.Help.Pretty as P
 import SimpleCmd (cmd, cmd_, cmdBool, error', grep_, logMsg,
                   pipe_, pipeBool, pipeFile_,
                   warning, (+-+),
@@ -49,6 +47,7 @@
                          listDirectory, pathIsSymbolicLink, removeFile,
                          renameFile, setCurrentDirectory, withCurrentDirectory,
                          writable)
+import System.Environment (lookupEnv)
 import System.FilePath (dropFileName, isAbsolute, isRelative, makeRelative,
                         joinPath, takeExtension, takeFileName, (</>), (<.>))
 import System.Posix.Files (createSymbolicLink, fileSize, getFileStatus,
@@ -59,9 +58,9 @@
 import qualified Text.ParserCombinators.ReadP as R
 import qualified Text.ParserCombinators.ReadPrec as RP
 import Text.Regex.Posix
-import qualified Text.PrettyPrint.ANSI.Leijen as P
 
 import DownloadDir
+import Paths_dl_fedora (version)
 
 data FedoraEdition = Cloud
                    | Container
@@ -138,7 +137,7 @@
   case rel of
     Rawhide -> allSpins rawhide current $ Fedora rawhide
     Fedora r -> fedoraSpins rel \\ missingEditions r
-    FedoraRespin -> delete KDEMobile $ allSpins rawhide current $ Fedora current
+    FedoraRespin -> allSpins rawhide current (Fedora current) \\ [KDEMobile, Miracle]
     FedoraTest -> allSpins rawhide current $ Fedora current -- FIXME use fedora-releases
     FedoraStage -> allSpins rawhide current $ Fedora (current + 1) -- FIXME use fedora-releases
     CS 9 True -> [Cinnamon, KDE, MATE, Xfce] -- FIXME missing MAX, MIN
@@ -162,7 +161,7 @@
 missingEditions :: Natural -> [FedoraEdition]
 missingEditions r =
   case compare r 41 of
-    GT -> [IoT]
+    GT -> IoT : [MATE | r >= 43]
     EQ -> [COSMIC]
     LT -> [COSMIC, KDEMobile, Miracle]
 
@@ -244,22 +243,21 @@
 data Mode = Check | Local | List | Download Bool -- replace
   deriving Eq
 
+-- FIXME add --editions
+-- FIXME add --releases
 main :: IO ()
 main = do
   let pdoc = Just $ P.vcat
-             [ P.text "Tool for downloading Fedora iso file images.",
-               P.text ("RELEASE = " <> intercalate ", " ["release number", "respin", "rawhide", "test (Beta)", "stage (RC)", "eln", "c9s", "c10s", "c9s-live"]),
-               P.text "EDITION = " <> P.lbrace <> P.align (P.fillCat (P.punctuate P.comma (map (P.text . lowerEdition) [(minBound :: FedoraEdition)..maxBound])) <> P.rbrace) <> P.text " [default: workstation]" ,
-               P.text "",
-               P.text "See <https://github.com/juhp/dl-fedora/#readme>"
+             [ P.pretty "Tool for downloading Fedora iso file images.",
+               P.pretty "EDITION = " <> P.lbrace <> P.align (P.fillCat (P.punctuate P.comma (map (P.pretty . lowerEdition) [(minBound :: FedoraEdition)..maxBound])) <> P.rbrace) <> P.pretty " [default: workstation]" ,
+               P.pretty ("RELEASE = " <> intercalate ", " ["release number", "respin", "rawhide", "test (Beta)", "stage (RC)", "eln", "c9s", "c10s", "c9s-live"]),
+               P.pretty "See <https://github.com/juhp/dl-fedora/#readme>"
              ]
   sysarch <- readArch <$> cmd "rpm" ["--eval", "%{_arch}"]
-  rawhideVersion <- getRawhideVersion
-  currentRelease <- getCurrentFedoraVersion
   home <- getHomeDirectory
   defaultDir <- checkDefaultIsoDir
   simpleCmdArgsWithMods (Just version) (fullDesc <> header "Fedora iso downloader" <> progDescDoc pdoc) $
-    program rawhideVersion
+    program
     <$> switchWith 'g' "gpg-keys" "Import Fedora GPG keys for verifying checksum file"
     <*> checksumOpts
     <*> switchLongWith "debug" "Debug output"
@@ -271,6 +269,7 @@
     <*> strOptionalWith 'd' "dir" "DIRECTORY" ("Download directory [default:" +-+ prettyDir home defaultDir ++ "]") defaultDir
     <*> switchWith 'n' "dry-run" "Don't actually download anything"
     <*> switchWith 'r' "run" "Boot image in QEMU"
+    <*> optional (strOptionWith 'q' "qemu" "QEMU" "specify QEMU command for --run (overrides $DLFEDORA_QEMU, defaults to qemu-kvm)")
     <*> mirrorOpt
     <*> switchLongWith "dvd" "Download dvd iso instead of boot netinst (for Server, eln, centos)"
     <*> optional (flagLongWith' CSDevelopment "cs-devel" "Use centos-stream development compose" <|>
@@ -278,7 +277,7 @@
                   flagLongWith' CSProduction "cs-production" "Use centos-stream production compose (default is mirror.stream.centos.org)")
     <*> optional (strOptionLongWith "alt-cs-extra-edition" "('MAX'|'MIN')" "Centos Stream Alternative Live Spin editions (MAX,MIN)")
     <*> (optionWith (eitherReader eitherArch) 'a' "arch" "ARCH" ("Specify arch [default:" +-+ showArch sysarch ++ "]") <|> pure sysarch)
-    <*> (readRelease rawhideVersion currentRelease <$> strArg "RELEASE")
+    <*> strArg "RELEASE"
     <*> (flagLongWith' AllDesktops "all-desktops" "Get all Fedora desktops" <|>
          flagLongWith' AllSpins "all-spins" "Get all Fedora Spins" <|>
          flagLongWith' AllEditions "all-editions" "Get all Fedora editions" <|>
@@ -303,10 +302,14 @@
                         primarySize :: Maybe Integer,
                         primaryTime :: Maybe UTCTime}
 
-program :: Natural -> Bool -> CheckSum -> Bool -> Bool -> Mode -> FilePath
-        -> Bool -> Bool -> Mirror -> Bool -> Maybe CentosChannel
-        -> Maybe String -> Arch -> Release -> RequestEditions -> IO ()
-program rawhide gpg checksum debug notimeout mode dlDir dryrun run mirror dvdnet mchannel mcsedition arch tgtrel reqeditions = do
+program :: Bool -> CheckSum -> Bool -> Bool -> Mode -> FilePath
+        -> Bool -> Bool -> Maybe String -> Mirror -> Bool
+        -> Maybe CentosChannel -> Maybe String -> Arch -> String
+        -> RequestEditions -> IO ()
+program gpg checksum debug notimeout mode dlDir dryrun run mqemu mirror dvdnet mchannel mcsedition arch tgtrelstr reqeditions = do
+  rawhide <- getRawhideVersion
+  currentRelease <- getCurrentFedoraVersion
+  let tgtrel = readRelease rawhide currentRelease tgtrelstr
   when (isJust mchannel && not (isCentosStream tgtrel)) $
     error' "channels are only for centos-stream"
   let mirrorUrl =
@@ -349,7 +352,7 @@
       _ -> error' "--alt-cs-extra-edition is only for CS Alt Live spins"
   current <- getCurrentFedoraVersion
   successes <-
-    mapM (runProgramEdition mgr mirrorUrl showdestdir gpg checksum debug mode dryrun run mirror dvdnet mchannel mcsedition arch tgtrel reqeditions) $
+    mapM (runProgramEdition mgr mirrorUrl showdestdir gpg checksum debug mode dryrun run mqemu mirror dvdnet mchannel mcsedition arch tgtrel reqeditions) $
     if mode == List
     then [Workstation]
     else
@@ -392,10 +395,10 @@
     _ -> True
 
 runProgramEdition :: Manager -> URL -> String -> Bool -> CheckSum -> Bool
-                  -> Mode -> Bool -> Bool -> Mirror -> Bool
-                  -> Maybe CentosChannel -> Maybe String -> Arch -> Release
-                  -> RequestEditions -> FedoraEdition -> IO Bool
-runProgramEdition mgr mirrorUrl showdestdir gpg checksum debug mode dryrun run mirror dvdnet mchannel mcsedition arch tgtrel reqeditions edition =
+                  -> Mode -> Bool -> Bool -> Maybe FilePath -> Mirror -> Bool
+                  -> Maybe CentosChannel -> Maybe String -> Arch
+                  -> Release -> RequestEditions -> FedoraEdition -> IO Bool
+runProgramEdition mgr mirrorUrl showdestdir gpg checksum debug mode dryrun run mqemu mirror dvdnet mchannel mcsedition arch tgtrel reqeditions edition =
   case mode of
     Check -> do
       eres <- findURL True
@@ -427,8 +430,7 @@
       mtarget <- derefSymlink symlink
       whenJust mtarget $ \target -> do
         putStrLn $ "Local:" +-+ target
-        when run $
-          bootImage dryrun target showdestdir
+        when run $ bootImage dryrun target showdestdir mqemu
       return True
     List -> do
       rawhide <- getRawhideVersion
@@ -457,7 +459,7 @@
           unless dryrun $ do
             let localfile = takeFileName fileurl
             updateSymlink localfile symlink removeold
-            when run $ bootImage dryrun localfile showdestdir
+            when run $ bootImage dryrun localfile showdestdir mqemu
           return True
   where
     findURL :: Bool
@@ -527,9 +529,9 @@
             let url = top +/+ path
             when debug $ do
               print url
-              redirs <- retry 3 $ httpRedirects mgr $ replace "https:" "http:" url
-              print redirs
-            ls <- retry 3 $ httpDirectory mgr url
+              -- force redirect
+              httpRedirects mgr (replace "https:" "http:" url) >>= print
+            ls <- retry 2 $ httpDirectory mgr url
             return (url, ls)
 
           findMirror primeUrl path file = do
@@ -802,8 +804,15 @@
         (primeSize,primeTime) <- retry 3 $ httpFileSizeTime mgr url
         when debug $ print (primeSize,primeTime,url)
         ok <- checkLocalFileSize filesize checksumfile primeSize primeTime True
-        unless ok $ error' $ "Checksum file filesize mismatch for " ++ checksumfile
-        return ok
+        if ok
+          then return True
+          else
+          if filesize < 900
+          then do
+            warning $ "Renaming unsigned checksum file" +-+ checksumfile
+            renameFile checksumfile $ checksumfile <.> "old"
+            return False
+          else error' $ "Checksum file filesize mismatch for " ++ checksumfile
 
     checkForFedoraKeys :: Natural -> IO Bool
     checkForFedoraKeys n =
@@ -867,7 +876,7 @@
       then return Nothing
       else do
       tz <- getCurrentTimeZone
-      putStrLn $ unwords ["downloading", filename, renderTime tz mtime, "to", showdestdir]
+      putStrLn $ unwords ["downloading", filename, renderTime tz mtime, "under", showdestdir]
       doCurl
       return (Just True)
   where
@@ -897,25 +906,40 @@
 
 liveRespin :: FedoraEdition -> String
 liveRespin Budgie = "Budgie"
+liveRespin COSMIC = "COSMIC"
 liveRespin I3 = "i3"
 liveRespin Miracle = "MiracleWM"
 liveRespin e = take 4 . upper . showEdition FedoraRespin $ e
 
-bootImage :: Bool -> FilePath -> String -> IO ()
-bootImage dryrun img showdir = do
+bootImage :: Bool -> FilePath -> String -> Maybe String -> IO ()
+bootImage dryrun img showdir mqemu = do
   let fileopts =
         case takeExtension img of
           ".iso" -> ["-boot", "d", "-cdrom"]
           _ -> []
-  mQemu <- findExecutable "qemu-kvm"
-  case mQemu of
-    Just qemu -> do
-      let args = ["-m", "4096", "-rtc", "base=localtime", "-cpu", "host"] ++ fileopts
-      -- replace with showCommandForUser or cmdN when updated
-      putStrLn . unwords $ qemu : map translateInternal (args ++ [showdir </> img])
-      unless dryrun $
-        cmd_ qemu (args ++ [img])
-    Nothing -> error' "Need qemu to run image"
+  qemucmd <-
+    case mqemu of
+      Just q -> return q
+      Nothing -> do
+        menv <- lookupEnv "DLFEDORA_QEMU"
+        return $ fromMaybe "qemu-kvm" menv
+  (c :| args) <-
+    case nonEmpty (words qemucmd) of
+      Nothing -> error' "qemu command cannot be empty"
+      Just (q:|qs) -> do
+        mQemu <- findExecutable q
+        case mQemu of
+          Nothing -> error' $ "No such program:" +-+ q
+          Just qemu ->
+            return $
+            qemu :|
+            if null qs
+            then  ["-m", "4096", "-rtc", "base=localtime", "-cpu", "host"] ++ fileopts
+            else qs
+  -- replace with showCommandForUser or cmdN when updated
+  putStrLn . unwords $ c : args ++ [translateInternal (showdir </> img)]
+  unless dryrun $
+    cmd_ c (args ++ [img])
 
 -- from process System.Process.Posix
 translateInternal :: String -> String
@@ -938,11 +962,11 @@
 #if !MIN_VERSION_http_directory(0,1,9)
 infixr 5 +/+
 (+/+) :: String -> String -> String
-"" +/+ s = s
-s +/+ "" = s
-s +/+ t | last s == '/' = init s +/+ t
-        | head t == '/' = s +/+ tail t
-s +/+ t = s ++ "/" ++ t
+s +/+ t =
+  case (s,t) of
+    ("",_) -> t
+    (_,"") -> s
+    (_,_) -> dropWhileEnd (== '/') s ++ '/' : dropWhile (== '/') t
 #endif
 
 -- derived from fedora-repoquery Types
diff --git a/test/tests.hs b/test/tests.hs
--- a/test/tests.hs
+++ b/test/tests.hs
@@ -44,24 +44,26 @@
     ,["-T", "-n", "c10s-live", "--all-editions"]
     ]
 
-mkFedEdition :: String -> [String]
-mkFedEdition ver =
+mkFedEdition :: Natural -> [String]
+mkFedEdition = mkFedEdition' . show
+
+mkFedEdition' :: String -> [String]
+mkFedEdition' ver =
   ["--dl", "-T", "-n", ver, "--all-editions"]
 
 allFedoraEditions :: Natural -> Natural -> [[String]]
 allFedoraEditions oldest rawhide =
-  map (mkFedEdition . show) [oldest..(rawhide-1)]
-  ++
-  [mkFedEdition "stage"]
-  ++
-  -- currently MATE is broken in Rawhide
-  [["--dl", "-T", "-n", show rawhide, "--exclude", "mate"]]
+  map mkFedEdition [oldest..(rawhide-1)]
+  -- currently empty
+  -- ++ [mkFedEdition' "stage"]
+  -- use --exclude for any missing
+  ++ [mkFedEdition rawhide]
 
 allEditions :: Natural -> [String]
 allEditions 9 = allEditions 10 ++ ["cinnamon", "mate", "xfce"]
 allEditions 10 = ["workstation", "kde", "max", "min"]
-allEditions rel = ["cloud","container","everything","server","workstation","budgie","cinnamon","i3","kde","lxde","lxqt","mate","soas","sway","xfce","silverblue","kinoite","onyx","sericea"] ++
-  ["cosmic" | rel >= 42] ++ ["kdemobile" | rel >= 41] ++ ["miracle" | rel >= 41] ++ ["iot" | rel < 42]
+allEditions rel = ["cloud","container","everything","server","workstation","budgie","cinnamon","i3","kde","lxde","lxqt","soas","sway","xfce","silverblue","kinoite","onyx","sericea"] ++
+  ["cosmic" | rel >= 42] ++ ["kdemobile" | rel >= 41] ++ ["miracle" | rel >= 41] ++ ["iot" | rel < 42] ++ ["mate" | rel < 43]
 
 listEditions :: Natural -> IO ()
 listEditions n = do
