I star repositories I want to find again, but that doesn’t preserve a copy. An owner can delete a repository, make it private, rewrite a tag, or remove a large-file object. An account can disappear too. I’d rather have the code saved before any of that happens.

As of August 4, 2026, my own starred-repository archive held 302 repositories and used about 50 GB. Some are tools I use. Some are references I expect to read later. Some probably made sense to me for fifteen minutes in 2019. I do not want the continued existence of any of them to depend on me noticing before somebody else removes one.

That is why I built StarSync. It takes the repositories starred by one GitHub account and maintains them as local Git checkouts. It adds new stars, refreshes the history that is still available, and retains repositories I later unstar.

What to preserve

A quick clone is better than a bookmark, but it is not quite the archive most people think they made. The default branch is only one view of a repository. Useful work may live on another branch or behind a tag. Git LFS content is stored separately from ordinary Git objects. Upstream can also move a tag and make an older target difficult to recover later.

For anything I mean to preserve, I want:

  • the repository’s available branches and tags;
  • enough identity to recognize it after an owner transfer or rename;
  • Git objects checked for integrity;
  • the original remote recorded without credentials embedded in it;
  • old references retained rather than pruned merely because upstream stopped advertising them;
  • a record of local changes, because an edited checkout is no longer a clean archive copy.

I back up the archive volume too. Saving everything locally still leaves me with a single copy until I do that.

Start a StarSync archive

StarSync 2 requires Git and either Bun or Node. It also requires an empty directory for a new format-2 archive. Set a GITHUB_TOKEN for the GitHub account whose stars you want, then initialize the directory:

bunx starsync init D:/archives/stars

The token is used to identify the account and list its stars. Clone and fetch authentication still comes from Git itself, such as Git Credential Manager or SSH keys. StarSync does not put the token in command arguments, Git remotes, or archive metadata.

Preview the first synchronization if you want to see the work before it starts:

bunx starsync sync --dry-run D:/archives/stars

Then build the archive:

bunx starsync sync D:/archives/stars

New repositories are cloned into staging directories and checked before being moved into their final folders. Existing checkouts are matched by GitHub’s stable repository ID rather than by a name that an owner can change. Dirty or divergent repositories are blocked instead of overwritten. Other repositories can still sync when one fails.

StarSync checks free space before a write-heavy operation and refuses to start below a minimum reserve. That is a guard against beginning on an already-full disk, not a prediction of what 302 repositories will need. A sync can still consume the remaining space. My own full-archive test proved that point by filling the volume I had sized for it.

Verify what you saved

Running a sync without errors tells me what happened during that run. Verification tells me what is on disk now:

bunx starsync verify D:/archives/stars

The normal verification is local, read-only, and does not need a token. It checks Git object integrity, origins, repository identity, duplicate IDs, local changes, archive ownership, and folders that no longer match a renamed or transferred repository.

I run verification periodically even when I haven’t added stars. It can find damaged Git objects or local edits that happened since the last sync.

Repository renames and transfers are previewed separately:

bunx starsync rename D:/archives/stars
bunx starsync rename --apply D:/archives/stars

Check the rename preview before applying it. The stable GitHub repository ID establishes whether the new name belongs to the project already in the archive.

Keep doing it

I choose the sync interval based on how much history I’m willing to miss. Verification and volume backups run separately. I also leave disappeared and unstarred repositories in place. Deleting them automatically would defeat the reason the archive exists.

You do not need StarSync to adopt that practice. A scheduled script that lists your stars, clones what is missing, fetches all available references without pruning, and checks the resulting Git objects gets most of the way there. I built StarSync to handle the identity checks, blocked checkouts, and other cases I kept running into.

Changelog

  • August 18, 2026: First published.

Where this came from