Skip to content

Latest commit

 

History

History
175 lines (135 loc) · 9.43 KB

README.md

File metadata and controls

175 lines (135 loc) · 9.43 KB

GitHub

Status

GitHub CLI for fetching issues, PRs, comments, reviews, code, and activity — with built-in caching.

A token-efficient GitHub client tailored for AI workflows. Parses issue/PR URLs or raw numbers, fetches bodies + comments + reviews, and outputs clean Markdown or JSON. Responses are cached in a local SQLite DB so repeated reads don't burn rate limit.


Key Features

Feature Description
URL or number Auto-detects owner/repo from the git remote when you pass just a number
PR review threads review pulls unresolved threads grouped by file
Comment filters Limit by count, recency, reactions, or exclude bots
Search Issues, PRs, and code search with state/type filters
Notifications & Activity Inbox triage and event feeds without leaving the terminal
SQLite cache Every fetched object is reusable; status shows cache stats
Interactive mode Run tools github with no args for a guided menu

Quick Start

# Fetch an issue or PR (URL or number if repo is inferrable)
tools github issue https://github.com/owner/repo/issues/123
tools github pr 456

# Include comments with filters
tools github pr 456 --no-bots --min-reactions 1 --last 20

# Review threads for a PR (only unresolved, grouped by file)
tools github review 456 --unresolved-only --group-by-file

# Search issues / PRs
tools github search "flaky test" --type pr --state open

# Code search
tools github code-search "TODO(matt)"

# Notifications (unread in last 7 days)
tools github notifications --state unread --since 7d

# Activity feed
tools github activity --since 1d --type pr

# Fetch a raw file
tools github get https://github.com/owner/repo/blob/main/src/index.ts --clipboard

# A repository's releases as one Markdown document
tools github releases oven-sh/bun --limit 3
tools github releases facebook/react --since 2026-01-01 --no-prereleases -o react-releases.md

# Safe stack-aware merge (retargets dependents before optional branch delete)
tools github merge 123 --rebase           # stack-safe: restack+FF (preserves SHAs); children only retargeted
tools github merge 123 --rebase --restack-children  # also rebase + force-push each direct child now
tools github merge 123 --rebase --no-restack  # legacy GitHub rewrite rebase (breaks cascades)
tools github merge 123 --ff-only          # true FF (base ref → head SHA; keeps commit SHAs)
tools github merge 123 --squash --delete-branch   # subject = PR title (#123), body = one bullet per commit
tools github merge 123 --squash --dry-run         # print the generated squash message, merge nothing
tools github merge 123 --squash --subject "feat: ship (#123)" --body "* one\n* two"   # explicit values win
tools github merge https://github.com/owner/repo/pull/123 --merge --delete-remote

# Cache + rate limit status
tools github status

Subcommands

Command Description
issue <url-or-num> Fetch an issue with optional comments
pr <url-or-num> Fetch a PR with optional comments and review comments
merge <url-or-num> Merge a PR; retarget stack dependents before optional branch delete
comments <url-or-num> Fetch only the comment thread
review <url-or-num> Review threads (unresolved-only, group-by-file, JSON/MD)
search <query> Search issues and PRs
code-search <query> GitHub code search
get <file-url> Fetch raw file contents
notifications List inbox notifications with filters
activity Personal activity / events feed
releases <repo> A repository's releases as one Markdown document
status Auth, rate limit, and cache stats

merge — stack-safe merge

GitHub only auto-retargets dependent PRs when a branch is deleted via the web UI "Delete branch" button. Deleting via gh pr merge --delete-branch, the REST API, or git push --delete closes child PRs instead (cli/cli#1168).

tools github merge always:

  1. Merges without deleting the head branch via the merge API:
    • --merge / --squash → GitHub pulls.merge
    • --rebase (default stack-safe) → local restack head onto base if needed, git push --force-with-lease, then true FF of base → head (preserves SHAs). The restack starts from the tip the PR's base had before its last force push (GitHub records it on the PR as a base force push), so a child whose parent a previous merge rebased drops exactly the parent's old commits. --restack-children also rebases each direct child right away (git rebase --onto <base> <old-parent-tip>, the gh stack cascade). It is off by default: it force-pushes branches outside this merge and strands their own children (2026-10-13: #496 showed 635 files instead of 62). Pass --no-restack for legacy GitHub merge_method=rebase (rewrites SHAs; breaks cascading children).
    • --ff-only (alias --ff) → true fast-forward: move base ref to head SHA (git.updateRef with force=false after a compare preflight). Preserves commit SHAs; fails if base is not an ancestor of head.
  2. Finds open PRs whose base is the merged head branch
  3. Retargets each onto the merged PR's base. GitHub native stacks reject REST PATCH /pulls/{n} {base} with "Cannot change the base branch because the pull request is part of a stack." The client then POST /repos/{owner}/{repo}/stacks/{n}/unstack and retries the PATCH. That keeps the child PR number and conversation. Close-and-reopen is never the happy path. If retarget still fails after the parent SHA is already on the base, stdout prints MERGED plus recovery commands (non-zero exit). It does not throw as if the merge never happened.
  4. (--rebase --restack-children only) Restacks dependents so the next PR is FF-able. Without it a child is rebased at its own merge.
  5. Only then, if --delete-branch / --delete-remote, deletes the remote head ref

Exactly one of --merge, --rebase, --squash, or --ff-only is required. All progress logs go to stdout.

--squash writes a real commit message by default. Without --subject the subject is the PR title, a space, and (#N) (not doubled when the title already ends with it). Without --body the body is every PR commit subject, oldest first, as * <subject> bullets separated by single newlines. The PR-commits endpoint stops at 250 commits, so past that the compare endpoint is walked page by page; if the collected count still differs from the PR's own commit count the merge refuses rather than write a short body. The CLI prints the message and says which part was generated and which came from a flag. Commit text is passed to the GitHub API as data, never through a shell. --merge is unchanged: no default message is generated there. --dry-run resolves the PR, lists dependents, prints the squash message and stops before any write.

releases — release notes as one document

tools github releases <owner/repo> lists a repository's releases (a github.com URL works too) and writes them as one Markdown document: a title, then for each release a heading with the tag, the name and the date, the release body, and the release URL. The newest release comes first.

tools github releases oven-sh/bun --limit 3                        # the three newest, to stdout
tools github releases facebook/react --since 2026-01-01 --no-prereleases -o react-releases.md
tools github releases https://github.com/vercel/next.js --since 1m --clipboard
tools github releases oven-sh/bun --limit 5 --json                 # machine-readable
Option Description
-L, --limit <n> Keep only the newest N releases
--since <date> Only releases published since a date: ISO 8601, or relative (7d, 2w, 3m)
--no-prereleases Skip pre-releases. Drafts are always skipped
--oldest List the oldest first instead of the newest first (applied after --limit)
--json Emit { tag, name, publishedAt, prerelease, url, body } per release instead of Markdown
-o, --output <file> Write to a file instead of stdout
-c, --clipboard Copy to the clipboard instead of stdout (with -o, both happen)

The listing is read page by page (100 per page) until it runs out, the limit is met, or, with --since, a whole page is older than the date. GitHub orders that listing by creation time, not publication time, so a release published long after its commit date, more than a page away from where its date puts it, can be missed by --limit and --since; reading every page would cost one request per 100 releases. Dates are UTC days. Headings inside a release body move down two levels so they nest under that release's own heading. It only reads. A token (GITHUB_TOKEN or gh auth) raises the rate limit and lets it read private repositories.

Run any subcommand with --help for its full option list. The most common flags (--format ai|json, --limit, --last, --no-bots, --min-reactions, --stats, --clipboard) work across multiple subcommands.


Auth

Uses gh auth credentials when available, otherwise works unauthenticated with public rate limits. tools github status tells you which mode you're in and how many calls remain.


Related tools

  • genesis-tools:github skill — read-only GitHub browsing for agents
  • genesis-tools:github-pr skill — PR review feedback workflow