Skip to content

Template bug: zero-results prose printed to stdout before the --json check breaks agent JSON consumers (6+ published CLIs) #3450

Description

@mvanhorn

Pattern

Generated CLIs print a zero-results prose line to stdout (exit 0) before the flags.asJSON check, so --json/--agent consumers get unparseable output on zero hits:

if len(results) == 0 {
    fmt.Fprintf(cmd.OutOrStdout(), "No results for %q\n", query)
    return nil
}
if flags.asJSON { ... }

Piped agent consumers fail with JSON decode failed: Expecting value: line 1 column 1 (char 0). This broke the last30days engine's Techmeme source in production (2026-07-04) and was fixed for techmeme search in mvanhorn/printing-press-library#1440 (see .printing-press-patches/search-json-dates-contract.json there for the contract: JSON mode must emit [] - note a nil Go slice marshals to null, so the empty slice must be initialized).

Confirmed sites (manual read of each, printing-press-library@main)

  • library/productivity/techmeme/internal/cli/author.go (~L52-55 vs the asJSON check at ~L109) - same CLI, NOT covered by verify-skill drift detected with printing-press-library #1440
  • library/other/ufo-goat/internal/cli/files_search_ufo.go (~L60-63 vs L66)
  • library/other/ufo-goat/internal/cli/new_files.go (~L112-119 vs L122)
  • library/media-and-entertainment/blu-ray/internal/cli/history.go (~L75-78 vs L79)
  • library/developer-tools/company-goat/internal/cli/company_funding.go (~L234-238 vs L255) - worse: calls os.Exit(5) before ever reaching the JSON branch
  • library/sales-and-crm/eu-tenders/internal/cli/search.go (~L51-54 vs L61) - partial: only the "not synced yet" early-exit is affected

Unverified candidates: eu-tenders/internal/cli/deadline_heat.go, eu-tenders/internal/cli/notices_helpers.go.

Why this is generator work

Per printing-press-library AGENTS.md triage: a defect reproducing across multiple published CLIs is a template bug - fix the generator so future prints are correct, then sweep the published library. Suggested template contract: every command's zero-results path must branch on output mode first; JSON mode emits an initialized empty slice (never prose, never null), prose stays for human mode only.

🤖 Generated with Claude Code

https://claude.ai/code/session_01BWuSdMPdQLnAeh65wTeG3L

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions