Building gh-rs: Minimal GitHub CLI in Rust
The official GitHub CLI (gh) is a comprehensive tool, but its scope has expanded significantly. For day-to-day coding agent automation and minimal terminal setups, developers often need only a fraction of its surface: authentication, repository inspection, pull requests, and issues.
Moreover, default CLI setups frequently write personal access tokens in plaintext into configuration files under ~/.config/gh/hosts.yml.
I built gh-rs to provide a compact, secure GitHub CLI in Rust with first-class JSON output for shell pipelines and AI agents.
+--------------------+ +-----------------------+ +---------------------+
| Terminal / Agent | | gh-rs (Rust CLI) | | OS Keychain |
| gh-rs repo list | -----> | Clap + Octocrab | <----> | Windows Credential |
| --json | | Tokio Async Runtime | | SecretService/macOS |
+--------------------+ +-----------------------+ +---------------------+
|
v
+-----------------------+
| GitHub REST / GraphQL |
+-----------------------+
OS Keychain Authentication
Instead of writing bearer tokens to disk, gh-rs implements the OAuth Device Authorization flow (RFC 8628).
- Running
gh-rs auth logindisplays a one-time verification code and opens the GitHub activation URL. - Once approved in the browser,
gh-rsexchanges the device code for an OAuth access token. - The token is immediately committed to the operating system's native keychain using the
keyringcrate:- Windows: Windows Credential Manager.
- macOS: Apple Keychain.
- Linux: Freedesktop Secret Service over D-Bus.
No access token ever lands in plaintext dotfiles or environment export scripts.
The Four Primitives
gh-rs deliberately restricts its scope to four primary commands:
# 1. Authentication
gh-rs auth login
gh-rs auth status
gh-rs auth logout
# 2. Repository management
gh-rs repo clone owner/repo
gh-rs repo create my-tool --public
gh-rs repo list --limit 10 --json
gh-rs repo view AkashPriyadarshii/kharcha-core
# 3. Pull requests
gh-rs pr list --limit 5
gh-rs pr view 42 --json
gh-rs pr diff 42
gh-rs pr merge 42 --method squash
# 4. Issue tracking
gh-rs issue create --title "Fix race condition" --body "Details here"
gh-rs issue list --json
gh-rs issue close 12
Agent-Ready JSON Output
Every query command supports the --json flag. This outputs unformatted, structured JSON suitable for direct piping into jq or consumption by coding agents like Claude Code:
gh-rs repo list --limit 5 --json | jq '.[].name'
Output fields use predictable schemas without terminal escape sequences or paging delays.
Binary Footprint
gh-rs is compiled with full Link-Time Optimization (LTO) and binary stripping:
- Binary footprint: 12.4MB on disk.
- Cold start:
--helpexecutes in approximately 50ms. - Memory: Under 18MB peak RSS during active API calls.
More Essays
Building jev-curate: Fast Synthetic Dataset Sifter in Rust
Filtering synthetic training data with TypeSafe AI Jev: streaming JSONL and Parquet rows through calibrated System One gates at 70ms latency with zero memory accumulation.
systemsBuilding jev-git: Sub-Second Git Reflex Gate in Rust
Screening staged git diffs for leaked secrets, destructive payloads, and AI hallucinations in 80ms using TypeSafe AI Jev System One.
systemsBuilding jev-scout: Zero-Hallucination Crate and Repo Scout
Preventing AI package hallucinations: discovering real crates and GitHub repositories using live registry APIs and TypeSafe Jev speculative fan-out scoring.