Skip to content

Bun GH CLI

Bun GH CLI is a comprehensive TypeScript SDK that wraps the entire GitHub CLI (gh) into a type-safe, ergonomic API. Instead of constructing shell strings by hand, you get autocompletion, typed option objects, and structured JSON output — all running on Bun’s fast shell primitives. Published as @jadujoel/gh-cli, it’s designed to make GitHub automation scripts as easy to write as regular TypeScript code.

  • Complete gh Coverage — Wraps 30+ command groups: auth, repo, pr, issue, release, workflow, search, secret, codespace, project, and more — totalling ~1,860 lines of typed surface area
  • Typed Options for Every Command — Each subcommand has a dedicated TypeScript interface (e.g. PrCreateOptions, IssueListOptions, RepoCreateOptions), so your editor catches mistakes before the shell does
  • Structured JSON Output — Every command returns a GhOutput object with .json<T>() for zero-boilerplate typed parsing of gh’s JSON mode
  • Smart Flag Builder — Automatically converts TypeScript options to CLI flags: single-char keys become -x, multi-char become --kebab-case, arrays repeat the flag, and booleans toggle presence
  • Ready-Made Automation Scripts — Ships with 12 scripts in scripts/ for common tasks: clone all repos, list PRs, gather repo stats, search repos, list workflow runs, and more
  • Unified Namespace — A single gh export gives you access to everything, or import individual modules like repo, pr, issue for tree-shaking
  • Raw Escape Hatch — Need something custom? gh.exec(["any", "args"]) drops down to raw gh invocation while still giving you the typed GhOutput back

The core is a small command builder that maps TypeScript objects to CLI arguments via Bun’s shell tagged-template (Bun.$):

import { gh } from "@jadujoel/gh-cli"
// List open PRs with typed JSON output
const result = await gh.pr.list({
state: "open",
limit: 10,
json: "number,title,author",
})
const prs = result.json<Array<{ number: number; title: string; author: { login: string } }>>()
for (const p of prs) {
console.log(`#${p.number} ${p.title} by ${p.author.login}`)
}

The included scripts/ directory demonstrates real-world usage — for example, clone-all-repos.ts fetches your full repo list and clones any that are missing locally, while repo-stats.ts aggregates star counts, fork counts, languages, and disk usage across all your repositories.

LanguageTypeScript
RuntimeBun
Shell IntegrationBun.$ (tagged template shell)
Package@jadujoel/gh-cli (npm)
LintingBiome
Testingbun:test (~720 lines of tests)
DependenciesZero runtime deps — only gh CLI on PATH

The test suite in index.test.ts validates both the SDK structure and live API calls. Structure tests verify that all 30+ command groups and their subcommands are present and correctly typed. Integration tests actually invoke gh to confirm that commands like auth.status(), issue.list(), and repo.list() return well-formed GhOutput objects with the expected fields. This ensures the flag-building logic produces correct CLI invocations end-to-end.

The source code is available on the project’s GitHub repository.