Triage GitHub Issues from the Shell with gh search issues
Forty browser tabs of half-remembered issues is no way to find the one bug report you need. With gh search issues you can build repeatable searches, narrow them by repository, state, label and date, and check the result as JSON. The examples use GitHub CLI 2.87.3 on Linux, and about fifteen minutes is plenty if gh is already authenticated.
The route
Jump straight to the step you need, or tick off Done means at the end.
- You need: the
ghcommand, network access to your GitHub host, and an account that can see the repositories you want to search. - Login: not needed for every public query, but private or organisation-restricted results need a proper
gh auth loginsession. - Read-only: searching does not change any issue.
Warning
Do not put a token in a query, shell history or article example.
1. Check the installed command
Confirm the binary and version before relying on an option. This is an ordinary, unprivileged check:
$ command -v gh
/usr/bin/gh
$ gh --version
gh version 2.87.3 (2026-02-23)
The option set belongs to the installed release. A newer or older GitHub CLI may add or change fields, so keep this check near the start of scripts and troubleshooting notes.
Checkpoint
Read the command's own synopsis and JSON field list.
$ gh search issues --help
Usage: gh search issues [ <query> ] [flags]
JSON FIELDS
assignees, author, authorAssociation, body, closedAt, commentsCount,
createdAt, id, isLocked, isPullRequest, labels, number, repository,
state, title, updatedAt, url
2. Start with words or a quoted phrase
Arguments after gh search issues become search terms. Separate words are combined, while a quoted phrase keeps its spaces together:
$ gh search issues readme typo
$ gh search issues "broken feature"
The first query looks for both words. The second searches for the phrase. GitHub search still applies its normal matching rules, so neither promises an exact text match in every field. Use --match=title, --match=body or --match=comments when the location matters.
Tip
Do not add sudo. The command reads remote search results and needs no protected local files.
3. Narrow the search with flags
Flags suit conditions common enough to deserve a named option. This finds open issues assigned to the authenticated user:
$ gh search issues --assignee=@me --state=open --limit 20
--limit controls the maximum number fetched and defaults to 30. It is not a page size for an existing result set. Set it deliberately in scripts so a later default change cannot alter the amount of work.
Repository and owner filters combine with ordinary terms:
$ gh search issues "cache invalidation" --repo OWNER/REPOSITORY --state=open
$ gh search issues --owner=github --archived=false --limit 50
Replace OWNER/REPOSITORY with a real repository. The owner form searches repositories owned by that account or organisation. The --archived=false example is explicit because archived repositories are otherwise included by the installed command's search behaviour.
Other useful filters: --label, --author, --milestone, --language, --created, --updated, --comments, --reactions and --locked. Check the value shape with gh search issues --help rather than guessing.
4. Pass GitHub search qualifiers safely
GitHub's search syntax can express conditions that have no dedicated flag. For example, this finds issues that do not have the bug label:
$ gh search issues -- -label:bug
The -- tells the local command-line parser that the remaining value is a query argument. Without it, a query beginning with a hyphen can be mistaken for a gh option. Use the same boundary for other negative qualifiers:
$ gh search issues -- "repo:OWNER/REPOSITORY is:open -label:bug"
$ gh search issues -- "in:title regression state:open"
Quote the complete query when it contains spaces, operators or punctuation. For a simple query, separate arguments read more easily. GitHub documents qualifiers such as repo:, is:, label:, author:, assignee:, created: and updated:. Use the official syntax when a query needs more than the flags expose.
5. Include pull requests only when you mean to
Issue search normally returns issues. Add --include-prs when pull requests should be part of the result:
$ gh search issues --include-prs --owner=cli --limit 10
Do not infer the type from the title. In a JSON result, inspect isPullRequest. If you need only issues while using a broad qualifier query, add the documented is:issue qualifier after the query boundary:
$ gh search issues -- "repo:OWNER/REPOSITORY is:open is:issue"
Tip
This distinction stops a pull request being counted as an issue in reports or triage scripts.
6. Make output suitable for scripts
Human-readable output is convenient at a terminal but a poor interface for automation. Ask for named JSON fields and select one property with the installed jq integration:
$ gh search issues --repo OWNER/REPOSITORY --state=open --limit 10 \
--json number,title,state,url \
--jq '.[] | "#\(.number) \(.state): \(.title) \(.url)"'
#123 open: Example issue title https://github.com/OWNER/REPOSITORY/issues/123
The result number and title above are illustrative. Your repository determines the actual values. JSON field names are case-sensitive and must be listed in gh search issues --help. Keep the query and formatting expression in separate shell words or quote them carefully, because a misplaced quote can change the query before it reaches GitHub.
For a first verification, omit --jq and inspect the raw JSON:
$ gh search issues --repo cli/cli --state=open --limit 1 \
--json number,title,url
[{"number":14511,"title":"Use the tracked organization-owned fork as the pull request head","url":"https://github.com/cli/cli/issues/14511"}]
Checkpoint
That live check confirms the request, the selected fields and the authentication path. An empty array is a valid result, not automatically a failure.
7. Diagnose the common failure modes
If the command reports an authentication or permission error, check the current account without printing credentials:
$ gh auth status
Sign in or select the correct host using your normal organisation process. Do not paste a token into a command line. If a public query works but a private repository does not, check repository visibility and account access before changing search syntax.
- Too many results. Add a repository, owner, state, label or date qualifier and lower
--limit. - No results. Remove one condition at a time.
- Leading hyphen. A qualifier beginning with
-is the most common shell trap; retry it after--. - Unquoted phrase. It sends each word as a separate term.
Tip
The --sort option accepts fields such as created, updated, comments and reactions, and defaults to best-match. --order matters only when a sort is selected and defaults to desc. State those choices in a report so a reader can reproduce the ordering.
Done means
- Version confirmed. You checked the installed GitHub CLI version and help output.
- Explicit query. It states repository, state and result-limit choices where they matter.
- Protected qualifiers. Negative or punctuation-heavy qualifiers use
--and suitable shell quoting. - Pull requests decided. You chose whether they belong in the result.
- Data, not decoration. Automation requests named JSON fields and checks actual data rather than terminal formatting.
- Failures told apart. You can distinguish an empty search result, a syntax mistake and an authentication failure.