Set up a fresh repository and you will want last project's labels, not GitHub's defaults, and gh label clone copies them across in one command. You will copy every label from one repository to another while keeping destination-only labels intact. The examples use GitHub CLI 2.87.3, the version installed on this machine, and take about ten minutes once you know the two repository names.
gh session that can read the source repository and change labels in the destination.sudo.Confirm which executable will run and check authentication before making a change:
$ command -v gh
/usr/bin/gh
$ gh --version
gh version 2.87.3 (2026-02-23)
$ gh auth status
The path can differ on your machine. The version line helps when you compare behaviour with another host. If gh auth status says you are not logged in, authenticate through your normal GitHub CLI process and stop until it succeeds. Never put an access token in a shell command or article.
Checkpoint: Both repository names are in OWNER/REPO form, for example acme/template-repo and acme/service-api. The source is the repository whose labels you want to copy.
Use shell variables to make the direction visible. Replace both values before running the later commands:
$ SOURCE='OWNER/SOURCE-REPOSITORY'
$ DESTINATION='OWNER/DESTINATION-REPOSITORY'
$ printf 'source: %s\ndestination: %s\n' "$SOURCE" "$DESTINATION"
source: OWNER/SOURCE-REPOSITORY
destination: OWNER/DESTINATION-REPOSITORY
Without --repo, the destination is the current repository. That default is easy to miss when you run the command from a checkout belonging to a different project. Supplying --repo removes the ambiguity and lets you run the operation from any directory.
List the labels on both sides before copying. These commands ask for the fields that matter in a review and raise the limit above its default of 30:
$ gh label list --repo "$SOURCE" --limit 1000 --sort name --json name,color,description
$ gh label list --repo "$DESTINATION" --limit 1000 --sort name --json name,color,description
Both print JSON. Keep the two outputs if the destination already has carefully tuned colours or descriptions. A label with the same name can have different settings in the two repositories, and that matters if you later use --force.
Checkpoint: $SOURCE is the intended origin and $DESTINATION is the intended target. A typo in either produces a valid request against the wrong repository.
Run the safe default first:
$ gh label clone "$SOURCE" --repo "$DESTINATION"
$ printf 'exit status: %s\n' "$?"
exit status: 0
What happens:
A zero exit status means the CLI completed the request. Verify the resulting state instead of waiting for a progress message. Check the destination again:
$ gh label list --repo "$DESTINATION" --limit 1000 --sort name --json name,color,description
Compare it with the source output. New labels should now be present, and existing destination labels should keep their previous colour and description, because the default operation skips them.
Warning: --force changes labels that share a name in the destination. It is the destructive branch of this workflow: source values replace destination values, and gh label clone has no undo.
Use it only when the source is the deliberate authority for matching labels:
$ gh label clone "$SOURCE" --repo "$DESTINATION" --force
$ printf 'exit status: %s\n' "$?"
exit status: 0
Review the destination once more:
$ gh label list --repo "$DESTINATION" --limit 1000 --sort name --json name,color,description
Recovery: Save the destination JSON before using --force. For a small number of labels you can then restore the recorded values with gh label edit, for example:
$ gh label edit 'bug' --repo "$DESTINATION" --color 'B60205' --description 'A confirmed defect'
Use the actual saved name, six-character hexadecimal colour and description from your review. This is manual restoration, not a transaction rollback.
gh uses. Run the two gh label list checks separately to see which side fails.--repo and do not rely on the current directory. If you find a mistaken destination after a copy, stop. The default operation is additive, so destination-only labels remain; if --force was used, inspect the label list and repair overwritten labels from your saved values.--limit. The default is 30, so a short listing does not prove the repository has only 30 labels. Raise the limit for large repositories and check the exit status.gh version and authenticated account were confirmed.OWNER/REPO form.--force was used only after review, with a saved record of any overwritten values.