auto-discoveredEdit on GitHub

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.

bash
1# Open issues (default)
2coco issues
3
4# Filter by state, assignee, author, labels
5coco issues --state closed
6coco issues --assignee @me        # shorthand: coco issues --mine
7coco issues --author gfargo
8coco issues --label bug,critical
9coco issues --search "auth flow"
10
11# Tune the page size
12coco issues --limit 50
13
14# JSON output for pipelines
15coco issues --json | jq '.[] | .title'
16
17# Disable / force-refresh the on-disk cache
18coco issues --no-cache
19coco 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.

bash
1# Open PRs (default)
2coco prs
3
4# State (PRs have a merged variant distinct from closed)
5coco prs --state merged
6coco prs --state all --limit 5
7
8# Targeting
9coco prs --draft
10coco prs --mine                   # = --author @me
11coco prs --base main
12coco prs --head feature/auth
13
14# Free-form search syntax
15coco 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.

bash
1# Force a fresh gh call (writes through to cache)
2coco issues --refresh
3
4# Skip the cache entirely (no read, no write)
5coco issues --no-cache
6
7# Clear the entire triage cache directory
8coco 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:

ChordSurface
g iIssues triage list
g PPull-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)

KeyAction
j / k / arrowsMove the cursor
PageUp / PageDownPage through the list
/Filter the visible list by free text (title, author, labels, assignees)
fCycle through canned filter presets (see below)
OOpen the cursored item's URL in the browser
yYank the cursored item's URL to the clipboard
cAdd a comment (multi-line prompt; Ctrl+D to submit)
LAdd a label (single-line prompt)
AAdd an assignee (single-line prompt; defaults to @me)
< / EscPop the view, returning to the previous surface

Issues view only

KeyAction
xClose the cursored issue (y-confirm)
XReopen the cursored issue (y-confirm — useful to undo a stray close)

PR triage view only

KeyAction
mMerge — prompts for strategy (merge / squash / rebase), then y-confirm
xClose without merging (y-confirm)
aApprove (y-confirm)
RRequest 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