Skip to content

Open a bundle's mail from the CLI with hey bundle view and hey contact threads - #378

Open
jeremy wants to merge 3 commits into
mainfrom
cli-bundle-mail
Open

Open a bundle's mail from the CLI with hey bundle view and hey contact threads#378
jeremy wants to merge 3 commits into
mainfrom
cli-bundle-mail

Conversation

@jeremy

@jeremy jeremy commented Sep 1, 2026

Copy link
Copy Markdown
Member

Fixes #156. Tracking: Basecamp card

A bundle row names a contact rather than a thread: hey box view lists it with no topic_id, and every plausible read — hey thread read with the posting id or the contact id — answered not-found. In the reporter's 500-posting Imbox sample, a third of the box was unreachable from the CLI. The TUI fixed this (f22746a…782e536) through two SDK operations, Postings().BundleUnseenPage and Contacts().ThreadsPage, and until now the TUI was their only caller.

hey bundle view <box-item-id> lists the unseen threads a bundle groups — the case the web app opens as the bundle view. The JSON carries the bundled contact next to the postings, because the contact id is what reads the rest once these threads are seen. A bundle with no unseen threads is not shown as an empty page; the notice says everything has been read and points at the contact's list.

hey contact threads <contact-id> lists every thread with a contact, seen and unseen — HEY's "All threads with …" list, and the only place a read-through bundle's mail lives, since a read bundle names no topic. This also replaces the undocumented single-page workaround through hey contact show's embedded postings, which contact show now cross-references.

Both are new mail.Source kinds riding the existing postings listing, so they answer --json, --styled, --markdown, --ids-only, --count, and the --limit/--all/--page cursors exactly as the box, label and collection listings do.

The failure stops lying. The sharpest point in #156: an agent that substitutes the bundle row's own id into hey thread read got a bare 404 and reported "no content" — silently wrong on exactly the senders worth automating. A thread-read not-found is now checked against the bundle route (one extra request, on the error path alone); when it answers, the error says the id is a bundle, names the sender, and gives both commands that read it. Any other id 404s on the probe too and keeps its original error.

Box listings and agent notes now say what a kind: "bundle" row is and how to open it, and hey bundle sits in the MAIL help category.

TMPDIR=/tmp/t make check green, including the regenerated .surface.


Summary by cubic

Fixes #156. The CLI can now open a bundle's mail, which hey box view listed but nothing could read — a bundled Imbox was unreachable outside the TUI. hey bundle view <box-item-id> lists a bundle's unseen threads, and hey contact threads <contact-id> lists every thread with a contact, seen and unseen — the only place a read-through bundle's mail lives.

Both ride the existing postings listing, so they answer --json, --styled, --markdown, --ids-only, --count, and the --limit/--all/--page cursors like the box, label, and collection listings do. A bundle with no unseen threads says where its mail lives instead of showing an empty page. README and agent notes document the new commands, and smoke tests cover them against a real server.

Error path

  • hey thread read with a bundle row's own id no longer answers bare "not found"; the 404 is probed against the bundle route and the error names the bundle and both commands that read it.
  • Any other id 404s on the probe too and keeps its original error; the probe costs one request on the error path alone.
  • hey contact threads replaces the single-page workaround via hey contact show embedded postings, which now cross-references it.
  • Box listings describe kind: "bundle" rows, and hey bundle sits in the MAIL help category.

Written for commit d3032fb. Summary will update on new commits.

Review in cubic

…t threads

A bundle row names a contact rather than a thread, so hey box view listed it
with no topic_id and nothing could read it — a third of a bundled Imbox was
unreachable outside the TUI. The SDK operations the TUI proved out now back
two CLI listings: hey bundle view <box-item-id> pages the unseen threads a
bundle groups, and hey contact threads <contact-id> pages every thread with
its sender, which is where a read-through bundle's mail lives.

Both ride the existing postings listing through two new mail.Source kinds,
so they answer every output format and cursor the box, label and collection
listings do. A bundle with no unseen threads says where its mail went
instead of showing an empty page.

The failure stops lying too: hey thread read handed a bundle row's own id
used to 404 as "not found", which agents read as "no content". A not-found
now gets checked against the bundle route, and when it answers, the error
names the bundle and both commands that read it.
@jeremy
jeremy requested a review from a team as a code owner September 1, 2026 10:20
Copilot AI balanced review requested due to automatic review settings September 1, 2026 10:20
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 1, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-01T10:47:57.863310Z d3032fb New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds CLI access to bundled mail, fixing #156 by reusing mail.Source pagination and improving bundle-ID errors.

Changes:

  • Adds hey bundle view and hey contact threads.
  • Extends mail sources and pagination for bundles and contacts.
  • Improves help, diagnostics, tests, and command-surface snapshots.

Tip

If you aren't ready for review, convert to a draft PR.
Click "Convert to draft" or run gh pr ready --undo.
Click "Ready for review" or run gh pr ready to reengage.

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
.surface Records new commands and flags.
AGENTS.md Documents bundle and contact sources.
internal/cmd/box.go Adds bundle guidance to box listings.
internal/cmd/bundle.go Implements bundle listing commands.
internal/cmd/bundle_test.go Tests new CLI behavior and errors.
internal/cmd/contacts.go Registers contact threads.
internal/cmd/contacts_show.go Cross-references contact threads.
internal/cmd/contacts_threads.go Implements contact-thread listings.
internal/cmd/help.go Adds bundle to MAIL help.
internal/cmd/help_test.go Updates help snapshot.
internal/cmd/postings_listing.go Supports meaningful empty-list notices.
internal/cmd/root.go Registers the bundle command.
internal/cmd/thread_source.go Diagnoses bundle IDs used as thread IDs.
internal/mail/page.go Reads bundle and contact pages.
internal/mail/page_test.go Tests the added page readers.
internal/mail/source.go Adds bundle and contact source kinds.
internal/mail/source_test.go Tests the new source constructors.
internal/tui/mail.go Handles new source kinds in navigation switches.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread internal/cmd/root.go
Comment thread internal/cmd/contacts.go
Comment thread internal/cmd/root.go
Comment thread internal/cmd/contacts.go
Comment thread internal/cmd/bundle_test.go Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7aba839d4f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread internal/cmd/root.go
Comment thread internal/cmd/contacts_threads.go
The README's listing inventory and Email examples now carry hey bundle view
and hey contact threads, per the command-documentation rule. Smoke coverage
discovers a bundle row in the Imbox — bundling an Imbox sender when the seed
data has none — and exercises bundle view, the thread-read misread error, and
contact threads with its pagination flags. The contact fixture's real-domain
address becomes a reserved example domain.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 4 files (changes from recent commits).

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread tests/smoke/contacts_test.go Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found and verified against the latest diff

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="internal/mail/page.go">

<violation number="1" location="internal/mail/page.go:153">
P2: When HEY returns `X-Total-Count` for a bundle or contact page, these readers discard it and report `Page.Total == 0`. Preserve `result.TotalCount` in both new `Page` values so generic listings can report accurate totals and truncation notices.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread internal/mail/page.go
A contact picked off the contact list may have no threads at all, which reads
as a pass without listing anything. An Imbox sender has at least one thread on
record, so the listing is asserted non-empty as well.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

No way to read messages inside a bundle posting

2 participants