diff --git a/modules/setting/repository.go b/modules/setting/repository.go
index d5a521b973..8add0a353b 100644
--- a/modules/setting/repository.go
+++ b/modules/setting/repository.go
@@ -7,6 +7,7 @@ import (
 	"os/exec"
 	"path"
 	"path/filepath"
+	"slices"
 	"strings"
 
 	"code.gitea.io/gitea/modules/log"
@@ -19,6 +20,8 @@ const (
 	RepoCreatingPublic             = "public"
 )
 
+var RecognisedRepositoryDownloadOrCloneMethods = []string{"download-zip", "download-targz", "download-bundle", "vscode-clone", "vscodium-clone", "cite"}
+
 // ItemsPerPage maximum items per page in forks, watchers and stars of a repo
 const ItemsPerPage = 40
 
@@ -43,6 +46,7 @@ var (
 		DisabledRepoUnits                       []string
 		DefaultRepoUnits                        []string
 		DefaultForkRepoUnits                    []string
+		DownloadOrCloneMethods                  []string
 		PrefixArchiveFiles                      bool
 		DisableMigrations                       bool
 		DisableStars                            bool `ini:"DISABLE_STARS"`
@@ -160,6 +164,7 @@ var (
 		DisabledRepoUnits:                       []string{},
 		DefaultRepoUnits:                        []string{},
 		DefaultForkRepoUnits:                    []string{},
+		DownloadOrCloneMethods:                  []string{"download-zip", "download-targz", "download-bundle", "vscode-clone"},
 		PrefixArchiveFiles:                      true,
 		DisableMigrations:                       false,
 		DisableStars:                            false,
@@ -358,4 +363,10 @@ func loadRepositoryFrom(rootCfg ConfigProvider) {
 	if err := loadRepoArchiveFrom(rootCfg); err != nil {
 		log.Fatal("loadRepoArchiveFrom: %v", err)
 	}
+
+	for _, method := range Repository.DownloadOrCloneMethods {
+		if !slices.Contains(RecognisedRepositoryDownloadOrCloneMethods, method) {
+			log.Error("Unrecognised repository download or clone method: %s", method)
+		}
+	}
 }
diff --git a/modules/web/middleware/data.go b/modules/web/middleware/data.go
index 08d83f94be..c1d1af8528 100644
--- a/modules/web/middleware/data.go
+++ b/modules/web/middleware/data.go
@@ -53,6 +53,7 @@ func CommonTemplateContextData() ContextData {
 		"ShowMilestonesDashboardPage":   setting.Service.ShowMilestonesDashboardPage,
 		"ShowFooterVersion":             setting.Other.ShowFooterVersion,
 		"DisableDownloadSourceArchives": setting.Repository.DisableDownloadSourceArchives,
+		"DownloadOrCloneMethods":        setting.Repository.DownloadOrCloneMethods,
 
 		"EnableSwagger":      setting.API.EnableSwagger,
 		"EnableOpenIDSignIn": setting.Service.EnableOpenIDSignIn,
diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index c53f573a10..57c11f1de0 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -961,6 +961,7 @@ all_branches = All branches
 fork_no_valid_owners = This repository can not be forked because there are no valid owners.
 use_template = Use this template
 clone_in_vsc = Clone in VS Code
+clone_in_vscodium = Clone in VS Codium
 download_zip = Download ZIP
 download_tar = Download TAR.GZ
 download_bundle = Download BUNDLE
diff --git a/templates/repo/clone_script.tmpl b/templates/repo/clone_script.tmpl
index 0797b400d8..9ff826bc93 100644
--- a/templates/repo/clone_script.tmpl
+++ b/templates/repo/clone_script.tmpl
@@ -38,5 +38,8 @@
 		for (const el of document.getElementsByClassName('js-clone-url-vsc')) {
 			el['href'] = 'vscode://vscode.git/clone?url=' + encodeURIComponent(link);
 		}
+		for (const el of document.getElementsByClassName('js-clone-url-vscodium')) {
+			el['href'] = 'vscodium://vscode.git/clone?url=' + encodeURIComponent(link);
+		}
 	})();
 </script>
diff --git a/templates/repo/home.tmpl b/templates/repo/home.tmpl
index d91dc4394e..eb6d96f28e 100644
--- a/templates/repo/home.tmpl
+++ b/templates/repo/home.tmpl
@@ -131,15 +131,32 @@
 						<button id="more-btn" class="ui basic small compact jump dropdown icon button" data-tooltip-content="{{ctx.Locale.Tr "repo.more_operations"}}">
 							{{svg "octicon-kebab-horizontal"}}
 							<div class="menu">
-								{{if not $.DisableDownloadSourceArchives}}
-									<a class="item archive-link" href="{{$.RepoLink}}/archive/{{PathEscapeSegments $.RefName}}.zip" rel="nofollow">{{svg "octicon-file-zip" 16 "gt-mr-3"}}{{ctx.Locale.Tr "repo.download_zip"}}</a>
-									<a class="item archive-link" href="{{$.RepoLink}}/archive/{{PathEscapeSegments $.RefName}}.tar.gz" rel="nofollow">{{svg "octicon-file-zip" 16 "gt-mr-3"}}{{ctx.Locale.Tr "repo.download_tar"}}</a>
-									<a class="item archive-link" href="{{$.RepoLink}}/archive/{{PathEscapeSegments $.RefName}}.bundle" rel="nofollow">{{svg "octicon-package" 16 "gt-mr-3"}}{{ctx.Locale.Tr "repo.download_bundle"}}</a>
-									{{if .CitiationExist}}
-										<a class="item" id="cite-repo-button">{{svg "octicon-cross-reference" 16 "gt-mr-3"}}{{ctx.Locale.Tr "repo.cite_this_repo"}}</a>
+								{{$citation := .CitationExist}}
+								{{$originLink := .CloneButtonOriginLink}}
+								{{range $.DownloadOrCloneMethods}}
+									{{if not $.DisableDownloadSourceArchives}}
+										{{if eq . "download-zip"}}
+										<a class="item archive-link" href="{{$.RepoLink}}/archive/{{PathEscapeSegments $.RefName}}.zip" rel="nofollow">{{svg "octicon-file-zip" 16 "gt-mr-3"}}{{ctx.Locale.Tr "repo.download_zip"}}</a>
+										{{end}}
+										{{if eq . "download-targz"}}
+										<a class="item archive-link" href="{{$.RepoLink}}/archive/{{PathEscapeSegments $.RefName}}.tar.gz" rel="nofollow">{{svg "octicon-file-zip" 16 "gt-mr-3"}}{{ctx.Locale.Tr "repo.download_tar"}}</a>
+										{{end}}
+										{{if eq . "download-bundle"}}
+										<a class="item archive-link" href="{{$.RepoLink}}/archive/{{PathEscapeSegments $.RefName}}.bundle" rel="nofollow">{{svg "octicon-package" 16 "gt-mr-3"}}{{ctx.Locale.Tr "repo.download_bundle"}}</a>
+										{{end}}
+										{{if $citation}}
+											{{if eq . "cite"}}
+											<a class="item" id="cite-repo-button">{{svg "octicon-cross-reference" 16 "gt-mr-3"}}{{ctx.Locale.Tr "repo.cite_this_repo"}}</a>
+											{{end}}
+										{{end}}
+									{{end}}
+									{{if eq . "vscode-clone"}}
+									<a class="item js-clone-url-vsc" href="vscode://vscode.git/clone?url={{$originLink.HTTPS}}">{{svg "gitea-vscode" 16 "gt-mr-3"}}{{ctx.Locale.Tr "repo.clone_in_vsc"}}</a>
+									{{end}}
+									{{if eq . "vscodium-clone"}}
+									<a class="item js-clone-url-vscodium" href="vscodium://vscode.git/clone?url={{$originLink.HTTPS}}">{{svg "gitea-vscode" 16 "gt-mr-3"}}{{ctx.Locale.Tr "repo.clone_in_vscodium"}}</a>
 									{{end}}
 								{{end}}
-								<a class="item js-clone-url-vsc" href="vscode://vscode.git/clone?url={{.CloneButtonOriginLink.HTTPS}}">{{svg "gitea-vscode" 16 "gt-mr-3"}}{{ctx.Locale.Tr "repo.clone_in_vsc"}}</a>
 							</div>
 						</button>
 						{{template "repo/clone_script" .}}{{/* the script will update `.js-clone-url` and related elements */}}
diff --git a/tests/integration/repo_test.go b/tests/integration/repo_test.go
index ed5466bc63..bb341b2ce0 100644
--- a/tests/integration/repo_test.go
+++ b/tests/integration/repo_test.go
@@ -43,6 +43,84 @@ func TestViewRepo(t *testing.T) {
 	session.MakeRequest(t, req, http.StatusNotFound)
 }
 
+func TestViewRepoCloneMethods(t *testing.T) {
+	defer tests.PrepareTestEnv(t)()
+
+	getCloneMethods := func() []string {
+		req := NewRequest(t, "GET", "/user2/repo1")
+		resp := MakeRequest(t, req, http.StatusOK)
+
+		htmlDoc := NewHTMLParser(t, resp.Body)
+		cloneMoreMethodsHTML := htmlDoc.doc.Find("#more-btn div a")
+
+		var methods []string
+		cloneMoreMethodsHTML.Each(func(i int, s *goquery.Selection) {
+			a, _ := s.Attr("href")
+			methods = append(methods, a)
+		})
+
+		return methods
+	}
+
+	testCloneMethods := func(expected []string) {
+		methods := getCloneMethods()
+
+		assert.Len(t, methods, len(expected))
+		for i, expectedMethod := range expected {
+			assert.Contains(t, methods[i], expectedMethod)
+		}
+	}
+
+	t.Run("Defaults", func(t *testing.T) {
+		defer tests.PrintCurrentTest(t)()
+
+		testCloneMethods([]string{"/master.zip", "/master.tar.gz", "/master.bundle", "vscode://"})
+	})
+
+	t.Run("Customized methods", func(t *testing.T) {
+		defer tests.PrintCurrentTest(t)()
+		defer test.MockVariableValue(&setting.Repository.DownloadOrCloneMethods, []string{"vscodium-clone", "download-targz"})()
+
+		testCloneMethods([]string{"vscodium://", "/master.tar.gz"})
+	})
+
+	t.Run("Individual methods", func(t *testing.T) {
+		defer tests.PrintCurrentTest(t)()
+
+		singleMethodTest := func(method, expectedURLPart string) {
+			t.Run(method, func(t *testing.T) {
+				defer tests.PrintCurrentTest(t)()
+				defer test.MockVariableValue(&setting.Repository.DownloadOrCloneMethods, []string{method})()
+
+				testCloneMethods([]string{expectedURLPart})
+			})
+		}
+
+		cases := map[string]string{
+			"download-zip":    "/master.zip",
+			"download-targz":  "/master.tar.gz",
+			"download-bundle": "/master.bundle",
+			"vscode-clone":    "vscode://",
+			"vscodium-clone":  "vscodium://",
+		}
+		for method, expectedURLPart := range cases {
+			singleMethodTest(method, expectedURLPart)
+		}
+	})
+
+	t.Run("All methods", func(t *testing.T) {
+		defer tests.PrintCurrentTest(t)()
+		defer test.MockVariableValue(&setting.Repository.DownloadOrCloneMethods, setting.RecognisedRepositoryDownloadOrCloneMethods)()
+
+		methods := getCloneMethods()
+		// We compare against
+		// len(setting.RecognisedRepositoryDownloadOrCloneMethods) - 1, because
+		// the test environment does not currently set things up for the cite
+		// method to display.
+		assert.GreaterOrEqual(t, len(methods), len(setting.RecognisedRepositoryDownloadOrCloneMethods)-1)
+	})
+}
+
 func testViewRepo(t *testing.T) {
 	defer tests.PrepareTestEnv(t)()