feat(mail): add 'mail list' for sibling symmetry - #5
Merged
Conversation
calendar, contacts, and drive all offer 'list'; mail offered only 'search'. 'mail list --max 5' therefore failed with cobra's 'unknown flag: --max' (the parent command swallowed 'list' as a positional arg), which reads like a flag inconsistency between siblings rather than a missing command - a first-hand confusion this closes. 'mail list' shows the most recent inbox messages (in:inbox), with --max/-m and --ids matching 'mail search' exactly. Flag parity is pinned by test. Audit note: all sibling list/search commands were checked for divergent flags; --max/-m is uniform across calendar events, contacts list/search, drive list/search, and mail search. This missing command was the only gap.
piekstra-dev
approved these changes
Aug 12, 2026
piekstra-dev
left a comment
Collaborator
There was a problem hiding this comment.
Automated PR Review
Reviewed commit: 5a460a8c271f
Profile: reviewer - Posting as: piekstra-dev
Summary
| Reviewer | Findings |
|---|---|
| go:implementation-tests | 0 |
| policies:conventions | 0 |
Reviewer Coverage
| Reviewer | Status | Inspected | Skipped | Constraints |
|---|---|---|---|---|
| go:implementation-tests | complete_broad | mailcmd/list.go, mailcmd/list_test.go, mailcmd/mail.go | unavailable | unavailable |
| policies:conventions | complete_broad | mailcmd/list.go, mailcmd/mail.go | unavailable | Canonical shared-standards docs (cli-common/docs, .github) were not present in the checked-out context, so this review relied only on in-repo sibling commands (search, calendar, contacts, drive) for convention comparisons rather than the source-of-truth policy text. |
0 PR discussion threads considered. 0 summarized; 0 resolved.
Completed in 1m 32s | $0.87 | claude-sonnet-5 | cr 0.10.268
| Field | Value |
|---|---|
| Model | claude-sonnet-5 |
| Reviewers | go:implementation-tests, policies:conventions |
| Engine | claude_cli · claude-sonnet-5 |
| Reviewed by | cr · piekstra-dev |
| Duration | 1m 32s wall · 2m 01s compute |
| Cost | $0.87 |
| Tokens | 58 in / 8.3k out |
Per-workstream usage
| Workstream | Model | In | Out | Cache read | Cache create | Cost | Duration |
|---|---|---|---|---|---|---|---|
| orchestrator-selection | claude-sonnet-5 | 6 | 1.8k | 57.0k | 13.0k | $0.12 | 22s |
| go:implementation-tests | claude-sonnet-5 | 18 | 2.3k | 296.3k | 25.5k | $0.28 | 38s |
| policies:conventions | claude-sonnet-5 | 28 | 3.9k | 458.0k | 25.2k | $0.35 | 51s |
| orchestrator-rollup | claude-sonnet-5 | 6 | 373 | 68.2k | 15.4k | $0.12 | 8s |
piekstra
added a commit
to open-cli-collective/google-readonly
that referenced
this pull request
Aug 12, 2026
…mail list (#175) ## Why Delivers the credential/profile UX overhaul to gro by bumping **google-cli-common v0.2.0 → v0.3.0** ([#4](open-cli-collective/google-cli-common#4), [#5](open-cli-collective/google-cli-common#5), [#6](open-cli-collective/google-cli-common#6), [#7](open-cli-collective/google-cli-common#7)) and registering the new `profiles` command group. Driven by a first-hand incident: the active profile's token went stale, every command failed with a bare `oauth2: "invalid_grant"`, and it read as "gro is dead" — when other profiles were fine and there was no way to list them short of dumping the macOS keychain. ## What gro users get - **`gro profiles list [--check] [--json]`** — every stored profile, the account email it holds, an active marker with *where* the selection came from, and (with `--check`) per-profile live token health: `ok` / `expired or revoked` / `error`. - **`gro profiles use <profile>`** — deliberate, visible switching of the active binding. - **Attributed auth errors** — verified live against Google's token endpoint: ``` credential google-readonly/work (selected via config.yml credential_ref) can no longer authenticate: oauth2: "invalid_grant" "Bad Request"; other profiles may be unaffected - run 'gro profiles list' to check them, or 'gro init' to re-authenticate this one ``` - **`gro init`** announces which profile/account it will (re)authenticate before any prompt or write, and `gro init --profile <name>` adds a NEW account without touching the active profile's token. - **`gro mail list`** — the audit of item 6 found no `--max` divergence among siblings; the real gap was the missing `list` command (cobra's `unknown flag: --max` came from the parent command). - **`gro config show`** names the credential-ref source. ## Changes here - go.mod bump (also pulls cli-common v0.4.1 → v0.5.0 for `credstore.ListProfiles`) - `internal/cmd/root`: register `profilescmd.NewCommand()`; root test pins it - README: `gro mail list` examples + command reference A follow-up docs PR documents the profile model (`profiles` commands, `init --profile`, and the decision to keep the `default` profile). Full flow smoke-tested end-to-end with a hermetic HOME + file-backend keyring, including the real `invalid_grant` path. `make check` green.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
A flag-consistency audit found no actual
--maxdivergence — every sibling list/search command (calendar events,contacts list/search,drive list/search,mail search) uniformly takes--max/-m. The real gap:mail listdoesn't exist while every sibling group haslist. Sogro mail list --max 5failed with:…because cobra treated
listas a positional arg to the parentmailcommand and choked on the flag — reading like a broken/inconsistent flag rather than a missing command (a first-hand confusion).What
mail list— most recent inbox messages (fixed queryin:inbox), equivalent tomail search "in:inbox". Anything narrower/wider stayssearch's job (per command-surface.md:list= paginated collection,search= list with a query).searchexactly:--max/-m(default 10) and--idsfor piping; parity pinned by test.mailhelp updated.Tests
Command-surface tests (use/args/flags), success,
--ids, and no-results paths via the existing mock factory.make checkgreen.