diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,12 @@
 # dnf-repo releases
 
+## 0.6.1 (2024-06-14)
+- add `--add-repofile URL` action
+- `--add-copr` can now also take an url
+- `--add-copr owner/pkg install` will now expand to "install pkg"
+- allow `-add-copr` and `--add-koji` to continue even if the .repo exists
+- get 1s speedup by dropping sleep 1!
+
 ## 0.6 (2024-04-22)
 - switch license from BSD to GPLv3+
 - add --only option to only --repo enable certain repos
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -21,10 +21,12 @@
 ## Help
 
 `$ dnf-repo --version`
+
 ```
-0.6
+0.6.1
 ```
 `$ dnf-repo --help`
+
 ```
 DNF wrapper repo tool
 
@@ -37,9 +39,11 @@
                   (-t|--enable-testing) | (-T|--disable-testing) |
                   (-m|--enable-modular) | (-M|--disable-modular) |
                   --enable-debuginfo | --disable-debuginfo | --enable-source |
-                  --disable-source | (-c|--add-copr [SERVER/]COPR/PROJECT)
+                  --disable-source | (-c|--add-copr [SERVER/]COPR/PROJECT|URL)
                   [--osname OSNAME] [--releasever RELEASEVER] |
-                  (-k|--add-koji REPO) | (-u|--repourl URL)] [DNFARGS]
+                  (-k|--add-koji REPO) | (-r|--add-repofile REPOFILEURL)
+                  [--releasever RELEASEVER] |
+                  (-u|--repourl URL)] [DNFARGS]
 
   see https://github.com/juhp/dnf-repo#readme
 
@@ -70,13 +74,15 @@
   --disable-debuginfo      Disable debuginfo repos
   --enable-source          Enable source repos
   --disable-source         Disable source repos
-  -c,--add-copr [SERVER/]COPR/PROJECT
-                           Create repo file for copr repo (defaults to fedora
-                           server)
+  -c,--add-copr [SERVER/]COPR/PROJECT|URL
+                           Install copr repo file (defaults to fedora server)
   --osname OSNAME          Specify OS Name to override (eg epel)
   --releasever RELEASEVER  Specify OS Release Version to override (eg rawhide)
   -k,--add-koji REPO       Create repo file for a Fedora koji repo (f40-build,
                            rawhide, epel9-build, etc)
+  -r,--add-repofile REPOFILEURL
+                           Install repo file
+  --releasever RELEASEVER  Specify OS Release Version to override (eg rawhide)
   -u,--repourl URL         Use temporary repo from a baseurl
 ```
 
@@ -111,17 +117,18 @@
 ```
 (note the copr repo is not permanently enabled).
 
+Also you can use the equivalent abbreviation: `dnf-repo -c varlad/helix install` if the package and repo have the same name.
+
 Later update with the copr:
 ```shellsession
 $ dnf-repo -e helix update
 ```
 
 ### Changing system repo config
-Disable fedora modular and cisco openh264 repos permanently:
+Disable fedora updates-testing and cisco openh264 repos permanently:
 ```shellsession
-$ dnf-repo --M -d h264 --save
+$ dnf-repo -T -d h264 --save
 ```
-(All modular repos were dropped in Fedora 39.)
 
 ### Use only source repos
 ```shellsession
diff --git a/dnf-repo.cabal b/dnf-repo.cabal
--- a/dnf-repo.cabal
+++ b/dnf-repo.cabal
@@ -1,14 +1,14 @@
 name:                dnf-repo
-version:             0.6
+version:             0.6.1
 synopsis:            A dnf wrapper with fine control of enabled repos
 description:
         A command-line wrapper of the dnf package manager to
         control the repos enabled for a dnf invocation.
 license:             GPL-3
 license-file:        COPYING
-author:              Jens Petersen <juhpetersen@gmail.com>
-maintainer:          Jens Petersen <juhpetersen@gmail.com>
-copyright:           2022-2024  Jens Petersen <juhpetersen@gmail.com>
+author:              Jens Petersen <petersen@redhat.com>
+maintainer:          Jens Petersen <petersen@redhat.com>
+copyright:           2022-2024  Jens Petersen <petersen@redhat.com>
 category:            Utility
 homepage:            https://github.com/juhp/dnf-repo
 bug-reports:         https://github.com/juhp/dnf-repo/issues
@@ -22,7 +22,7 @@
                      ||  == 9.0.2
                      ||  == 9.2.7
                      ||  == 9.4.8
-                     ||  == 9.6.4
+                     ||  == 9.6.5
                      ||  == 9.8.2
 data-dir:            data
 data-files:          koji-REPO.repo
diff --git a/src/Main.hs b/src/Main.hs
--- a/src/Main.hs
+++ b/src/Main.hs
@@ -28,7 +28,6 @@
 import System.FilePath
 import System.IO (hSetBuffering, stdout, BufferMode(NoBuffering))
 import System.IO.Extra (withTempDir)
-import System.Time.Extra (sleep)
 
 import Paths_dnf_repo (getDataFileName, version)
 import ExpireRepos
@@ -60,12 +59,17 @@
       where
         cleanupReponame =
           -- FIXME handle copr url too
-          serverAliases . replace "@" "group_" . replace "/" ":" . dropWhileEnd (== '/') . dropWhile (== '/')
+          serverAliases . replace "@" "group_" . replace "/" ":" . dropWhileEnd (== '/') . dropWhile (== '/') . handleCoprUrl
 
         serverAliases ('r':'e':'d':'h':'a':'t':':':copr) =
           "copr.devel.redhat.com:" ++ copr
         serverAliases copr = copr
 
+        handleCoprUrl url =
+          if "https:" `isPrefixOf` url
+          then replace "coprs/" "" $ dropPrefix "https:" url
+          else url
+
     modeOpt =
       DisableRepo <$> repoOptionWith 'd' "disable" "REPOPAT" "Disable repos" <|>
       EnableRepo <$> repoOptionWith 'e' "enable" "REPOPAT" "Enable repos" <|>
@@ -82,11 +86,16 @@
       flagLongWith' (Specific EnableSource) "enable-source" "Enable source repos" <|>
       flagLongWith' (Specific DisableSource) "disable-source" "Disable source repos" <|>
       AddCopr
-      <$> repoOptionWith 'c' "add-copr" "[SERVER/]COPR/PROJECT" "Create repo file for copr repo (defaults to fedora server)"
+      <$> repoOptionWith 'c' "add-copr" "[SERVER/]COPR/PROJECT|URL" "Install copr repo file (defaults to fedora server)"
       <*> optional (strOptionLongWith "osname" "OSNAME" "Specify OS Name to override (eg epel)")
       <*> optional (strOptionLongWith "releasever" "RELEASEVER" "Specify OS Release Version to override (eg rawhide)") <|>
-      AddKoji <$> repoOptionWith 'k' "add-koji" "REPO" "Create repo file for a Fedora koji repo (f40-build, rawhide, epel9-build, etc)" <|>
-      RepoURL <$> strOptionWith 'u' "repourl" "URL" "Use temporary repo from a baseurl"
+      AddKoji
+      <$> repoOptionWith 'k' "add-koji" "REPO" "Create repo file for a Fedora koji repo (f40-build, rawhide, epel9-build, etc)" <|>
+      AddRepo
+      <$> strOptionWith 'r' "add-repofile" "REPOFILEURL" "Install repo file"
+      <*> optional (strOptionLongWith "releasever" "RELEASEVER" "Specify OS Release Version to override (eg rawhide)") <|>
+      RepoURL
+      <$> strOptionWith 'u' "repourl" "URL" "Use temporary repo from a baseurl"
 
 fedoraCopr :: String
 fedoraCopr = "copr.fedorainfracloud.org"
@@ -114,13 +123,17 @@
   withCurrentDirectory yumReposD $ do
     forM_ modes $
       \case
-        AddCopr copr mosname mrelease -> addCoprRepo dryrun debug mosname mrelease copr
-        AddKoji repo -> addKojiRepo dryrun debug repo
+        AddCopr copr mosname mrelease ->
+          addCoprRepo dryrun debug mosname mrelease copr
+        AddKoji repo ->
+          addKojiRepo dryrun debug repo
+        AddRepo repo mrelease ->
+          addRepoFile dryrun debug mrelease repo
         _ -> return ()
     repofiles <- filesWithExtension "./" "repo"
-    when debug $
-      print modes
+    when debug $ print modes
     nameStates <- sort <$> concatMapM readRepos repofiles
+    when debug $ mapM_ print nameStates
     let actions = selectRepo exact nameStates modes
         moreoutput = not (null args) || null actions || listrepos
     when (debug && not (null modes)) $
@@ -169,7 +182,6 @@
       when save $ putStrLn ""
       listRepos $ map (updateState actions) nameStates
       else do
-      sleep 1
       when save $ putStrLn ""
       mdnf <-
         if dnf4
@@ -183,7 +195,18 @@
               weakdeps = maybe [] (\w -> ["--setopt=install_weak_deps=" ++ show w]) mweakdeps
               quietopt = if quiet then ("-q" :) else id
               cachedir = ["--setopt=cachedir=/var/cache/dnf" </> relver | relver <- maybeToList (maybeReleaseVer args)]
-          in doSudo dryrun debug dnf $ quietopt repoargs ++ cachedir ++ weakdeps ++ map mungeArg args
+              extraargs =
+                -- special case for "dnf-repo -c owner/project install"
+                case modes of
+                  [mode] ->
+                    case mode of
+                      AddCopr proj _ _ | args == ["install"] ->
+                                           [takeWhileEnd (/= ':') proj]
+                      _ -> []
+                  _ -> []
+          in doSudo dryrun debug dnf $
+             quietopt repoargs ++ cachedir ++ weakdeps ++ map mungeArg args ++
+             extraargs
         -- FIXME rpm-ostree install supports --enablerepo
         Nothing -> error' "missing dnf (rpm-ostree is not supported)"
   where
@@ -196,22 +219,24 @@
   let (server,owner,project) = serverOwnerProject repo
       repofile =
         "_copr:" ++ server ++ ':' : owner ++ ':' : project <.> "repo"
-  whenM (doesFileExist repofile) $
-    error' $ "repo already defined:" +-+ repofile
-  osName <- maybe getRpmOSName return mosname
-  osVersion <- maybe getRpmOsRelease return mrelease
-  let repofileUrl = "https://" ++ server +/+ "coprs" +/+ mungeGroupUrl owner +/+ project +/+ "repo" +/+ osName ++ '-' : osVersion +/+ owner ++ '-' : project <.> "repo"
-  (curlres,curlcontent) <- curlGetString repofileUrl []
-  unless (curlres == CurlOK) $
-    error' $ "downloading failed of" +-+ repofileUrl
-  putStrLn $ "Setting up copr repo" +-+ repo
-  withTempDir $ \ tmpdir -> do
-    let tmpfile = tmpdir </> repofile
-    unless dryrun $ writeFile tmpfile $
-      maybe id (replace "$releasever") mrelease $
-      replace "enabled=1" "enabled=0" curlcontent
-    doSudo dryrun debug "cp" [tmpfile, repofile]
-    putStrLn ""
+  exists <- doesFileExist repofile
+  if exists
+    then warning $ "copr repo already defined:" +-+ repofile
+    else do
+    osName <- maybe getRpmOSName return mosname
+    osVersion <- maybe getRpmOsRelease return mrelease
+    let repofileUrl = "https://" ++ server +/+ "coprs" +/+ mungeGroupUrl owner +/+ project +/+ "repo" +/+ osName ++ '-' : osVersion +/+ owner ++ '-' : project <.> "repo"
+    (curlres,curlcontent) <- curlGetString repofileUrl []
+    unless (curlres == CurlOK) $
+      error' $ "downloading failed of" +-+ repofileUrl
+    putStrLn $ "Setting up copr repo" +-+ repo
+    withTempDir $ \ tmpdir -> do
+      let tmpfile = tmpdir </> repofile
+      unless dryrun $ writeFile tmpfile $
+        maybe id (replace "$releasever") mrelease $
+        replace "enabled=1" "enabled=0" curlcontent
+      doSudo dryrun debug "cp" [tmpfile, repofile]
+      putStrLn ""
   where
     mungeGroupUrl ('g':'r':'o':'u':'p':'_':own) = "g" +/+ own
     mungeGroupUrl own = own
@@ -225,7 +250,7 @@
             if '.' `elem` c
             then (c, o, p)
             else error' $ "unknown copr server:" +-+ rpo
-          ["copr",_,_,_] -> serverOwnerProject $ dropPrefix "copr/" rpo
+          ["copr",_,_,_] -> serverOwnerProject $ dropPrefix "copr:" rpo
           _ -> error' $ "unknown copr:" +-+ rpo
 
 addKojiRepo :: Bool -> Bool -> String -> IO ()
@@ -239,14 +264,38 @@
   let repofile = replace "REPO" repo kojiRepoTemplate
   exists <- doesFileExist repofile
   if exists
-    then error' $ "repo already defined:" +-+ repofile
-    else putStrLn $ "Setting up koji repo" +-+ repo
-  withTempDir $ \ tmpdir -> do
-    let tmpfile = tmpdir </> repofile
-    unless dryrun $ writeFile tmpfile repodef
-    doSudo dryrun debug "cp" [tmpfile, repofile]
-    putStrLn ""
+    then warning $ "koji repo already defined:" +-+ repofile
+    else do
+    putStrLn $ "Setting up koji repo" +-+ repo
+    withTempDir $ \ tmpdir -> do
+      let tmpfile = tmpdir </> repofile
+      unless dryrun $ writeFile tmpfile repodef
+      doSudo dryrun debug "cp" [tmpfile, repofile]
+      putStrLn ""
 
+-- FIXME maybe handle string (vscode) or local file?
+addRepoFile :: Bool -> Bool -> Maybe String -> String -> IO ()
+addRepoFile dryrun debug mrelease url = do
+  unless (".repo" `isExtensionOf` url) $
+    error' $ url +-+ "does not appear to be a .repo file"
+  let repofile = takeFileName url
+  exists <- doesFileExist repofile
+  if exists
+    then warning $ "repo file already exists:" +-+ repofile
+    else do
+    (curlres,curlcontent) <- curlGetString url []
+    unless (curlres == CurlOK) $
+      error' $ "downloading failed of" +-+ url
+    putStrLn $ "Setting up" +-+ repofile
+    withTempDir $ \ tmpdir -> do
+      let tmpfile = tmpdir </> repofile
+      unless dryrun $ writeFile tmpfile $
+        maybe id (replace "$releasever") mrelease $
+        maybe id (replace "$releasever") mrelease $
+        replace "enabled=1" "enabled=0" curlcontent
+      doSudo dryrun debug "cp" [tmpfile, repofile]
+      putStrLn ""
+
 listRepos :: [RepoState] -> IO ()
 listRepos repoStates = do
   let (on,off) =
@@ -339,3 +388,9 @@
               dropPrefix "\"" $
               dropPrefix idkey osid
     oss -> error' $ "multiple IDs in" +-+ osrelease ++ ":" ++ unwords oss
+
+#if !MIN_VERSION_filepath(1,4,2)
+isExtensionOf :: String -> FilePath -> Bool
+isExtensionOf ext@('.':_) = isSuffixOf ext . takeExtensions
+isExtensionOf ext         = isSuffixOf ('.':ext) . takeExtensions
+#endif
diff --git a/src/State.hs b/src/State.hs
--- a/src/State.hs
+++ b/src/State.hs
@@ -20,12 +20,13 @@
                         replace, sortOn, stripInfix)
 import Data.Maybe (mapMaybe)
 import SimpleCmd (error', (+-+))
+import System.FilePath (takeBaseName)
 import System.FilePath.Glob (compile, match)
 
 import YumRepoFile (RepoState)
 
 data Mode = AddCopr String (Maybe String) (Maybe String) | AddKoji String
-          | RepoURL String
+          | AddRepo String (Maybe String) | RepoURL String
           | EnableRepo String | DisableRepo String | OnlyRepo String
           | ExpireRepo String | ClearExpires
           | DeleteRepo String
@@ -35,6 +36,7 @@
 modePattern :: Mode -> Maybe String
 modePattern (AddCopr c _ _) = Just c
 modePattern (AddKoji k) = Just k
+modePattern (AddRepo r _) = Just r
 modePattern (RepoURL _) = Nothing
 modePattern (EnableRepo r) = Just r
 modePattern (DisableRepo r) = Just r
@@ -195,6 +197,8 @@
           maybeChange repo isSuffixOf (not enabled) (Enable name)
         AddKoji repo ->
           maybeChange repo isSuffixOf (not enabled) (Enable name)
+        AddRepo repo _ ->
+          maybeChange (takeBaseName repo) isSuffixOf (not enabled) (Enable name)
         RepoURL url -> Just $ BaseURL url
         EnableRepo pat ->
           maybeChange pat matchesRepo (not enabled) (Enable name)
@@ -247,7 +251,8 @@
     matchesRepo :: String -> String -> Bool
     matchesRepo "" = error' "empty repo pattern"
     matchesRepo pat
-      | isGlob pat = (match . compile) $
+      | isGlob pat =
+        (match . compile) $
         if exact
         then pat
         else
diff --git a/test/tests.hs b/test/tests.hs
--- a/test/tests.hs
+++ b/test/tests.hs
@@ -8,11 +8,12 @@
 
 tests :: [[String]]
 tests =
-  [["-t"]
+  [["-e", "updates", "-t"] -- updates to avoid rawhide failing
   ,["-e", "copr"]
   ,["-e", "openh264"]
   ,["-e", "rawhide"]
   ,["-d", "update"]
+  ,["-o", "fedora"]
   ,["--enable-source"]
   ,["-d", "*", "--enable-source"]
   ]
