Skip to content

Add built-in jq filtering - #203

Merged
robzolkos merged 2 commits into
mainfrom
add-built-in-jq-filtering
Aug 20, 2026
Merged

Add built-in jq filtering#203
robzolkos merged 2 commits into
mainfrom
add-built-in-jq-filtering

Conversation

@robzolkos

@robzolkos robzolkos commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

HEY’s structured commands gain a built-in --jq filter so agents and scripts can select response data without depending on an external binary. Existing output remains unchanged unless the new flag is supplied, and commands with dedicated raw output reject it explicitly.

Review readiness: ✅ Yes
Risk: 🟡 Medium — this adds a dependency and a shared output path used by every structured command
Decision: None

✅ Change — structured output can be filtered in-process

Before

Agent or script needs selected HEY response fields
└── Run a structured HEY command
    └── ❌ Pipe the full response through an externally installed jq binary

After

Agent or script needs selected HEY response fields
└── Run a structured HEY command with --jq
    └── ✅ Filter the response inside hey  ← CHANGED

--jq filters the full success envelope and implies JSON output. --quiet --jq filters data directly. Scalar strings print as text, compound values print formatted JSON, multiple results stream predictably, and error envelopes remain complete.

Raw-output paths (auth token, completion, skill display, the TUI, and --version) reject --jq rather than silently ignoring it.

✅ Evidence — behavior, safety boundaries, and compatibility are covered
  • ✅ Unit coverage exercises scalar, object, array, multiple, empty, environment, invalid, runtime-error, error-envelope, and large-integer behavior.
  • ✅ Command coverage exercises registration, conflicts, unsupported raw commands, and version behavior.
  • ✅ Terminal-focused coverage exercises CSI/OSC/C1 stripping, compound values, collision-safe hostile keys, and byte preservation for pipes.
  • ✅ Copilot feedback on explicit-empty filters and local-config trust was validated, fixed in ac9d4b1, replied to, and resolved with focused regressions.
  • CLI demo recording shows the flag in help and a built-in filtered response.
GOWORK=off make test                                      PASS
GOWORK=off make lint                                      PASS (0 issues)
GOWORK=off go test -race ./internal/output ./internal/cmd PASS
Binary smoke checks for filtering and unsupported paths   PASS
Independent adversarial diff review and re-review         PASS (no P2/blockers)
✅ Scope — existing output is preserved unless --jq is requested

Included:

  • global --jq parsing, validation, and help
  • gojq evaluation with environment lookup
  • full-envelope and quiet data-only filtering
  • terminal-safe result rendering without key loss
  • explicit unsupported raw-output behavior
  • README, embedded skill, dependency manifests, and CLI surface updates

Not included:

  • changing ordinary --json, --quiet, or styled output
  • filtering error envelopes
  • extending --jq to raw token, script, document, version, or TUI output
  • promising byte-for-byte compatibility with the external jq executable
➖ Delivery — no migration, configuration, or rollout work

gojq is linked into the existing Go binary. There are no migrations, feature flags, credentials, backfills, or deploy-order requirements. Rollback is a normal revert of this commit.

✅ Review decision — no unresolved product decision

Start with output semantics and terminal-safe rendering. Confirm that filtering only successful structured responses, while retaining complete error envelopes and rejecting dedicated raw formats, is the right boundary.

✅ Review path — output flow first, then regression coverage and user guidance
  1. internal/output/writer.go and internal/output/errors.go — filter execution, rendering, safety, and errors.
  2. internal/cmd/root.go and internal/cmd/local_config_trust.go — global flag wiring, raw-command boundaries, and machine-output trust behavior.
  3. internal/output/writer_test.go, internal/cmd/jq_test.go, and internal/cmd/local_config_trust_test.go — behavioral and security regressions.
  4. README.md, skills/hey/SKILL.md, go.mod, .surface, and help coverage — guidance, dependency, and public surface.

Origin and supporting links: Basecamp card

@robzolkos
robzolkos requested a review from a team as a code owner August 20, 2026 11:32
Copilot AI balanced review requested due to automatic review settings August 20, 2026 11:32

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 built-in --jq filtering for structured CLI responses.

Changes:

  • Integrates gojq with safe result rendering.
  • Wires global flag validation and raw-output exclusions.
  • Adds documentation, help text, surface metadata, and tests.

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 11 out of 12 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
.surface Records the new public flags.
README.md Documents filtering behavior and examples.
skills/hey/SKILL.md Updates agent guidance for built-in filtering.
go.mod Adds filtering and ANSI dependencies.
go.sum Locks new dependency checksums.
internal/output/writer.go Implements filtering and terminal-safe rendering.
internal/output/writer_test.go Tests filtering and output safety.
internal/output/errors.go Adds typed jq errors.
internal/cmd/root.go Registers and validates --jq.
internal/cmd/jq_test.go Tests command integration and exclusions.
internal/cmd/help.go Adds --jq to help output.
internal/cmd/help_test.go Updates help expectations.
Suppressed comments (1)

internal/cmd/root.go:227

  • An explicitly supplied empty value (--jq '' or --jq=) is treated as though the flag were absent. The earlier format selection also uses jqFlag != "", so this silently falls back to ordinary, unfiltered output instead of validating the expression or implying JSON; a script can unexpectedly receive the full response. Track flag presence with cmd.Flags().Changed("jq") separately from its value, and reject an empty expression while preserving the absent-flag case.
	if filter == "" {
		return nil

💡 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 Outdated
@robzolkos
robzolkos merged commit d4dd05c into main Aug 20, 2026
23 checks passed
@robzolkos
robzolkos deleted the add-built-in-jq-filtering branch August 20, 2026 11:53
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