Skip to content

feat: boxel search can list a realm's cards without a query, and explains rejected filters#5275

Open
jurgenwerk wants to merge 2 commits into
mainfrom
cs-11651-boxel-search-discovery-and-errors
Open

feat: boxel search can list a realm's cards without a query, and explains rejected filters#5275
jurgenwerk wants to merge 2 commits into
mainfrom
cs-11651-boxel-search-discovery-and-errors

Conversation

@jurgenwerk

@jurgenwerk jurgenwerk commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

What was wrong

boxel search required a fully-formed query — there was no way to just "list what's in a realm." And writing a query needs a card's module URL up front, so if you didn't know it you'd guess, and the server rejected the bad filter with a cryptic cannot determine the type of filter 400 that didn't say how to fix it.

Why it matters

The software factory's agent reaches for boxel search to discover what cards a realm already has — before it knows any module URLs. It kept hitting both walls (required option '--query', then the cryptic 400) and stalling on what should be a simple "what's here?" lookup.

What this changes

  • --query is now optional — omit it to list every card in the realm(s). (An explicit empty filter, {"filter":{}}, is treated the same way.)
  • When the server can't classify a filter, the CLI prints an actionable hint: the valid filter shapes, and that field filters need an on type scope.
  • Skill docs lead with "list first to discover, then write a typed filter."

Testing

  • Unit tests for query normalization (omitted / {} / empty filter → list-all) and the error-hint text.
  • Searching with a real filter is unchanged.

…r errors

`boxel search` is a precise typed-query tool, but agents (and the factory) use
it to *discover* a realm's cards before they know any module URLs — and it
fought them: `--query` was required (no list-all), an empty filter 400'd, and
the realm's "cannot determine the type of filter" error said nothing about how
to fix it.

- `--query` is now optional; omitted → `{}`, which the federated-search
  endpoint already treats as "every card in the realm(s)". `boxel search
  --realm X` now lists everything.
- An explicit empty `filter` (`{"filter":{}}`) is normalized to list-all
  instead of 400'ing.
- On the unclassifiable-filter 400, print a hint enumerating valid filter
  shapes and the `on` requirement for field filters.
- Extracted `parseSearchQuery` / `searchErrorHint` as pure, unit-tested helpers.
- search skill: drop the false "or stdin" claim, document list-all discovery,
  the `on` requirement, and "don't pass an empty filter".

CS-11651.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jurgenwerk jurgenwerk changed the title boxel-cli: make search usable for discovery + actionable filter errors feat: boxel-cli search supports discovery (optional --query) + actionable filter errors Jun 18, 2026
@jurgenwerk jurgenwerk requested a review from Copilot June 19, 2026 11:38

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

This PR updates boxel-cli’s search command to support realm “discovery” by making --query optional (defaulting to a list-all query), normalizing an explicit empty filter, and appending actionable hints for a specific 400 error. It also adds unit tests for the new query normalization and error-hint behavior and updates the search skill documentation accordingly.

Changes:

  • Make --query optional and normalize omitted/empty/{"filter":{}} queries to list-all ({}).
  • Add a targeted, actionable hint for the “cannot determine the type of filter” 400 response.
  • Add vitest unit coverage for query normalization and hint generation; update skill docs to describe discovery-first usage.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
packages/boxel-cli/src/commands/search.ts Implements optional --query, normalization helper, and actionable error hinting.
packages/boxel-cli/tests/commands/search.test.ts Adds unit tests for parseSearchQuery and searchErrorHint.
packages/boxel-cli/plugin/skills/search/SKILL.md Updates skill documentation to describe discovery/list-all behavior and common pitfalls.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +153 to +157
' • all cards in the realm: omit --query (or pass {})',
' • by type: {"filter":{"type":{"module":"<https card module url>","name":"<CardName>"}}}',
' • by field: {"filter":{"on":{"module":"<url>","name":"<CardName>"},"eq":{"<field>":"<value>"}}}',
' • combine: "any" (OR) / "every" (AND); also "contains", "range", "not"',
'Field filters (eq/contains/range) require an "on" type scope, and "module" must be the full HTTPS URL of the card definition (no relative paths).',

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

(Written by Claude on Matic's behalf.)

Fixed in aedbe7f. The hint now uses a single consistent placeholder <https-module-url> in both the type and field examples, and the trailing line spells out that it's the full HTTPS URL of the card definition (no relative paths).

Comment on lines +21 to 22
Queries are JSON, passed via `--query`. **Omit `--query` to list every card in the realm(s)** — the fastest way to discover what's there (and to find a card's module URL from its `meta.adoptsFrom`) before writing a typed filter. The shape mirrors the `_search` API:

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

(Written by Claude on Matic's behalf.)

Fixed in aedbe7f. Regenerated the synopsis with build-plugin — the generated --query line now reads "JSON query object (as a string). Omit to list every card in the realm(s).", matching the CLI. (Only the search skill changed.)

- Use a single consistent placeholder (<https-module-url>) in the
  cannot-classify-filter hint instead of mixing "<https card module url>"
  and "<url>".
- Regenerate the search skill's autogenerated command block so the --query
  option text reflects it's now optional (omit to list all).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jurgenwerk jurgenwerk changed the title feat: boxel-cli search supports discovery (optional --query) + actionable filter errors feat: boxel search can list a realm's cards without a query, and explains rejected filters Jun 19, 2026
@jurgenwerk jurgenwerk requested a review from a team June 19, 2026 11:52
@jurgenwerk jurgenwerk marked this pull request as ready for review June 19, 2026 12:08
| "give me JSON I can pipe" | add `--json` |
| Ask | Run |
| ------------------------------- | -------------------------------------------------------------------- |
| "what cards are in this realm?" | `boxel search --realm <url>` — **omit `--query`** to list everything |

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.

what about the /_mtimes API? this list everything in a realm and is much cheaper

@habdelra

Copy link
Copy Markdown
Contributor

Also this might collide with the work to refactor boxel-cli to use the new unified search endpoint #5291

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.

4 participants