diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,14 @@
 # Revision history for fedora-repoquery
 
+## 0.7.2 (2025-05-08)
+- warn when no release specified
+- add support for epel10.x minor releases
+- also parse cNs (c8s, c9s, c10s)
+- use eln via download.fp.o (or dl.fp.o) and drop its channels
+- support short pneumonics for common queryformats (nv,nvr,nvra,envr,envra)
+- improve branched pre-release logic using fedora-releases for Bodhi API
+- drop head/tail usage
+
 ## 0.7.1 (2024-09-08)
 - fix for branched: "frozen" state is still in development/ like "pending"
 - enable updates-testing for fedora branched from Beta freeze
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
 
 A dnf wrapper to repoquery different Fedora releases,
 caching repodata separately per release.
-It also supports EPEL and Centos Stream repos.
+It also supports EPEL, Centos Stream and ELN repos.
 
 ## Usage
 Usage examples:
@@ -10,10 +10,10 @@
 `$ fedora-repoquery rawhide firefox`
 
 ```
-firefox-130.0-1.fc42.x86_64 (fedora-rawhide)
+firefox-138.0.1-1.fc43.x86_64 (fedora-rawhide)
 ```
 
-`$ fedora-repoquery 40 --requires filesystem`
+`$ fedora-repoquery 42 --requires filesystem`
 
 ```
 setup
@@ -28,13 +28,13 @@
 `$ fedora-repoquery c10 bash`
 
 ```
-bash-5.2.26-4.el10.x86_64 (c10s-BaseOS)
+bash-5.2.26-6.el10.x86_64 (c10s-BaseOS)
 ```
 
 `$ fedora-repoquery eln kernel`
 
 ```
-kernel-6.11.0-0.rc6.20240906gitb831f83e40a2.53.eln142.x86_64 (eln-BaseOS)
+kernel-6.15.0-0.rc5.250507g0d8d44db295c.45.eln148.x86_64 (eln-BaseOS)
 ```
 
 Without a release argument, the system yum repo configuration is used:
@@ -42,48 +42,46 @@
 `$ fedora-repoquery pandoc`
 
 ```
-pandoc-3.1.11.1-32.fc41.x86_64 (rawhide)
+pandoc-3.6.4-35.fc43.x86_64 (rawhide)
 ```
 but then currently you have to insert `--` before a query option:
 
 `$ fedora-repoquery -- --whatrequires pandoc`
 
 ```
-R-reprex-2.0.2-12.fc41.noarch (rawhide)
-R-rmarkdown-2.24-5.fc41.noarch (rawhide)
-pandoc-pdf-3.1.11.1-32.fc41.x86_64 (rawhide)
-python3-nb2plots-0.7.2-5.fc41.noarch (rawhide)
-python3-pypandoc-1.13-6.fc41.noarch (rawhide)
-rstudio-common-2024.04.2+764-3.fc41.x86_64 (rawhide)
+R-reprex-2.1.1-1.fc43.noarch (rawhide)
+R-rmarkdown-2.24-8.fc43.noarch (rawhide)
+pandoc-pdf-3.6.4-35.fc43.x86_64 (rawhide)
+python3-pypandoc-1.15-3.fc42.noarch (rawhide)
 ```
 
 Use the --time (-T) option to display repo timestamps:
 ```
-$ fedora-repoquery -T 41 fedrq
-2024-07-16 19:45:44 +08 <https://mirror.freedif.org/fedora/fedora/linux/development/rawhide>
+$ fedora-repoquery -T 43 fedrq
+2025-05-07 15:57:29 +08 <https://mirror.freedif.org/fedora/fedora/linux/development/rawhide/>
 
-fedrq-1.1.0-3.fc41.noarch (fedora-rawhide)
+fedrq-1.5.0-1.fc43.noarch (fedora-rawhide)
 ```
 
 Repo timestamp(s) are output when there are no query args
 after the release version:
 
-`$ fedora-repoquery 40`
+`$ fedora-repoquery 42`
 
 ```
-2024-04-20 02:22:34 +08 <https://mirror.freedif.org/fedora/fedora/linux/releases/40/>
-2024-09-07 09:37:56 +08 <https://mirror.freedif.org/fedora/fedora/linux/updates/40/>
+2025-04-15 01:43:43 +08 <https://mirror.freedif.org/fedora/fedora/linux/releases/42/>
+2025-05-08 12:18:02 +08 <https://mirror.freedif.org/fedora/fedora/linux/updates/42/>
 ```
 
 One can also query multiple releases (or arch's):
 
-`$ fedora-repoquery 40 41 python3 | grep x86_64`
+`$ fedora-repoquery 41 42 python3 | grep x86_64`
 
 ```
-python3-3.12.2-2.fc40.x86_64 (f40)
-python3-3.12.5-2.fc40.x86_64 (f40-updates)
-python3-3.13.0~rc1-2.fc41.x86_64 (f41-development)
-python3-3.13.0~rc1-3.fc41.x86_64 (f41-updates-testing)
+python3-3.13.0-1.fc41.x86_64 (f41)
+python3-3.13.3-2.fc41.x86_64 (f41-updates)
+python3-3.13.2-2.fc42.x86_64 (f42)
+python3-3.13.3-2.fc42.x86_64 (f42-updates)
 ```
 
 
@@ -91,7 +89,7 @@
 `$ fedora-repoquery --version`
 
 ```
-0.7.1
+0.7.2
 ```
 
 `$ fedora-repoquery --help`
@@ -101,7 +99,6 @@
 
 Usage: fedora-repoquery [--version] [-4|--dnf4] [(-q|--quiet) | (-v|--verbose)]
                         [--dynamic] [-T|--time] [-K|--koji]
-                        [--devel-channel | --test-channel]
                         [(-m|--mirror URL) | (-D|--dl)]
                         [(-s|--source) | (-A|--all-archs) | [-a|--arch ARCH]]
                         [-t|--testing] [-d|--debug]
@@ -122,8 +119,6 @@
   --dynamic                Redirect each HTTP through mirror
   -T,--time                Show time-stamp of repos
   -K,--koji                Use Koji buildroot
-  --devel-channel          Use eln development compose
-  --test-channel           Use eln test compose [default: production]
   -m,--mirror URL          Fedora mirror [default:
                            https://download.fedoraproject.org/pub]
   -D,--dl                  Use dl.fp.o
@@ -139,7 +134,7 @@
 The default arch is the system arch.
 
 ## Installation
-fedora-repoquery is available in Fedora and EPEL 9:
+fedora-repoquery is available in Fedora and EPEL:
 <https://src.fedoraproject.org/rpms/fedora-repoquery>.
 
 ## Building from source
diff --git a/fedora-repoquery.cabal b/fedora-repoquery.cabal
--- a/fedora-repoquery.cabal
+++ b/fedora-repoquery.cabal
@@ -1,5 +1,5 @@
 name:                fedora-repoquery
-version:             0.7.1
+version:             0.7.2
 synopsis:            Fedora release repos package query tool
 description:
         A CLI tool for repoquerying Fedora and Centos Stream release packages:
@@ -45,17 +45,16 @@
                        URL
   hs-source-dirs:      src
   build-depends:       base < 5,
-                       bodhi,
-                       cached-json-file,
                        case-insensitive,
                        curl,
                        directory,
                        extra,
+                       fedora-releases >= 0.2,
                        filepath,
                        Glob,
                        regex-compat,
                        safe,
-                       simple-cmd,
+                       simple-cmd >= 0.2,
                        simple-cmd-args,
                        text,
                        time,
diff --git a/src/BodhiRelease.hs b/src/BodhiRelease.hs
--- a/src/BodhiRelease.hs
+++ b/src/BodhiRelease.hs
@@ -10,19 +10,18 @@
   )
 where
 
-import Control.Monad.Extra (when)
 import qualified Data.List as L
 import Data.Maybe (mapMaybe)
-import Fedora.Bodhi (bodhiReleases, lookupKey, makeKey)
+import Distribution.Fedora.BodhiReleases (getBodhiFedoraReleases, lookupKey)
 import SimpleCmd (error')
-import System.Cached.JSON (getCachedJSONQuery)
 
 import Types (Natural)
 
 data BodhiRelease =
-  Release {releaseVersion :: String, -- to handle eln
+  Release {releaseVersion :: String, -- to handle "eln"
            releaseState ::  String,
            releaseBranch :: String,
+           releaseComposed :: Bool,
            releasePostBeta :: Bool}
   deriving Eq
 
@@ -30,24 +29,26 @@
 activeFedoraRelease :: Natural -> IO (Either Natural BodhiRelease)
 activeFedoraRelease n = do
   active <- activeFedoraReleases
-  when (null active) $ error' "failed to find active releases with Bodhi API"
-  case L.find (\r -> releaseVersion r == show n) active of
-    Just rel -> return $ Right rel
-    Nothing ->
-      let ordered = L.sort $ map releaseVersion active
-      in return $ Left $ read $ head ordered
+  case L.sortOn releaseVersion active of
+    [] -> error' "failed to find active releases with Bodhi API"
+    (oldest:_) ->
+      return $
+      case L.find (\r -> releaseVersion r == show n) active of
+        Just rel -> Right rel
+        Nothing -> Left $ read $ releaseVersion oldest
 
 activeFedoraReleases :: IO [BodhiRelease]
 activeFedoraReleases =
-  L.nub . mapMaybe maybeRelease <$> getCachedJSONQuery "fedora-repoquery" "fedora-bodhi-releases-active" (bodhiReleases (makeKey "exclude_archived" "1")) 1000
+  L.nub . mapMaybe maybeRelease <$> getBodhiFedoraReleases
   where
     maybeRelease obj = do
       version <- lookupKey "version" obj
-      state <- lookupKey "state" obj
       branch <- lookupKey "branch" obj
+      state <- lookupKey "state" obj
+      composed <- lookupKey "composed_by_bodhi" obj
       let setting = lookupKey "setting_status" obj
       return $
-        Release version state branch $
+        Release version state branch composed $
         setting == Just ("post_beta" :: String)
 
 fedoraReleaseState :: Natural -> IO String
diff --git a/src/List.hs b/src/List.hs
--- a/src/List.hs
+++ b/src/List.hs
@@ -11,5 +11,5 @@
 listVersionsCmd =
   activeFedoraReleases >>= mapM_ printRelease . sortOn releaseState
   where
-    printRelease (Release _version state branch _postbeta) =
+    printRelease (Release _version state branch _composed _postbeta) =
       putStrLn $ branch +-+ state
diff --git a/src/Main.hs b/src/Main.hs
--- a/src/Main.hs
+++ b/src/Main.hs
@@ -13,13 +13,13 @@
 #endif
   )
 #endif
-import Control.Monad (forM_)
+import Control.Monad (forM_, when)
 import Data.Either (partitionEithers)
 import Data.Tuple (swap)
 #if !MIN_VERSION_simple_cmd_args(0,1,7)
 import Options.Applicative (eitherReader, maybeReader, ReadM)
 #endif
-import SimpleCmd ((+-+))
+import SimpleCmd ((+-+), warning)
 import SimpleCmdArgs
 import System.IO (BufferMode(NoBuffering), hSetBuffering, stdout)
 
@@ -29,7 +29,7 @@
 import Paths_fedora_repoquery (version)
 import Query (repoqueryCmd)
 import Release (showReleaseCmd, downloadServer)
-import Types (Channel(..), Mirror(..), Release (System), RepoSource(..), Verbosity(..),
+import Types (Mirror(..), Release (System), RepoSource(..), Verbosity(..),
               eitherRelease)
 
 data Command = Query [String] | CacheSize | CacheEmpties | List
@@ -49,8 +49,6 @@
     <*> switchWith 'T' "time" "Show time-stamp of repos"
     <*> (RepoSource
           <$> switchWith 'K' "koji" "Use Koji buildroot"
-          <*> (flagLongWith' ChanDevel "devel-channel" "Use eln development compose" <|>
-               flagLongWith ChanProd ChanTest "test-channel" "Use eln test compose [default: production]")
           <*> ((Mirror <$> strOptionWith 'm' "mirror" "URL" ("Fedora mirror [default: " ++ downloadServer ++ "]")) <|>
                flagWith DownloadFpo DlFpo 'D' "dl" "Use dl.fp.o"))
     <*> (flagWith' [Source] 's' "source" "Query source repos" <|>
@@ -73,12 +71,14 @@
     Query relargs ->
       -- spanJust from utility-ht nicer but this gets us enough
       let (releases,args) = swap $ partitionEithers $ map eitherRelease relargs
-      in
+      in do
+        when (null releases && verbose /= Quiet) $
+          warning "(using system repos)"
         forM_ (if null releases then [System] else releases) $ \release ->
-        if null args
-        then if null archs
-             then showReleaseCmd debug dynredir reposource release sysarch Nothing testing
-             else forM_ archs $ \arch -> showReleaseCmd debug dynredir reposource release sysarch (Just arch) testing
-        else
-          let multiple = length releases > 1 || length archs > 1
-          in repoqueryCmd dnf4 debug verbose multiple dynredir time release reposource sysarch archs testing args
+          if null args
+          then if null archs
+               then showReleaseCmd debug dynredir reposource release sysarch Nothing testing
+               else forM_ archs $ \arch -> showReleaseCmd debug dynredir reposource release sysarch (Just arch) testing
+          else
+            let multiple = length releases > 1 || length archs > 1
+            in repoqueryCmd dnf4 debug verbose multiple dynredir time release reposource sysarch archs testing args
diff --git a/src/Query.hs b/src/Query.hs
--- a/src/Query.hs
+++ b/src/Query.hs
@@ -6,12 +6,12 @@
 
 import Control.Monad.Extra
 import Data.Char (isSpace)
-import qualified Data.List.Extra as L
+import Data.List.Extra
 import Data.Maybe (isJust, fromMaybe)
 import Safe (lastMay)
 import SimpleCmd (cmdLines)
 import System.Directory (doesFileExist, findExecutable)
-import System.FilePath (takeBaseName)
+import System.FilePath (takeBaseName, (<.>))
 
 import Arch
 import Common (warning)
@@ -72,26 +72,37 @@
     res <- cmdLines dnf cmdargs
     unless (null res) $ do
       unless (not checkdate || release == System || multiple) $ warning ""
-      putStrLn $ L.intercalate "\n" res
+      putStrLn $ intercalate "\n" res
   where
     tweakedArgs dnf5 =
       if not dnf5
       then args
-      else tweakQf $ map tweakInfo args
+      else tweakQfOpt $ map tweakInfo args
       where
         -- dnf5 only has --info not -i
         tweakInfo "-i" = "--info"
         tweakInfo arg = arg
 
         -- dnf5 doesn't append \n to queryformat
-        tweakQf as@(x:y:rest) | x `elem` ["--qf","--queryformat"] =
-                                case lastMay y of
-                                  Just sp -> if isSpace sp
-                                             then as
-                                             else x : (y ++ "\n") : rest
-                                  Nothing -> as
-                              | otherwise = x : tweakQf (y:rest)
-        tweakQf xs = xs
+        tweakQfOpt (x:y:rest) | x `elem` ["--qf","--queryformat"] =
+                                   x : tweakQf y : rest
+                              | otherwise = x : tweakQfOpt (y:rest)
+        tweakQfOpt xs = xs
+
+        tweakQf qf =
+          expandQf qf ++
+          case lastMay qf of
+            Just lc -> if isSpace lc then "" else "\n"
+            Nothing -> ""
+
+        expandQf qf =
+          case lower qf of
+            "nv" -> "%{name}-%{version}"
+            "nvr" -> expandQf "nv" ++ "-%{release}"
+            "nvra" -> expandQf "nvr" <.> "%{arch}"
+            "envr" -> "%{epoch}:" ++ expandQf "nvr"
+            "envra" -> "%{epoch}:" ++ expandQf "nvra"
+            _ -> qf
 
 renderRepoConfig :: (String, URL) -> [String]
 renderRepoConfig (name, url) =
diff --git a/src/Release.hs b/src/Release.hs
--- a/src/Release.hs
+++ b/src/Release.hs
@@ -17,6 +17,7 @@
 import Data.Time.Format (defaultTimeLocale, parseTimeM, rfc822DateFormat)
 import Data.Time.LocalTime (utcToLocalZonedTime)
 import Network.Curl (curlHead, CurlOption(..))
+import Safe (tailSafe)
 import SimpleCmd (error', (+-+))
 import Text.Regex (mkRegex, subRegex)
 
@@ -33,7 +34,7 @@
 
 getRelease :: Bool -> Bool -> Bool -> Bool -> RepoSource
             -> Release -> Arch -> Maybe Arch -> Bool -> IO [(String, URL)]
-getRelease debug dynredir warn checkdate reposource@(RepoSource koji _chan _mirror) release sysarch march testing = do
+getRelease debug dynredir warn checkdate reposource@(RepoSource koji _mirror) release sysarch march testing = do
   let arch = fromMaybe sysarch march
   (url,path) <- getURL debug dynredir reposource release arch
   let urlpath = url +//+ path
@@ -46,24 +47,57 @@
       ELN -> return ([("BaseOS",urlpath)],
                      [("AppStream",urlpath),("CRB",urlpath)])
       Rawhide -> return ([("development", urlpath)],[])
+      -- curl -s https://bodhi.fedoraproject.org/releases/?exclude_archived=True | jq
       Fedora n -> do
-        state <- fedoraReleaseState n
-        postbeta <- fedoraReleasePostBeta n
-        return $
-          if state `elem` ["pending","frozen"]
-          then (("development", urlpath) :
-                [("updates", url +//+ ["updates",show n]) | postbeta , state == "frozen"] ++
-                -- FIXME add way to disable or invert testing
-                [("updates-testing", url +//+ ["updates","testing",show n]) | testing || state == "frozen" || postbeta]
-               ,[])
-          else (("releases", urlpath) :
-                ("updates", url +//+ ["updates",show n]) :
-                [("updates-testing", url +//+ ["updates","testing",show n]) | testing || postbeta]
-               ,[])
+        eactiverelease <- activeFedoraRelease n
+        case eactiverelease of
+          Left _oldest ->
+              return (("releases", urlpath) :
+                      ("updates", url +//+ ["updates",show n]) :
+                      [("updates-testing", url +//+ ["updates","testing",show n]) | testing]
+                     ,[])
+          Right rel -> do
+            let composed = releaseComposed rel
+                state = releaseState rel
+                postbeta = releasePostBeta rel
+            return $
+          -- after Beta Freeze
+          -- {"state": "pending", "composed_by_bodhi": true,
+          --  "create_automatic_updates": false, "setting_status": "post_beta"}
+          --
+          -- final freeze
+          -- {"state": "frozen", "composed_by_bodhi": true,
+          --  "create_automatic_updates": false, "setting_status": "post_beta"}
+          --
+          -- final unfrozen
+          -- {"state": "current", "composed_by_bodhi": true,
+          --  "create_automatic_updates": false, "setting_status": "post_beta"}
+          --
+          -- released
+          -- {"state": "current", "composed_by_bodhi": true,
+          --  "create_automatic_updates": false, "setting_status": null}
+          --
+          -- Rawhide
+          -- {"state": "pending", "composed_by_bodhi": false,
+          --  "create_automatic_updates": true, "setting_status": "pre_beta"}
+              if state `elem` ["pending","frozen"] || state == "current" && postbeta
+              then (("development", urlpath) :
+                    [("updates", url +//+ ["updates",show n]) | postbeta , state == "current"] ++
+                    -- FIXME add way to disable or invert testing
+                    [("updates-testing", url +//+ ["updates","testing",show n]) | testing || composed, state /= "current"]
+                   ,[])
+              else (("releases", urlpath) :
+                    ("updates", url +//+ ["updates",show n]) :
+                    [("updates-testing", url +//+ ["updates","testing",show n]) | testing || postbeta]
+                   ,[])
       EPEL n -> return
                 (("epel",urlpath) :
                  [("epel-testing",url +//+ ["testing", show n]) | testing],
                  [])
+      EPEL10Dot n -> return
+                (("epel",urlpath) :
+                 [("epel-testing",url +//+ ["testing", "10." ++ show n]) | testing],
+                 [])
       EPELNext _n -> return ([("epelnext",urlpath)],[])
       System -> error' "showRelease: system unsupported"
   rawhide <- rawhideFedoraRelease
@@ -83,8 +117,9 @@
               case release of
                 Centos 10 -> ["metadata","composeinfo.json"]
                 Centos _ -> ["COMPOSE_ID"] -- ["metadata","composeinfo.json"]
-                ELN -> ["metadata","composeinfo.json"]
+                ELN -> ["COMPOSE_ID"]
                 EPEL _ -> ["Everything", "state"]
+                EPEL10Dot _ -> ["Everything", "state"]
                 EPELNext _ -> ["Everything", "state"]
                 Fedora _ -> if "updates" `isInfixOf` reponame
                             then ["Everything", "state"]
@@ -102,7 +137,7 @@
 
 getURL :: Bool -> Bool -> RepoSource -> Release -> Arch
        -> IO (URL,[String])
-getURL debug dynredir reposource@(RepoSource koji chan _mirror) release arch =
+getURL debug dynredir reposource@(RepoSource koji _mirror) release arch =
   case release of
     Centos n ->
       case n of
@@ -121,15 +156,16 @@
         8 -> return (URL "http://vault.centos.org/8-stream/", [])
         _ -> error' "old Centos is not supported"
     ELN ->
-      return (URL "https://odcs.fedoraproject.org/composes", [channel chan, "latest-Fedora-ELN", "compose"])
+      getFedoraServer debug dynredir reposource ["eln"] ["1"]
     EPEL n | n < 7 ->
                return
                (URL "https://archives.fedoraproject.org/pub/archive/epel", [show n])
     EPEL n -> getFedoraServer debug dynredir reposource ["epel"] [show n]
+    EPEL10Dot n -> getFedoraServer debug dynredir reposource ["epel"] ["10." ++ show n]
     EPELNext n -> getFedoraServer debug dynredir reposource ["epel","next"] [show n]
     Fedora n -> do
-      ebodhirelease <- activeFedoraRelease n
-      case ebodhirelease of
+      eactiverelease <- activeFedoraRelease n
+      case eactiverelease of
         Left oldest ->
           if n < oldest
           then
@@ -139,10 +175,12 @@
         Right rel ->
           -- state values: ["disabled","pending","frozen","current","archived"]
           let pending = releaseState rel /= "current"
+              postbeta = releasePostBeta rel
               rawhide = pending && releaseBranch rel == "rawhide"
               releasestr = if rawhide then "rawhide" else show n
           in getFedoraServer debug dynredir reposource fedoraTop
-             [if pending then "development" else "releases", releasestr]
+             [if pending || postbeta then "development" else "releases",
+              releasestr]
     Rawhide -> getFedoraServer debug dynredir reposource fedoraTop ["development", "rawhide"]
     System -> error' "getURL: system unsupported"
   where
@@ -155,7 +193,7 @@
 repoConfigArgs :: RepoSource -> Arch -> Maybe Arch -> Natural -> Release
                -> (String,URL) -> (String,(URL,[String]))
 -- non-koji
-repoConfigArgs (RepoSource False _chan mirror) sysarch march rawhide release (repo,url) =
+repoConfigArgs (RepoSource False mirror) sysarch march rawhide release (repo,url) =
   let arch = fromMaybe sysarch march
       archsuffix = if arch == sysarch then "" else "-" ++ showArch arch
       reponame = repoVersion ++ archsuffix ++
@@ -169,6 +207,7 @@
           Centos _ -> [repo, showArch arch] ++ (if arch == Source then ["tree"] else ["os"])
           ELN -> [repo, showArch arch] ++ (if arch == Source then ["tree"] else ["os"])
           EPEL n -> (if n >= 8 then ("Everything" :) else id) [showArch arch] ++ ["tree" | arch == Source]
+          EPEL10Dot _n -> "Everything" : showArch arch : ["tree" | arch == Source]
           EPELNext _n -> ["Everything", showArch arch]
           Fedora _ -> ["Everything", showArch arch] ++ (if arch == Source then ["tree"] else ["os" | repo `elem` ["releases","development"]])
           Rawhide -> ["Everything", showArch arch, if arch == Source then "tree" else "os"]
@@ -177,18 +216,20 @@
   where
     repoVersion :: String
     repoVersion =
-      if release `elem` [Rawhide, Fedora rawhide]
-      then "fedora-rawhide"
-      else
-        show release ++
-        case release of
-          Centos _ -> '-':repo
-          ELN -> '-':repo
-          EPEL _ -> if repo == "epel-testing" then "-testing" else ""
-          Fedora _ | repo /= "releases" -> '-':repo
-          _ -> ""
+      case release of
+        Rawhide -> "fedora-rawhide"
+        Fedora n ->
+          if n == rawhide
+          then "fedora-rawhide"
+          else show release ++ if repo == "releases" then "" else '-':repo
+        ELN -> show release ++ '-':repo
+        EPEL10Dot _ -> show release ++ if repo == "epel-testing" then "-testing" else ""
+        EPELNext _ -> show release ++ if repo == "epelnext-testing" then "-testing" else ""
+        EPEL _ -> show release ++ if repo == "epel-testing" then "-testing" else ""
+        Centos _ -> show release ++ '-':repo
+        System -> ""
 -- koji
-repoConfigArgs (RepoSource True _chan _mirror) sysarch march _rawhide release (repo,url) =
+repoConfigArgs (RepoSource True _mirror) sysarch march _rawhide release (repo,url) =
   let (compose,path) =
         case release of
           Rawhide -> (["repos", show release, "latest"],"")
@@ -204,7 +245,7 @@
 
 getFedoraServer :: Bool -> Bool -> RepoSource -> [String] -> [String]
                 -> IO (URL,[String])
-getFedoraServer debug dynredir (RepoSource koji _ mirror) top path =
+getFedoraServer debug dynredir (RepoSource koji mirror) top path =
   if koji
   then return (URL "https://kojipkgs.fedoraproject.org",[])
   else
@@ -246,7 +287,7 @@
 curlGetHeader mtimeout field url = do
   (_status,headers) <- curlHead url $ maybe [] (singleton . CurlConnectTimeoutMS . fromIntegral) mtimeout
   -- tail because curl leaves space before field value
-  return $ tail <$> lookup field (map (first CI.mk) headers)
+  return $ tailSafe <$> lookup field (map (first CI.mk) headers)
 
 #if !MIN_VERSION_base(4,15,0)
 singleton :: a -> [a]
diff --git a/src/Types.hs b/src/Types.hs
--- a/src/Types.hs
+++ b/src/Types.hs
@@ -4,15 +4,13 @@
   Mirror(..),
   Natural,
   RepoSource(..),
-  Channel(..),
-  channel,
   Verbosity(..),
   Release(..),
   eitherRelease
   ) where
 
 import Data.Char (isDigit)
-import Data.List.Extra (lower)
+import Data.List.Extra (lower, unsnoc)
 import Numeric.Natural
 
 --import Distribution.Fedora.Repoquery
@@ -24,23 +22,11 @@
   deriving Eq
 
 -- FIXME: True for koji make into type
-data RepoSource = RepoSource Bool Channel Mirror
-  deriving Eq
-
-data Channel = ChanDevel | ChanTest | ChanProd
+data RepoSource = RepoSource Bool Mirror
   deriving Eq
 
-channel :: Channel -> String
-channel ChanDevel = "development"
-channel ChanTest = "test"
-channel ChanProd = "production"
-
-instance Show Channel where
-  show ChanDevel = "devel"
-  show ChanTest = "test"
-  show ChanProd = "prod"
-
-data Release = EPEL Natural | EPELNext Natural | Centos Natural | Fedora Natural
+data Release = EPEL10Dot Natural | EPEL Natural | EPELNext Natural
+             | Centos Natural | Fedora Natural
              | ELN | Rawhide | System
   deriving (Eq, Ord)
 
@@ -57,9 +43,21 @@
     -- FIXME add proper parsing:
     "epel8-next" -> Right $ EPELNext 8
     "epel9-next" -> Right $ EPELNext 9
+    ('e':'p':'e':'l':'1':'0':'.':n@(_:_)) | all isDigit n -> let br = EPEL10Dot (read n)
+                                                 in Right br
     ('e':'p':'e':'l':n@(_:_)) | all isDigit n -> let br = EPEL (read n)
                                                  in Right br
-    ('c':n@(_:_)) | all isDigit n -> let r = read n in Right (Centos r)
+    ('c':n@(_:_)) ->
+      let ver =
+            case unsnoc n of
+              Just (v,'s') -> v
+              _ -> n
+      in if null ver
+         then Left rel
+         else
+           if all isDigit ver
+           then Right (Centos $ read ver)
+           else Left rel
     "eln" -> Right ELN
     ('f':n@(_:_)) | all isDigit n -> let r = read n in Right (Fedora r)
     ns@(_:_) | all isDigit ns ->
@@ -74,6 +72,7 @@
 instance Show Release where
   show Rawhide = "rawhide"
   show (Fedora n) = "f" ++ show n
+  show (EPEL10Dot n) = "epel10." ++ show n
   show (EPEL n) = (if n <= 6 then "el" else "epel") ++ show n
   show (EPELNext n) = "epel" ++ show n ++ "-next"
   show ELN = "eln"
diff --git a/src/URL.hs b/src/URL.hs
--- a/src/URL.hs
+++ b/src/URL.hs
@@ -8,7 +8,7 @@
   removeSubpath
 ) where
 
-import Data.List.Extra (dropSuffix)
+import Data.List.Extra (dropSuffix, dropWhileEnd)
 
 newtype URL = URL String
   deriving Eq
@@ -40,11 +40,11 @@
 -- from http-directory
 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
 
 removeSubpath :: [String] -> String -> String
 removeSubpath path url =
diff --git a/test/tests.hs b/test/tests.hs
--- a/test/tests.hs
+++ b/test/tests.hs
@@ -18,7 +18,7 @@
 
 -- copied from dl-fedora
 branched :: Int
-branched = 41
+branched = 42
 current, previous, prevprev, rawhide :: String
 current = show branched
 previous = show (branched - 1)
@@ -31,7 +31,9 @@
   ,(["-D","rawhide"], Nothing)
   ,([current], Nothing)
   ,([previous], Nothing)
-  ,([prevprev], Nothing)
+  ,(["eln"], Nothing)
+  ,(["epel9"], Nothing)
+  ,(["c10s"], Nothing)
   ,(["-T", "rawhide"], Just "coreutils")
   ,(["--dynamic", rawhide], Just "coreutils")
   ,(["-T", current], Just "gtk4")
@@ -40,6 +42,8 @@
   ,(["-t", previous], Just "podman")
   ,(["eln"], Just "ibus")
   ,(["epel9"], Just "ghc")
+  ,(["epel10"], Just "ghc")
+  ,(["epel10.0"], Just "ghc-srpm-macros")
   ,(["c10"], Just "bash")
   ,(["c9"], Just "kernel")
   ,(["rawhide", "--whatprovides"], Just "perl(Regexp::Pattern::License)")
