Search that cannot tell you what you may not read

One search across every record type, filtered by the same read rules as everything else, with totals that do not change when hidden records match.

Until now you found a record by knowing its type and listing it. Core v1.167.0 adds one search across every record type you may read.

It matches plain text, ignoring case, in the fields each type marks as searchable: a Decision's title and body, a Task's description, a Signal's message, a plan's body. Records without a title are found too. It works from code, over MCP and from the command line.

The read rules come first. Every hit goes through the same check as listing and fetching. A record you may not read is not a hit, and it does not change the total either. A count that moved when hidden records matched would tell you they exist, so the count is taken only over what you can see.

You can filter by type and state. One filter is useful on its own: records that have no place. A Decision imported from an old ADR file that nobody has put in a Domain or Area shows up there, so the unplaced ones are easy to find and sort. For example:

smeldr-cli search --type Decision --state proposed --place none

The answer is the same on SQLite and Postgres. SQLite lowercases only plain ASCII letters, so the database does a cheap first filter on those and the real match runs in Go. "Æble" finds "æble" on both.

A search is a read surface like any other. If it counts before it filters, the total leaks what the hits hide.

Released in core v1.167.0, mcp v1.65.0 and cli v0.28.0.