Skip to content

Feature: Add --select flag to gh api for server-side field selection via GraphQL #13334

@SebTardif

Description

@SebTardif

Problem

When using gh api with REST endpoints, the entire API response is downloaded and --jq filters it client-side. For many common operations, this transfers far more data than needed:

Call Downloaded Used Waste
gh api repos/cli/cli --jq '.default_branch' ~15KB (entire repo object, 100+ fields) 6 bytes ~99.9%
gh api repos/cli/cli/issues/1 --jq '.title' Full issue + all comments ~20 bytes >95%

Meanwhile, the high-level commands already solve this. When you run gh issue view 1 --json title,body, it generates a targeted GraphQL query via IssueGraphQL(fields) in api/query_builder.go. But this infrastructure is only accessible through commands like gh issue/pr/repo view — the raw gh api command that LLM agents and automation tools rely on has no way to leverage it.

Related: #13333 (batch mode for gh api)

Proposed Solution

Add a --select flag to gh api that translates recognized REST endpoint patterns into targeted GraphQL queries, fetching only the specified fields from the server.

Usage

# Server-side field selection — only ~100 bytes transferred
gh api repos/{owner}/{repo} --select name,defaultBranchRef

# Combine with --jq for minimal transfer + formatted output
gh api repos/{owner}/{repo} --select defaultBranchRef --jq '.defaultBranchRef.name'

# Works for issues
gh api repos/{owner}/{repo}/issues/42 --select title,state,labels

# Works for pull requests
gh api repos/{owner}/{repo}/pulls/7 --select title,isDraft,reviewDecision

How it works

  1. Recognizes the REST endpoint pattern (e.g., repos/{owner}/{repo})
  2. Validates fields against the known lists (RepositoryFields, IssueFields, PullRequestFields)
  3. Builds a GraphQL query using the existing RepositoryGraphQL(), IssueGraphQL(), or PullRequestGraphQL() functions from api/query_builder.go
  4. Sends the query to the GraphQL endpoint
  5. Unwraps the GraphQL response envelope so the output matches the REST structure
  6. Passes the result through --jq / --template as normal

Supported patterns

REST pattern GraphQL resource Builder function
repos/{owner}/{repo} Repository RepositoryGraphQL()
repos/{owner}/{repo}/issues/{n} Issue IssueGraphQL()
repos/{owner}/{repo}/pulls/{n} PullRequest PullRequestGraphQL()

Unsupported endpoints produce a clear error with the list of supported patterns.

Field validation

Fields are validated against the same lists used by gh repo/issue/pr view --json:

$ gh api repos/cli/cli --select nonexistent
Error: unknown Repository field: "nonexistent"
Available fields:
  id
  name
  nameWithOwner
  ...

Architecture Fit

This feature reuses 100% of the existing query_builder.go infrastructure. No new GraphQL query building code is needed — it calls the same RepositoryGraphQL(), IssueGraphQL(), and PullRequestGraphQL() functions that power the high-level commands.

The implementation is ~160 lines of new code (plus tests) in a single new file select_fields.go, with minimal changes to api.go.

Prototype

Working implementation with 20 unit + integration tests: SebTardif/cli@feat/api-batch (second commit on the branch).

Files:

  • pkg/cmd/api/select_fields.go — Pattern matching, query building, response unwrapping
  • pkg/cmd/api/select_fields_test.go — 15 unit tests
  • pkg/cmd/api/api.go — Flag registration, validation, execution path
  • pkg/cmd/api/api_test.go — 5 integration tests

All existing tests pass. Lint clean.

Why this matters

LLM coding agents (GitHub Copilot, Cursor, etc.) increasingly use gh api as their primary GitHub interface. They make dozens of gh api calls per session. This feature would let them request only the fields they need, reducing:

  • Network bandwidth — by 90-99% for typical calls
  • GitHub server load — GraphQL naturally fetches less data
  • Agent response latency — less data to parse

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions