Skip to content

Issue PR Triage

Griffen Fargo edited this page Jun 10, 2026 · 2 revisions

Issue & PR Triage

Coco's triage workflow (#882) brings issue and pull-request review into the same terminal-native muscle memory as the rest of the workstation. Two complementary surfaces:

  • CLI: coco issues and coco prs print formatted, filterable lists to stdout — composable with grep, jq, and other pipeline tools.
  • TUI: gi (issues) and gP (PR triage) inside coco ui open list-on-left / inspector-on-right surfaces with full action keys.

Both surfaces work across GitHub, GitHub Enterprise, and GitLab. Coco auto-detects the forge from the git remote host and drives the matching CLI — gh for GitHub / GitHub Enterprise, glab for GitLab. On GitLab the views operate on merge requests and issues with the same keybindings. Anything that works from the shell works inside the workstation; authentication is whatever your gh auth status / glab auth status reports — no separate token setup.

Requirements

  • The matching CLI installed and authenticated:
    • gh CLI (gh auth login) — GitHub / GitHub Enterprise
    • glab CLI (glab auth login) — GitLab
  • The current repository has a GitHub or GitLab remote (origin or fallback)

Coco surfaces a friendly empty state when either requirement is missing, so the failure mode is discoverable rather than a stack trace. For self-hosted vanity hostnames, see forgeHosts.

CLI

coco issues

List issues in the current repository.

# Open issues (default)
coco issues

# Filter by state, assignee, author, labels
coco issues --state closed
coco issues --assignee @me        # shorthand: coco issues --mine
coco issues --author gfargo
coco issues --label bug,critical
coco issues --search "auth flow"

# Tune the page size
coco issues --limit 50

# JSON output for pipelines
coco issues --json | jq '.[] | .title'

# Disable / force-refresh the on-disk cache
coco issues --no-cache
coco issues --refresh

Every option maps 1:1 to the corresponding gh issue list flag, so anything gh accepts here works the same way.

coco prs

Same shape, for pull requests.

# Open PRs (default)
coco prs

# State (PRs have a merged variant distinct from closed)
coco prs --state merged
coco prs --state all --limit 5

# Targeting
coco prs --draft
coco prs --mine                   # = --author @me
coco prs --base main
coco prs --head feature/auth

# Free-form search syntax
coco prs --search "is:open is:public-good"

Disk cache

Both commands cache responses on disk under ~/.cache/coco/github/ (or $XDG_CACHE_HOME/coco/github/) with a 5-minute TTL. Triage is bursty — you tend to run coco issues a dozen times in a few minutes, then not touch it for hours — so the cache pays for itself quickly.

# Force a fresh gh call (writes through to cache)
coco issues --refresh

# Skip the cache entirely (no read, no write)
coco issues --no-cache

# Clear the entire triage cache directory
coco cache clear-github

The repo header tag on cache hits reads cached Ns ago so you can always tell when a list is fresh vs warm.

TUI

Inside coco ui:

Chord Surface
g i Issues triage list
g P Pull-request triage list (capital P; lowercase g p keeps targeting the existing single-PR action panel for the current branch)

The two triage surfaces are independent of the single-PR view — g p continues to show the rich action panel for the current branch's PR with status checks, reviews, and merge buttons. Use g P when you want to triage across many PRs.

Layout

Each surface follows the standard workstation chrome:

  • List (main panel): rows of #number state glyphs author branch title [labels] with color-coded state, draft/mergeable glyphs, and review-decision markers. Cursor with j / k or arrows; PageUp / PageDown page through.
  • Inspector (right pane): metadata for the cursored row — state, author, branches, labels, assignees, mergeable status, review decision, timestamps, URL.
  • Inspector hydration: when the cursor rests on a row for ~250ms, Coco fetches the item's body, comments, and (for PRs) reviews and status checks. Rapid j/k navigation never fires a gh call — only intentional rests. The hydrated detail caches per session, so cursoring back to a previously-viewed item shows instantly.

The header shows a ▼ <preset> indicator next to the row count — press f to cycle.

Action keys

Both views support the same scanning + acting flow. Destructive actions (close, reopen, merge, approve, request-changes) route through Coco's standard y-confirm prompt.

Common (both views)

Key Action
j / k / arrows Move the cursor
PageUp / PageDown Page through the list
/ Filter the visible list by free text (title, author, labels, assignees)
f Cycle through canned filter presets (see below)
O Open the cursored item's URL in the browser
y Yank the cursored item's URL to the clipboard
c Add a comment (multi-line prompt; Ctrl+D to submit)
L Add a label (single-line prompt)
A Add an assignee (single-line prompt; defaults to @me)
< / Esc Pop the view, returning to the previous surface

Issues view only

Key Action
x Close the cursored issue (y-confirm)
X Reopen the cursored issue (y-confirm — useful to undo a stray close)

PR triage view only

Key Action
m Merge — prompts for strategy (merge / squash / rebase), then y-confirm
x Close without merging (y-confirm)
a Approve (y-confirm)
R Request changes — multi-line review body prompt (Ctrl+D to submit), then y-confirm

These match the chord set on the single-PR action panel (g p) exactly, so muscle memory carries over. The triage view targets the cursored PR by number rather than the current branch. Every mutating action — merge, approve, close, comment, label, assign for MRs; comment, label, assign, close, reopen for issues — works the same on GitLab as on GitHub.

GitLab nuance: GitLab has no native "request changes" review verb, so R posts a note prefixed Requested changes: instead of a formal review event. Merge (m) on GitLab offers the squash / rebase strategies. See Multi-Forge Support for the full list of forge differences.

Filter presets

f cycles through canned filters that compile to the same --state / --assignee / --author / etc. knobs the CLI accepts. The active preset shows in the surface header (▼ open, ▼ mine, ...).

Issues: open → closed → mine (open + assigned to me) → assigned → wrap

Pull requests: open → draft → mine (open + authored by me) → assigned → closed → merged → wrap

The presets aren't 1:1 across the two surfaces by design:

  • Issues have no draft / mergeable concept, so those presets are skipped on the issue list.
  • PRs have a merged state distinct from closed; issues don't.
  • mine semantics differ: for issues it means I'm the assignee (issues are tasks people pick up); for PRs it means I authored it (PRs are work people post).

Inspector content

Pre-hydration, the inspector renders the metadata available from the list payload — title, state, author, branches, labels, mergeable / review markers, timestamps, URL.

Post-hydration (250ms cursor rest), the inspector gains:

Issues

  • Body excerpt (first 6 non-empty lines, with a … N more lines trailer)
  • Comments section — total count + 3 most recent in @author: body form

Pull requests

  • Body excerpt
  • Status checks summary — pass / fail / pending counts
  • Reviews section — per-reviewer state (approved / changes requested / commented) with inline body excerpt
  • Comments section

Empty sections are omitted — a low-activity issue or PR doesn't pad the right pane with empty headings.

Cache behavior across mutations

When you mutate a row through one of the action keys (c, L, A, x, m, etc.), Coco:

  1. Drops the in-memory list cache for the active surface so the next render refetches with fresh state.
  2. Drops the mutated item's detail entry from the per-session detail cache so the inspector hydrates fresh on the next cursor rest.
  3. Wipes the on-disk cache (~/.cache/coco/github/) so any subsequent coco issues / coco prs CLI call sees the change immediately.

This is intentionally aggressive — the cost of a refetch is much smaller than the cost of showing stale data right after an action.

Tips

  • Pair the views. Cycle gigP to triage issues that gate PRs and PRs that close issues. The breadcrumb in the header shows the path.
  • / and f compose. Set a preset with f, then / to narrow within it. Filter survives across navigation.
  • Use --json for one-offs. A quick coco issues --label bug --json | jq '.[] | "\(.number) \(.title)"' is faster than launching the workstation for read-only spelunking.
  • Open in browser, then come back. O opens the cursored URL; the workstation keeps running. Close the browser tab and your cursor is exactly where you left it.

Related

Clone this wiki locally