diff --git a/release/README.md b/release/README.md
index b3ed32e74642b3527d374995b8afe51f1ad78708..f73c28985bf5a24ff12c3ddf8b57e7d118121b58 100644
--- a/release/README.md
+++ b/release/README.md
@@ -60,3 +60,14 @@ In case you want to preview release notes generation, or re-generate them after
 ```sh
 yarn release-offline v0.77.0 1234567890abcdef1234567890abcdef12345678  --changelog > changelog.log
 ```
+
+## Required checks copy
+
+When we cut a new release branch, we want to clone the current set of required checks from master. Over time, we add and remove test suites for master, but we want to keep each release branch consistent with the state of master at the time it was cut. To do this, we can run the following command after cutting a new release branch:
+
+```sh
+yarn copy-required-checks release-x.{version}.x
+```
+
+> [!important]
+> This will overwrite existing checks if they already exist
diff --git a/release/package.json b/release/package.json
index 43bbe02b72492b6663c4a1458c2e6b262aa13c0f..385f5d8b5b66a4068f438a6cd915d9007907e3f9 100644
--- a/release/package.json
+++ b/release/package.json
@@ -11,6 +11,7 @@
     "build": "esbuild src/index.ts --bundle --outfile=dist/index.cjs --platform=node --target=node16",
     "prettier": "prettier --write",
     "release-offline": "tsx release-offline.ts",
+    "copy-required-checks": "tsx ./src/required-checks.ts",
     "test:unit": "jest --testPathPattern unit",
     "test:integration": "jest --testPathPattern integration"
   },
diff --git a/release/src/required-checks.ts b/release/src/required-checks.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0da68fd7313b93ac305151a520ebba7f0fb9604a
--- /dev/null
+++ b/release/src/required-checks.ts
@@ -0,0 +1,64 @@
+import "dotenv/config";
+import { Octokit } from "@octokit/rest";
+import "zx/globals";
+$.verbose = false;
+
+const { GITHUB_TOKEN, GITHUB_OWNER, GITHUB_REPO } = process.env;
+
+const github = new Octokit({ auth: GITHUB_TOKEN });
+
+const config = {
+  owner: GITHUB_OWNER || "",
+  repo: GITHUB_REPO || "",
+};
+
+const targetBranch = process.argv[2];
+
+if (!targetBranch) {
+  console.error(chalk.red("You must provide a target branch name"));
+  console.log("Usage: ", chalk.blue("yarn copy-required-checks <branch-to-copy-to>"));
+  process.exit(1);
+}
+
+function filterChecks(checks: string[]) {
+  const checksToExclude = ["Decide whether to backport or not"];
+  return checks.filter(check => !checksToExclude.includes(check));
+}
+
+async function setRequiredChecks(branchName: string, masterCheckList: string[]) {
+  await github.rest.repos.updateBranchProtection({
+    ...config,
+    branch: branchName,
+    required_status_checks: {
+      strict: false,
+      contexts: masterCheckList,
+    },
+    restrictions: null,
+    required_pull_request_reviews: null,
+    enforce_admins: true,
+  });
+
+  console.log(chalk.green(`✅ ${masterCheckList.length} required checks copied to ${branchName}`));
+}
+
+async function getRequiredChecksFromMaster() {
+  const { data: masterCheckList } = await github.rest.repos.getAllStatusCheckContexts({
+    ...config,
+    branch: "master",
+  });
+
+  const filteredCheckList = filterChecks(masterCheckList);
+
+  return filteredCheckList;
+}
+
+async function copyRequiredChecksToBranch(branchName: string) {
+  const masterCheckList = await getRequiredChecksFromMaster();
+
+  await setRequiredChecks(branchName, masterCheckList);
+}
+
+copyRequiredChecksToBranch(targetBranch).catch(e => {
+  console.error(e);
+  process.exit(1);
+});