Copy Labels Between Repos with gh label clone

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.

1. Check the installed command and your session

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.

2. Record the source and destination

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.

3. Inspect both label sets

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.

4. Copy labels without overwriting existing ones

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.

5. Overwrite matching labels only after review

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.

6. Diagnose the common failures

Done means