fj pr list cannot filter by label/assignee/author, though fj issue list filters by label and assignee #108

Closed
opened 2026-06-11 00:01:28 +00:00 by stephen · 2 comments
Owner

Observation

fj pr list can only filter by state. There is no way to narrow pull requests by label, assignee, or author, even though fj issue list already offers label and assignee filters against the same forge.

fj pr list --help exposes only --state, --limit, --page, --json, --web:

$ fj pr list --help
  -s, --state <STATE>    Filter by state [default: open] [possible values: open, closed, all]
  -L, --limit <LIMIT>    Maximum number of pull requests to fetch [default: 30]
      --page <PAGE>      Page of results to fetch [default: 1]
      --json             Emit JSON instead of a table
      --web              Open the pull request list in your browser

The CLI struct carries nothing else (src/cli/pr.rs:69-88, ListArgs: only state, limit, page, json, web), and the API options it feeds carry nothing else either (src/api/pull_core.rs:100-104):

pub struct ListOptions {
    pub state: State,
    pub limit: u32,
    pub page: u32,
}

The asymmetry is the sharp part: the issue path already does this. fj issue list accepts --label and --assignee (src/cli/issue.rs:67 ListArgs), and the issue ListOptions threads them straight into the query string (src/api/issue.rs:66-71, 99-102):

if let Some(l) = opts.labels {
    query.push(("labels".into(), l.into()));
}
if let Some(a) = opts.assignee {
    query.push(("assignee".into(), a.into()));
}

Forgejo serves PRs through the issues model and accepts the same labels/assignee/poster query parameters on GET /repos/{owner}/{repo}/pulls (and /issues?type=pulls), so the gap is purely at the CLI/options layer, not the API's. Neither pr list nor issue list exposes an author/--author filter at all.

Why it matters

"Show me the PRs I need to act on" is the spine of the daily review loop, and it is almost always a filtered query: PRs with the needs-review label, PRs assigned to me, PRs opened by a given teammate. gh pr list --label <l> --assignee <a> --author <u> is table stakes, and fj markets parity with gh for the surface Forgejo exposes. Today a team scripting triage on fj pr list can only slice by open/closed/all and must fall back to fj api with hand-built query strings, the exact escape hatch the tool is supposed to remove. The fact that issue list already has the filters makes the omission read as an oversight rather than a Forgejo limitation, and it breaks the muscle memory of anyone who learned the issue command first.

Possible directions (sketches)

  • (sketch) Add --label and --assignee to fj pr list, mirroring src/cli/issue.rs:67 flag-for-flag, and thread them into pull_core::ListOptions and its query builder the same way src/api/issue.rs:99-102 does.
  • (sketch) Add --author to both pr list and issue list (Forgejo's poster/created_by query param) to close the gh --author gap in one move.
  • (sketch) Factor the shared label/assignee/author filter flags into a small reusable clap Args struct so issue and PR list stay in lockstep and cannot drift again.

Confidence

High. The flags' absence is verified from both fj pr list --help and the source (src/cli/pr.rs:69-88, src/api/pull_core.rs:100-104), and the working contrast on the issue side is verified (src/cli/issue.rs:67, src/api/issue.rs:66-71, 99-102). The only open question is the exact Forgejo query-param spelling for PR author filtering, which is an implementation detail, not a question of whether the gap exists.

## Observation `fj pr list` can only filter by state. There is no way to narrow pull requests by label, assignee, or author, even though `fj issue list` already offers label and assignee filters against the same forge. `fj pr list --help` exposes only `--state`, `--limit`, `--page`, `--json`, `--web`: ``` $ fj pr list --help -s, --state <STATE> Filter by state [default: open] [possible values: open, closed, all] -L, --limit <LIMIT> Maximum number of pull requests to fetch [default: 30] --page <PAGE> Page of results to fetch [default: 1] --json Emit JSON instead of a table --web Open the pull request list in your browser ``` The CLI struct carries nothing else (`src/cli/pr.rs:69-88`, `ListArgs`: only `state`, `limit`, `page`, `json`, `web`), and the API options it feeds carry nothing else either (`src/api/pull_core.rs:100-104`): ```rust pub struct ListOptions { pub state: State, pub limit: u32, pub page: u32, } ``` The asymmetry is the sharp part: the issue path already does this. `fj issue list` accepts `--label` and `--assignee` (`src/cli/issue.rs:67` `ListArgs`), and the issue `ListOptions` threads them straight into the query string (`src/api/issue.rs:66-71`, `99-102`): ```rust if let Some(l) = opts.labels { query.push(("labels".into(), l.into())); } if let Some(a) = opts.assignee { query.push(("assignee".into(), a.into())); } ``` Forgejo serves PRs through the issues model and accepts the same `labels`/`assignee`/`poster` query parameters on `GET /repos/{owner}/{repo}/pulls` (and `/issues?type=pulls`), so the gap is purely at the CLI/options layer, not the API's. Neither `pr list` nor `issue list` exposes an author/`--author` filter at all. ## Why it matters "Show me the PRs I need to act on" is the spine of the daily review loop, and it is almost always a filtered query: PRs with the `needs-review` label, PRs assigned to me, PRs opened by a given teammate. `gh pr list --label <l> --assignee <a> --author <u>` is table stakes, and `fj` markets parity with gh for the surface Forgejo exposes. Today a team scripting triage on `fj pr list` can only slice by open/closed/all and must fall back to `fj api` with hand-built query strings, the exact escape hatch the tool is supposed to remove. The fact that `issue list` already has the filters makes the omission read as an oversight rather than a Forgejo limitation, and it breaks the muscle memory of anyone who learned the issue command first. ## Possible directions (sketches) - *(sketch)* Add `--label` and `--assignee` to `fj pr list`, mirroring `src/cli/issue.rs:67` flag-for-flag, and thread them into `pull_core::ListOptions` and its query builder the same way `src/api/issue.rs:99-102` does. - *(sketch)* Add `--author` to both `pr list` and `issue list` (Forgejo's `poster`/`created_by` query param) to close the gh `--author` gap in one move. - *(sketch)* Factor the shared label/assignee/author filter flags into a small reusable `clap` `Args` struct so issue and PR list stay in lockstep and cannot drift again. ## Confidence High. The flags' absence is verified from both `fj pr list --help` and the source (`src/cli/pr.rs:69-88`, `src/api/pull_core.rs:100-104`), and the working contrast on the issue side is verified (`src/cli/issue.rs:67`, `src/api/issue.rs:66-71`, `99-102`). The only open question is the exact Forgejo query-param spelling for PR author filtering, which is an implementation detail, not a question of whether the gap exists.
Author
Owner

Converted to backlog item rasterstate/fj#113 (p2, size M).

Tracked there with task / priority / reason / acceptance / dependencies. Keeping this open with the converted label as the originating opportunity.

Converted to backlog item `rasterstate/fj#113` (p2, size M). Tracked there with task / priority / reason / acceptance / dependencies. Keeping this open with the `converted` label as the originating opportunity.
Author
Owner

Derived backlog item rasterstate/fj#113 merged (PR #130). Closing this opportunity per the issue state machine.

Derived backlog item rasterstate/fj#113 merged (PR #130). Closing this opportunity per the issue state machine.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
rasterstate/fj#108
No description provided.