Status: ✅ Done (2026-07-28)
List pull requests for a repository, with analysis data — the plural counterpart to pull-request (which shows a single PR by number). Supports a free-text search filter, a target-branch filter, and an open/closed state filter.
codacy pull-requests [provider] [organization] [repository]
codacy pull-requests # auto-detect from git remote
codacy pull-requests gh my-org my-repo
codacy prs gh my-org my-repo --search "fix flaky"
codacy prs gh my-org my-repo --base main
codacy prs gh my-org my-repo --state closed
codacy prs gh my-org my-repo --output json
| Option | Short | Description |
|---|---|---|
--search <text> |
-q |
Filter by free-text search matched against the PR title or author handle (maps to the API's textQuery param) |
--base <name> |
-B |
Filter by target (base) branch name (maps to the API's targetBranch param) |
--state <state> |
-S |
open (default) or closed — maps to the API's search classification param (see below) |
--limit <n> |
-n |
Maximum number of pull requests to return (default: 100, max: 1000) |
--search/-q and --base/-B match the flag names already established elsewhere in the CLI (findings/patterns use -q, --search; --base avoids colliding with -b, --branch's different meaning — "the analysed branch" — in ls/directories/issues).
The API's search param (not exposed directly) toggles between a last-updated classification (default) and a merged one; leaving it undefined returns closed/merged PRs mixed in with open ones with no way to tell them apart (no Status column in this command's table) — the same problem repository.ts's "Open Pull Requests" table works around by filtering status === "open" || "Open" client-side. This command instead always passes an explicit search value:
--state open(default) →search = "last-updated"--state closed→search = "merged"— namedclosedon the CLI, notmerged, because that API classification also returns closed-but-not-merged PRs, so"merged"would be a factually wrong label to expose.
listRepositoryPullRequests — AnalysisService.listRepositoryPullRequests(provider, org, repository, limit, cursor, search, textQuery, targetBranch).
Pages through cursor up to --limit (page size capped at 100 per request), same loop shape as findings/issues. The pagination-warning guard checks total > items.length || hasMore (not just total) — the API can omit pagination.total, and falling back to total = items.length would otherwise mask a page still pending behind a live cursor. The same latent bug (guard was total > items.length alone) was fixed in findings.ts at the same time, since that's where this loop shape was copied from.
Table format, columns:
| ✓ | # | Title | Branches | Issues | Complexity | Duplication | Coverage | Updated |
|---|
- ✓ is the leading column — the gate verdict is the first thing you scan a PR list for, so it reads before the number and title. It's dim
⋯whileisAnalysingis true (rather than falling through to a hard ✗ for gate data that isn't final yet), otherwise ✓/✗/-from quality + coverageisUpToStandards— a shared fix informatStandards()(utils/formatting.ts), so it also applies torepository's andpull-request's uses of the same helper. - Branches shows
originBranch → targetBranch(truncated at 30) — same pairingpull-request.ts's About section uses, so the "Branch" label doesn't collide withrepository.ts's Open PR table (which showsoriginBranchalone under the same header) or ambiguously imply which branch--basefilters on. - Issues, Complexity, Duplication, Coverage reuse the same shared helpers as
repository's "Open Pull Requests" table (buildGateStatus,formatPrIssues,formatPrCoverage,formatDelta) andpull-request's own Analysis section — gate-colored the same way. The metric order matches therepositoriescommand (issues → complexity → duplication → coverage) so the same four metrics read in the same order across the CLI. - Complexity/Duplication read
quality.deltaComplexity/quality.deltaClonesCountfirst, via the sharedprQualityMetric()helper. The API populates the flat top-level fields and the nestedqualityobject inconsistently — the pull-request endpoints returnquality.deltaComplexitybut omit the top-leveldeltaComplexity(while still sending a top-leveldeltaClonesCount), so reading only the flat field rendered every PR's complexity as "no data".qualityis the newer, structured shape (same direction ascoveragevs. the deprecated top-level coverage fields), so it wins with the flat field as fallback. Applied torepositoryandpull-requesttoo, which had the same bug. - Coverage is hidden entirely when no listed PR has a coverage value (
hasAnyPrCoverage()). A repo without coverage set up returnsdiffCoverage.cause(e.g.MissingRequirements) and no numbers on any PR, so the column would otherwise be a full column of-. The helper lives next toformatPrCoverageso both agree on what counts as "has data". - A zero issue count renders as a bare
0, not+0/-0—-0reads as a negative number, and the sign adds nothing when nothing was added or fixed. Matches the rulepull-request.ts's Files table andformatFileDeltaalready use;formatDeltaalready did the same for complexity/duplication. - Missing values render as a dim
-, notN/A— informatDelta,formatPrCoverage, andformatPrIssues, matching the convention already used byformatStandards,formatCountCell, andformatCoverageCell. Being shared helpers, this also applies torepository's Open PR table andpull-request's Analysis section. (N/Asurvives elsewhere in the CLI for non-metric fields — grades, dates, author names, default branch — which is a separate sweep.) - Shows pagination warning (suggesting
--limit,--search,--base,--state) if more results exist than were fetched. - JSON whitelist includes
pullRequest.originBranch/targetBranch(both rendered in the Branches column),coverage.isUpToStandards/quality.isUpToStandards(needed to reproduce the ✓ column programmatically), thequality.*mirrors of the flat metric fields (the API omits some of the top-level ones, and these are what the table actually renders), andquality.resultReasons/coverage.resultReasons(which drive the per-metric gate coloring — without them a JSON consumer can't tell which gate passed or failed). It dropspullRequest.status/pullRequest.owner.name(neither rendered anywhere in the table) — matching thepickDeepconvention inAGENTS.md("only includes fields that correspond to what's shown in the console table").
File: src/commands/pull-requests.test.ts — 19 tests.
Manually verified against gh codacy codacy-website: --base main → 0 results (repo's PRs all target master), --base master → matches the unfiltered count, --search "AI" → narrows to exactly the one matching title, --output json shape correct, and [provider] [org] [repo] auto-detect from the git remote works from inside a real checkout.
Also verified against gh codacy codacy-worker (a repo with no coverage set up): PR #1218 renders Complexity +21 (previously N/A, since the API omits the flat deltaComplexity), the Coverage column is dropped from the table, and codacy pr gh codacy codacy-worker 1218 shows the same +21 in its Analysis section.