A GitHub CLI extension for bulk label management and synchronization from YAML/JSON/CSV files.
No more 47 individual API calls! Declarative label management with multi-format support (YAML, JSON, CSV), intelligent diffing, and safe preview mode.
Setting up labels in new repositories or syncing label changes across multiple repos is tedious with the GitHub web UI or requires writing custom scripts. This extension provides declarative label management with support for multiple file formats.
gh extension install scttfrdmn/gh-label-syncgh label-sync sync --file .github/labels.yml
gh label-sync sync --file labels.json --repo owner/repo
gh label-sync sync --file labels.yml --dry-runFlags:
--file/-f(required): Path to label definition file (YAML or JSON)--dry-run: Show what would change without applying--repo/-R: Target repository (default: current repo)--force: Update existing labels even if they differ (default: skip)--delete-unmanaged: Remove labels not in file (dangerous, default: false)
gh label-sync export > .github/labels.yml
gh label-sync export --format json > labels.json
gh label-sync export --repo source/repo | gh label-sync sync --file -Flags:
--format: Output format (yaml[default] orjson)--repo/-R: Source repository
gh label-sync clone source/repo --repo target/repo
gh label-sync clone source/repo --repo target/repo --forceQuick way to copy all labels from one repository to another.
# .github/labels.yml
labels:
- name: "bug"
color: "d73a4a"
description: "Something isn't working"
- name: "enhancement"
color: "a2eeef"
description: "New feature or request"
- name: "type: feature"
color: "1d76db"
description: "New feature implementation"
- name: "priority: critical"
color: "b60205"
description: "Needs immediate attention"{
"labels": [
{
"name": "bug",
"color": "d73a4a",
"description": "Something isn't working"
},
{
"name": "enhancement",
"color": "a2eeef",
"description": "New feature or request"
}
]
}name,color,description
bug,d73a4a,Something isn't working
enhancement,a2eeef,New feature or request
type: feature,1d76db,New feature implementation
Field Requirements:
name(required): Label namecolor(required): 6-character hex color (with or without#)description(optional): Label description
- Create missing labels: Labels in file but not in repo → create
- Skip differing labels: Labels exist but differ → skip (unless
--force) - Keep unmanaged labels: Labels in repo but not in file → keep (unless
--delete-unmanaged)
$ gh label-sync sync --file .github/labels.yml
Analyzing labels...
✓ bug - matches
✓ enhancement - matches
+ type: feature - will create
+ type: bug - will create
~ priority: high - exists but differs (color: ff9800 → fb8c00)
⚠ help wanted - exists but not in file
Summary:
2 labels match
2 labels to create
1 label to update (use --force to apply)
1 unmanaged label (use --delete-unmanaged to remove)
? Apply changes? (Y/n)# Export labels from a template repository
gh label-sync export --repo myorg/template > .github/labels.yml
# Apply to new repository
cd new-project
gh label-sync sync --file .github/labels.yml# Define labels once
cat > org-labels.yml <<EOF
labels:
- name: "priority: critical"
color: "b60205"
description: "Needs immediate attention"
- name: "priority: high"
color: "d93f0b"
description: "High priority"
# ... more labels
EOF
# Apply to all repos
for repo in $(gh repo list myorg --json nameWithOwner -q '.[].nameWithOwner'); do
gh label-sync sync --file org-labels.yml --repo $repo --force
done# Quick clone
gh label-sync clone source/repo --repo target/repo
# Or using export/sync
gh label-sync export --repo source/repo | \
gh label-sync sync --file - --repo target/repo- Go 1.21 or later
- GitHub CLI (
gh) installed
git clone https://github.com/scttfrdmn/gh-label-sync.git
cd gh-label-sync
go build
gh extension install .# Test the extension locally
gh label-sync export
# Run Go tests
go test ./...# Build for current platform
go build -o gh-label-sync
# Cross-compile for release (done automatically by GitHub Actions)
GOOS=linux GOARCH=amd64 go build -o gh-label-sync-linux-amd64gh-label-sync/
├── main.go # Entry point and CLI setup
├── cmd/ # Command implementations
│ ├── sync.go
│ ├── export.go
│ └── clone.go
├── pkg/
│ ├── api/ # GitHub API client wrapper
│ ├── parser/ # YAML/JSON/CSV parsing
│ ├── diff/ # Label diff algorithm
│ └── format/ # Output formatting
└── .github/
└── workflows/
└── release.yml # Automated cross-platform builds
- Update version in code
- Commit changes:
git commit -am "Release v1.0.0" - Create tag:
git tag v1.0.0 - Push tag:
git push --tags - GitHub Actions automatically builds cross-platform binaries and creates release
Contributions welcome! Please:
- Fork the repository
- Create a feature branch
- Make your changes with tests
- Submit a pull request
MIT License - see LICENSE file for details
- gh-milestone - Companion extension for milestone management
- GitHub CLI
- go-gh - Go library for building GitHub CLI extensions
This extension was created because GitHub CLI maintainers decided not to include file-based label import in the core CLI, preferring users create extensions to avoid "format debates" between JSON, YAML, CSV, etc.
By being an extension, we can support all formats! 🎉
The design is based on comprehensive real-world experience setting up GitHub projects.