Views
Saved combinations of filters, sorting, grouping, and column choices for the issue list — personal or shared with a team.
A View is a saved configuration of how the issue list looks: which filters apply, how rows are sorted, what they’re grouped by, and which columns are visible. Build one once for a recurring question — “high-priority bugs on my team”, “what’s still in in_review past Friday”, “stale backlog older than 30 days” — and reuse it forever instead of rebuilding the filter chip-set every time.
Views are scoped to a team. They can be personal (creator-only) or shared (visible to every team member). There’s no separate “organization” visibility — at the org level, you’d build the same query as a team-shared view in the team that does the work.
Anatomy of a view
| Field | Notes |
|---|---|
name | Display name shown in the sidebar |
teamId | Required — every view is scoped to one team |
creatorId | The user who saved it |
isShared | true = visible to every team member; false = personal to the creator |
filters | JSON — the filter chip-set (status, priority, assignee, label, sprint, project, due-date range, …) |
sorting | JSON — sort field + direction (e.g. { field: "priority", direction: "desc" }) |
grouping | JSON — group rows by status, priority, assignee, project, label, or none |
columns | JSON — which columns are visible and in what order |
Filters/sorting/grouping/columns are stored as opaque JSON blobs the issue list interprets at render time. The schema isn’t versioned — if a new filter type ships, old views simply ignore it.
Building a view
- Open the issue list (
/my-issues, a project, a sprint, or a team page) and apply the filters you want. - Pick a sort order — click a column header — and a grouping if useful (
Group by status,Group by priority, etc.). - Hide or reorder columns from the column picker.
- Click Save view, give it a name, and choose Personal or Shared with team.
Saved views appear in the sidebar under the team they belong to, and in the view-picker dropdown above the issue list. Click any view to swap to its config; the URL updates so you can copy-paste-share the link.
Examples
| View name | Use case |
|---|---|
| My open issues | Filter assignee = me + status not in (done, cancelled), group by priority |
| Sprint board | Filter sprint = current + team = me, group by status, columns optimized for kanban |
| Bug triage queue | Filter label = bug + status in (backlog, todo), sort by created desc |
| Stuck in review | Filter status = in_review + updatedAt < 3 days ago, sort by updatedAt asc |
| Unassigned work | Filter assignee is null + status not in (done, cancelled), group by project |
| Overdue | Filter dueDate < today + status not in (done, cancelled), group by assignee |
CLI
pfai view wraps the REST surface with the standard kubectl-style verbs:
pfai view list # list views accessible to you in the current team
pfai view view <id> # show a view's full config
pfai view create --name "Bug triage" --team backend --shared \
--filters '{"label":"bug","status":["backlog","todo"]}' \
--sorting '{"field":"createdAt","direction":"desc"}'
pfai view update <id> --name "Bug triage v2"
pfai view delete <id>
--shared toggles isShared; omit it for personal views. The filter/sort/grouping/columns JSON shapes follow the issue-list state object — the easiest way to author one is to build it in the UI, then pfai view view <id> to copy the JSON.
REST endpoints
| Method · Path | Purpose |
|---|---|
GET /api/v1/views | List views — filter by teamId query param to scope |
POST /api/v1/views | Create — { name, teamId, isShared, filters, sorting, grouping, columns } |
GET /api/v1/views/{id} | Read |
PATCH /api/v1/views/{id} | Update any subset of fields |
DELETE /api/v1/views/{id} | Delete |
Visibility rules
| Field | Who sees it |
|---|---|
isShared = false | Only the creator |
isShared = true | Every team member (anyone with read access on the team’s issues) |
A non-creator team member can read a shared view but can’t edit or delete it — only the creator and team leads/owners can. There’s no “shared but read-only” middle state; sharing means full team access.
How views relate to other primitives
- Issues are the data; views are how the data renders. Changing a view never mutates issues.
- Sprints can be filtered by views (
sprint = X) but a sprint isn’t a view itself. - Teams scope every view — you can’t have an org-wide view without picking a team.
- Custom Fields values can be filtered the same way built-in fields are.
For workflows that span teams (e.g. “all unassigned bugs across the org”), build the view on each team and link them in a sidebar group, rather than trying to fit one global view that ignores team scope.
See also
The data model behind every view — statuses, priorities, custom fields all become filterable.
Every view is team-scoped; team leads can curate the shared-view set.
A common view filter — `sprint = current` is the start of every team's sprint board view.
If your view question is a chart, the built-in dashboards page may already answer it.