/ghsync
Bulk clone and keep in sync every GitHub repo you can access across an org or personal account. For an org it unions the repos reachable through the teams you belong to with the org's repo list (so direct-collaborator and public repos count even with no team membership); for a
Claude Code
$ npx -y skills add bjcoombs/ai-native-toolkit --skill ghsync --agent claude-code
Codex
$ npx skills add bjcoombs/ai-native-toolkit --skill ghsync -a codex -y
Cursor
$ npx skills add bjcoombs/ai-native-toolkit --skill ghsync -a cursor -y
Gemini CLI
$ npx skills add bjcoombs/ai-native-toolkit --skill ghsync -a gemini-cli -y
GitHub Copilot
$ npx skills add bjcoombs/ai-native-toolkit --skill ghsync -a github-copilot -y
OpenCode
$ npx skills add bjcoombs/ai-native-toolkit --skill ghsync -a opencode -y
Windsurf
$ npx skills add bjcoombs/ai-native-toolkit --skill ghsync -a windsurf -y
SKILL.md
ghsync.SKILL.mdname: ghsync
description: "Bulk clone and keep in sync every repo you can access on GitHub or GitLab. GitHub: an org's repos via your teams plus the org repo list, or a personal account's repos. GitLab (--provider gitlab --host <host>): every project in every group you belong to, with nested subgroups and projects shared into those groups, laid out under its path_with_namespace; --group narrows to one subtree, and --porcelain / --from-list split discovery from cloning for hosts reachable only from another network. Deduplicates, then clones new repos and fast-forward syncs existing ones (and their worktrees) into a <path>/<repo>-main + <path>/worktree layout. TRIGGER when the user types /ghsync, wants to clone or sync all org repos, their personal repos or all GitLab group projects, asks to mirror everything they have access to on GitHub or a GitLab host, is onboarding into a new enterprise, org or GitLab group, or wants to refresh their local checkouts to latest."
ghsync: mirror and sync every repo you can access on GitHub or GitLab
Onboarding into a new enterprise means finding and cloning dozens of repos by hand, then drifting out of date. This skill does both halves: it **discovers** everything you can reach and **keeps it in sync**.
- **First run** — clones every accessible repo into a worktree-friendly layout.
- **Every run after** — fast-forward updates repos already on their default
branch, updates their worktrees, and clones anything new. It never clobbers local work: repos with uncommitted changes or on a non-default branch are fetched but not pulled, and reported in the summary.
It is **org-agnostic**: point it at any GitHub org, GitHub Enterprise host, **personal account**, or a **GitLab host** (gitlab.com or self-managed) with `--provider gitlab`; see [GitLab](#gitlab) below. On GitHub: the script detects the account type itself. For an organization it unions the teams you belong to with the org's repo list (so direct-collaborator and public repos are included even with no team membership); for a personal account it uses the account's repo list (private repos included when it's your own account).
How to run it
The script lives next to this file. Claude Code writes this skill's directory into the script paths below when it loads the skill, so each path is already absolute:
# Org is derived from the directory you run in. To mirror the "meridianhub"
# org, run from a directory named meridianhub:
cd ~/dev/github.com/meridianhub
bash "${CLAUDE_SKILL_DIR}/scripts/ghsync.sh"The org defaults to the **basename of the directory you launch from**. So running inside `~/dev/github.com/meridianhub` syncs the `meridianhub` org into that directory. Override the org name or target directory explicitly when they differ:
bash "${CLAUDE_SKILL_DIR}/scripts/ghsync.sh" --org meridianhub --root ~/dev/github.com/meridianhubWhat to do when invoked
1. **Confirm the target.** Run with `--list-repos` first (or `--list-teams` for an org) so the user sees which account and how many repos before any cloning. This doubles as a check that the derived account name is correct. 2. **Dry run on first use against a new org** (`--dry-run`) to preview clones and updates without touching disk. 3. **Run the real sync.** Stream the output; the run ends with a summary (up-to-date / updated / failed / uncommitted / branch issues / worktrees). 4. **Surface the exceptions.** Call out anything under *Failed*, *Uncommitted changes*, or *Not on default branch* — these are the repos the user may need to deal with manually.
Flags
| Flag | Effect | |------|--------| | `--provider github\|gitlab` | Which host type to sync (default: `github`) | | `--root DIR` | Directory to clone into; an explicit `--root` must already exist, in every mode (GitHub default: current directory; GitLab default: `~/dev/<host>` with any `:port` dropped, created on the first real sync) | | `--list-repos` | List the deduplicated accessible repos and exit | | `--porcelain` | Machine-readable repo list: one path per line to stdout (GitHub: the repo name; GitLab: `path_with_namespace`), all chatter to stderr; implies `--list-repos`. Consumed by `/ghreport` and by `--from-list`. | | `--dry-run` | Show what would be cloned/updated without making changes. On GitLab it creates no directory and writes no `.gh_archived_repos`; on GitHub it still refreshes `.gh_archived_repos` in the root | | `--limit N` | Process only the first N repos (useful for a quick test) | | `--quiet` | Suppress per-repository chatter; keep the final summary | | `--org NAME` | GitHub only. Org or personal account to sync (default: basename of `--root` / cwd) | | `--list-teams` | GitHub only. List your teams in the org (with repo counts) and exit; orgs only | | `--host HOST` | GitLab only. Host to sync (default: `gitlab.com`); `https://` and a trailing `/` are accepted, and so is a web port (`host:8443`) | | `--group PATH` | GitLab only. Sync one group and its subgroups instead of every group you belong to. Covers every project the group shows you, including when you belong only to a subgroup of it (projects directly in the group and in sibling subgroups count). If the group itself cannot be read, the run syncs your subgroups under it and prints one stderr warning naming them and what was skipped; it fails only when nothing under the group is reachable | | `--from-list FILE` | GitLab only. Sync the paths in FILE (the `--porcelain` format; blank lines and `#` comments ignored) with no discovery and no `glab` |
A flag that belongs to the other provider is rejected with an error, not ignored.
GitLab
# Every project in every group you belong to on gitlab.com, into ~/dev/gitlab.com/
bash "${CLAUDE_SKILL_DIR}/scripts/ghsync.sh" --provider gitlab --list-repos
bash "${CLAUDE_SKILL_DIR}/scripts/ghsync.sh" --provider gitlab
# One group subtree on a self-managed host, into ~/dev/gitlab.example.com/
bash "${Read more
name: ghsync description: "Bulk clone and keep in sync every repo you can access on GitHub or GitLab. GitHub: an org's repos via your teams plus the org repo list, or a personal account's repos. GitLab (--provider gitlab --host <host>): every project in every group you belong to, with nested subgroups and projects shared into those groups, laid out under its path_with_namespace; --group narrows to one subtree, and --porcelain / --from-list split discovery from cloning for hosts reachable only from another network. Deduplicates, then clones new repos and fast-forward syncs existing ones (and their worktrees) into a <path>/<repo>-main + <path>/worktree layout. TRIGGER when the user types /ghsync, wants to clone or sync all org repos, their personal repos or all GitLab group projects, asks to mirror everything they have access to on GitHub or a GitLab host, is onboarding into a new enterprise, org or GitLab group, or wants to refresh their local checkouts to latest."
ghsync: mirror and sync every repo you can access on GitHub or GitLab
Onboarding into a new enterprise means finding and cloning dozens of repos by hand, then drifting out of date. This skill does both halves: it **discovers** everything you can reach and **keeps it in sync**.
- **First run** — clones every accessible repo into a worktree-friendly layout.
- **Every run after** — fast-forward updates repos already on their default
branch, updates their worktrees, and clones anything new. It never clobbers local work: repos with uncommitted changes or on a non-default branch are fetched but not pulled, and reported in the summary.
It is **org-agnostic**: point it at any GitHub org, GitHub Enterprise host, **personal account**, or a **GitLab host** (gitlab.com or self-managed) with `--provider gitlab`; see [GitLab](#gitlab) below. On GitHub: the script detects the account type itself. For an organization it unions the teams you belong to with the org's repo list (so direct-collaborator and public repos are included even with no team membership); for a personal account it uses the account's repo list (private repos included when it's your own account).
How to run it
The script lives next to this file. Claude Code writes this skill's directory into the script paths below when it loads the skill, so each path is already absolute:
# Org is derived from the directory you run in. To mirror the "meridianhub"
# org, run from a directory named meridianhub:
cd ~/dev/github.com/meridianhub
bash "${CLAUDE_SKILL_DIR}/scripts/ghsync.sh"The org defaults to the **basename of the directory you launch from**. So running inside `~/dev/github.com/meridianhub` syncs the `meridianhub` org into that directory. Override the org name or target directory explicitly when they differ:
bash "${CLAUDE_SKILL_DIR}/scripts/ghsync.sh" --org meridianhub --root ~/dev/github.com/meridianhubWhat to do when invoked
1. **Confirm the target.** Run with `--list-repos` first (or `--list-teams` for an org) so the user sees which account and how many repos before any cloning. This doubles as a check that the derived account name is correct. 2. **Dry run on first use against a new org** (`--dry-run`) to preview clones and updates without touching disk. 3. **Run the real sync.** Stream the output; the run ends with a summary (up-to-date / updated / failed / uncommitted / branch issues / worktrees). 4. **Surface the exceptions.** Call out anything under *Failed*, *Uncommitted changes*, or *Not on default branch* — these are the repos the user may need to deal with manually.
Flags
| Flag | Effect | |------|--------| | `--provider github\|gitlab` | Which host type to sync (default: `github`) | | `--root DIR` | Directory to clone into; an explicit `--root` must already exist, in every mode (GitHub default: current directory; GitLab default: `~/dev/<host>` with any `:port` dropped, created on the first real sync) | | `--list-repos` | List the deduplicated accessible repos and exit | | `--porcelain` | Machine-readable repo list: one path per line to stdout (GitHub: the repo name; GitLab: `path_with_namespace`), all chatter to stderr; implies `--list-repos`. Consumed by `/ghreport` and by `--from-list`. | | `--dry-run` | Show what would be cloned/updated without making changes. On GitLab it creates no directory and writes no `.gh_archived_repos`; on GitHub it still refreshes `.gh_archived_repos` in the root | | `--limit N` | Process only the first N repos (useful for a quick test) | | `--quiet` | Suppress per-repository chatter; keep the final summary | | `--org NAME` | GitHub only. Org or personal account to sync (default: basename of `--root` / cwd) | | `--list-teams` | GitHub only. List your teams in the org (with repo counts) and exit; orgs only | | `--host HOST` | GitLab only. Host to sync (default: `gitlab.com`); `https://` and a trailing `/` are accepted, and so is a web port (`host:8443`) | | `--group PATH` | GitLab only. Sync one group and its subgroups instead of every group you belong to. Covers every project the group shows you, including when you belong only to a subgroup of it (projects directly in the group and in sibling subgroups count). If the group itself cannot be read, the run syncs your subgroups under it and prints one stderr warning naming them and what was skipped; it fails only when nothing under the group is reachable | | `--from-list FILE` | GitLab only. Sync the paths in FILE (the `--porcelain` format; blank lines and `#` comments ignored) with no discovery and no `glab` |
A flag that belongs to the other provider is rejected with an error, not ignored.
GitLab
# Every project in every group you belong to on gitlab.com, into ~/dev/gitlab.com/
bash "${CLAUDE_SKILL_DIR}/scripts/ghsync.sh" --provider gitlab --list-repos
bash "${CLAUDE_SKILL_DIR}/scripts/ghsync.sh" --provider gitlab
# One group subtree on a self-managed host, into ~/dev/gitlab.example.com/
bash "${A Claude Code plugin - and a set of standalone skills for any AI assistant: skills and agents for AI-native development. In Claude Code it runs locally against your own codebase using whichever model you already pay for.
Other skills on ai-native-toolkit.
ab-equivalence
Compare two versions of an LLM-directed document - an original (teacher) and a candidate (student) - across a transfer set and…
assess-findings
Renders the /assess report from the deterministic run-context.json and the layer scorecard - the scorecard, the verbatim…
assess-pr
The /assess end-of-run offers - open a PR with the report, track the Top 3 Actions in the user's issue tracker, freeze the…
assess
Assess a codebase's readiness for AI agent contributors using the layered contract model, and generate a complexity hotspot SVG…
More skills from other plugins.
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
ask-matt
Ask which skill or flow fits your situation. A router over the skills in this repo.
Questions about ghsync.
- Which coding agents can use ghsync?
- ghsync installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.

