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.
gh command, network access to your GitHub host, and an account that can see the repositories you want to search.gh auth login session.Warning: do not put a token in a query, shell history or article example.
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
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.
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.
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.
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.
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.
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.
--limit.- is the most common shell trap; retry it after --.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.
-- and suitable shell quoting.