gh-select

How it works

Where the repository list comes from, how it is cached, what runs on your machine and what counts against GitHub's rate limits.

View as Markdown

Authentication

gh-select has no login of its own. It reads the token for your default host from the GitHub CLI and uses it for the REST and GraphQL APIs. The token is read once per run. When gh has no token, the program exits with could not authenticate with GitHub (run gh auth login).

Deleting repositories is the only feature that needs an extra scope. See Deleting repositories.

The repository list

The list holds every repository you own, belong to through an organization, or collaborate on, de-duplicated and ordered by recent activity. Your repositories and your stars load as parallel REST pages. Fork parents and languages, which the REST listing leaves out, come from one small GraphQL lookup. Around 300 repositories load in about a second.

Each entry carries its visibility, language, star count, last push, license, disk size, fork parent and archived state. Those fields drive the columns, the details block and the filter tokens.

Caching

The list is cached on disk and follows a stale-while-revalidate rule:

  1. With a cache present, the list renders immediately from it.
  2. When the cache is older than GH_SELECT_CACHE_TTL seconds (1800 by default), a refresh runs in the background and the list updates when it finishes.
  3. With no cache, the program fetches first and prints Loading repositories…, so the screen is never empty.

-n or --no-cache skips the cache and fetches fresh data. gh select refresh refetches and exits, which suits cron jobs. Starred repositories have their own cache, shown instantly and refreshed once per session.

The cache files are versioned. Upgrading to a release that adds repository fields refetches once. See files and paths for the names and the directory.

Local clones

gh-select finds repositories you already cloned and tags them local. The scan runs in the background on every start and is cached in locals.json for the next one, so the tags appear without waiting.

  • It searches GH_SELECT_SCAN_DIRS first, then the clone directory, the current directory and your home directory.
  • A repository is matched by its git remote, so a renamed folder is still recognized. HTTPS, SSH and ssh:// remotes all work.
  • Git worktrees and submodules count.
  • Dependency and cache folders such as node_modules, vendor, target, dist, build, venv, Library and snap are skipped, and so are hidden folders other than .config and .dotfiles.
  • One scan reads at most 40000 directories, and a folder with more than 4096 entries is treated as data and skipped.
  • When a repository is cloned twice, the most recently used copy wins.

Rate limits

GitHub gives each account separate budgets for search, core REST, GraphQL and code search. Other tools using your gh login draw from the same budgets.

BucketWindowUsed by
search1 minuteGitHub search scope
core1 hourListing, trees, files, releases, downloads
graphql1 hourFork parents and languages
code_search1 minuteShown for completeness

GitHub search waits until you pause typing for 350 ms before it fires, and fetches a single page of 30 results per query. gh select limits and the ? overlay show usage, how far each window has run, time to reset, and how soon the current pace would empty a bucket. Reading the limits does not count against any of them.

Cloning, saving and downloading

  • A clone runs git clone through your own git, so your SSH keys and credential helpers apply. The URL is https://github.com/OWNER/REPO.git.
  • A partial clone runs git clone --filter=blob:none --sparse, then a sparse checkout of the marked paths. Folders alone use cone mode. Individual files switch to non-cone patterns anchored at the repository root. Blobs are fetched when needed.
  • Saving files and downloading release assets use the GitHub API directly and need no git.
  • Opening a URL uses open on macOS, rundll32 on Windows, and xdg-open or wslview elsewhere. Copying uses pbcopy, clip.exe, wl-copy, xclip or xsel, whichever exists.

What is written to disk

Only the cache, the saved theme and any files you ask for. gh-select never changes your repositories' contents, and deleting a repository on GitHub never removes a local clone.

Edit this page on GitHub

Last updated on

On this page