Skip to content

fix(cli): keep author and channel in compact message output - #5764

Open
Cynthia427 wants to merge 2 commits into
block:mainfrom
Cynthia427:fix/compact-messages-keep-author-and-channel
Open

fix(cli): keep author and channel in compact message output#5764
Cynthia427 wants to merge 2 commits into
block:mainfrom
Cynthia427:fix/compact-messages-keep-author-and-channel

Conversation

@Cynthia427

Copy link
Copy Markdown

--format compact reduced every message to id, content, created_at, dropping the two fields a reader needs to act on a result.

Author. Every message read back in compact form is anonymous — a whole channel history returns as text with no senders, so "who said this" requires a second query in the full format.

Channel. messages search results span channels, so a hit carries no indication of where it came from: nothing to reply to, nothing to open. That is the one thing a search result exists to enable.

This is the documented default path for agents (--format compact is the global flag in the agent guide), so it is how messages are normally read, not an edge case. It is also quietly misleading rather than merely sparse — the fields are absent, so a caller can conclude the author or channel is unknown when the relay returned both. I hit exactly that reading a channel history and had to re-fetch the raw event to find where a message had been posted.

Compact stays compact: a pubkey and a UUID are small beside content, and the alternative is re-querying every result in full.

channel comes from the h tag — NIP-29 scopes by h, and reading e would yield a thread root that looks like a channel id, which is worse than none. It is omitted rather than emitted empty for events that legitimately have no channel (DMs), so absence stays distinguishable from a zero-length id.

6 tests; mutation-verified (removing either field fails exactly the test naming it), and the json format is asserted unchanged. fmt/clippy clean, 349 tests pass.

`--format compact` reduced every message to id, content and created_at. Two
fields a reader needs to act on a message were dropped:

- **pubkey**: every message read back in compact form is anonymous. A whole
  channel history comes back as text with no senders, so "who said this" needs
  a second query in the full format.
- **channel**: `messages search` results span channels, so a hit carries no
  indication of where it came from. There is nothing to reply to and nothing to
  open — the one thing a search result exists to enable.

This is the documented default path for agents (`--format compact` is the
global flag in the agent guide), so it is the normal way messages are read, not
an edge case. It is also quietly misleading rather than merely sparse: the
fields are absent, so a caller reasoning about a result can conclude the author
or channel is unknown when the relay returned both.

Compact stays compact. A pubkey and a UUID are small beside `content`, and the
alternative is re-querying every result in the full format, which costs more
than it saves.

`channel` is read from the `h` tag — NIP-29 scopes messages by `h`, and reading
`e` would yield a thread root that looks like a channel id, which is worse than
having none. It is omitted rather than emitted empty for events that legitimately
have no channel (DMs), so absence stays distinguishable from a zero-length id.

6 tests. Mutation-verified: removing either field fails exactly the test that
names it, and the json format is asserted unchanged.

Signed-off-by: Cynthia Rohr <cynthia.r@kreativreason.co>
@Cynthia427
Cynthia427 requested a review from a team as a code owner August 13, 2026 15:10
@Chessing234

Copy link
Copy Markdown
Contributor

the same compact projection is duplicated in feed.rs:46-58 and still drops both fields. buzz feed filters on #p across everything, so its results are cross-channel and cross-author by construction — the "a hit carries no indication of where it came from" argument lands harder there than on messages get. worth folding in, otherwise compact means two different shapes depending on the subcommand.

@Chessing234 Chessing234 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.

two things.

nest_skill.md:81 documents this exact shape — buzz --format compact messages get --channel <UUID> # [{id, content, created_at}] — and isn't updated here, so the installed agent skill would advertise a stale projection. that file also only reaches existing nests when NEST_SKILL_VERSION in nest.rs is bumped (#5776 is doing that for its own edit), so a doc fix without the bump wouldn't reach anyone already installed.

on the projection itself: the three format_events callers are cmd_get_messages, cmd_get_thread and cmd_search. search is the one that spans channels and genuinely needs channel; get and thread are already scoped by a channel the caller passed in, so there it repeats a known value on every row — which is the one place the compact-size argument actually bites. pubkey earns its place in all three.

…ted shape

Addresses both review points on block#5764.

feed.rs had a second copy of the compact projection, still dropping pubkey and
channel. It is now the same function, not a matching one: `format_events` is
shared from `messages`. Two copies is how these drifted in the first place,
and Projects v3 (block#5792) adds ten more projection sites in the same style, so a
matching-but-separate copy would not have stayed matching for long.

`buzz feed` is the sharpest case of the three. It filters on `#p` across
everything, so results are cross-channel and cross-author by construction — a
hit carrying neither is the least actionable output the CLI produces: nothing
to reply to, nothing to open.

nest_skill.md documented the old shape, so the installed agent skill taught
agents to expect [{id, content, created_at}] from a command that now returns
pubkey and channel too. A skill doc that disagrees with the tool is worse than
one that says nothing, because agents plan against it.

Two tests on the feed path: rows carry author and distinct channels survive,
and the compact key set matches what messages produces.

fmt clean, clippy clean, 8 projection tests pass.

Signed-off-by: Cynthia Rohr <cynthia.r@kreativreason.co>
@Cynthia427

Copy link
Copy Markdown
Author

Both addressed at c111446f4, and the second point changed the shape of the fix.

feed.rs — shared, not duplicated. You were right that a matching copy would drift, so feed now calls format_events from messages rather than keeping its own projection. That is also why the diff is smaller than expected: the local json!({...}) block is gone entirely instead of gaining two fields.

Your framing of why feed is the sharpest case is in the code comment, because it is the thing a future reader needs: buzz feed filters on #p across everything, so results are cross-channel and cross-author by construction — a hit carrying neither is the least actionable output the CLI produces.

Worth noting for timing: #5792 (Projects v3) adds issues.rs and projects.rs with ten more compact/JSON projection sites in the same style. Sharing one function now rather than fixing a second copy seems the better bet against that.

nest_skill.md:81 — updated to [{id, pubkey, channel, content, created_at}]. Agents plan against the installed skill, so a doc that disagrees with the tool is worse than one that says nothing.

Tests on the feed path specifically: rows carry the author, distinct channels survive across a cross-channel result set, and the compact key set matches what messages produces — that last one fails if the two are ever separated again.

fmt clean, clippy clean, 8 projection tests passing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants