Search
One field over every message you have ever sent or received, every memory a project keeps, and the name of every file a session left on disk.
The screen
/ opens it from any screen. Results come back as you type, in a millisecond or two. The TYPE column says what each hit is, because the three kinds want different things done to them, and ↵ opens the screen that can do it: a conversation opens its spine at that turn, a memory opens the reader, a work product opens the browser at that directory.
| Key | What it does |
|---|---|
| type | the query, live |
| tab | narrow to this conversation, or widen back to everything |
| ↑ / ↓ | move through the hits |
| ↵ | open the hit |
| esc | back where you came from |
From the command line
braids search "lock across a network call" braids search worktree --limit 5 braids search "index" --type memory,artifact braids search deploy --project braids --since 30d braids search "rate limit" --since 2026-08-01 --until 2026-08-31 braids search "timed out" --kind tool_result --lane 46360382 braids search "fork" --json
| Flag | What it does |
|---|---|
| --lane ID | only this conversation, by ID prefix |
| --project NAME | only this project, matched without regard to case |
| --since WHEN | a date or an age: 2026-08-01, 30d, 6w, 12h |
| --until WHEN | the same, as an upper bound. A bare date means all of that day |
| --type LIST | conversation, memory, artifact. All three unless you narrow it |
| --kind LIST | text, thinking, tool_use, tool_result |
| --limit N | how many hits, default 20 |
| --json | machine readable, with whole IDs |
The query syntax
Search is SQLite's FTS5 over what was written, and its whole query syntax
works. The one worth knowing first is that bare words are and:
payment retry asks for both, which is narrower than either word
alone and is the usual reason a search comes back empty about a conversation
that is really there.
| Query | Matches |
|---|---|
| a b | both, in any order |
| a OR b | either. This is how you cover a synonym |
| a NOT b | a, excluding anything that also has b |
| "a b" | that phrase, in that order |
| a* | prefix: deploy* matches deployed and deployment |
| NEAR(a b, 10) | both, within ten words of each other |
Anything with an operator, a quote, a bracket or a star is handed to FTS5 as written. Everything else is treated as words to find, so a plain question needs no escaping.
Raise --limit when you use OR. The limit is shared across the whole query, so a rare word gets crowded out by a common one: on a real history of 28 conversations, five alternatives found fifteen of them at --limit 500 and seven at the default of twenty.
Reading what a hit points at
A hit is a pointer, not an answer. It names a conversation, the turn the match was on, and about twelve words either side of it, which is enough to recognise the right thread and far too little to tell a proposal from a conclusion. The sentence that settles it is usually the one after the one that matched.
braids show --lane 9419fd9c --at 22403 # six turns either side braids show --lane 9419fd9c --at 22403 --kind text # only what was said braids show --lane 9419fd9c --from 100 --to 140 # a range braids show --lane 9419fd9c --plain # without terminal colour braids show --lane 9419fd9c # how it ended
Two thirds of a real conversation is tool calls and their results, so
--kind text is usually what you want; leave it off when the
thing you are after is what a command returned. Each block is cut at
--chars characters and says how many it dropped, because a
single tool result can be a whole file and arriving whole is rarely a
kindness.
A tool that found a terminal on the other end wrote colour codes, and braids
stores what was written, so they come back with it. --plain
takes them out. It is off by default because editing a transcript to make it
read better is the one thing braids does not do, and on request because those
bytes sit inside the words: a test run that printed
1 failed in red holds eleven escape bytes in the middle of that
phrase, so searching the output for it finds nothing. Stripping happens
before --chars, so asking for it also buys more of the words.
This is the command the map has always had as a screen and the command line did not. A search could tell an agent where an answer was and give it no way to read the answer, which made the honest advice "quote the evidence" impossible to follow.
The same filters, typed
Flags are right for a script and wrong for a person mid-sentence, so the filters can also be typed into the query itself, which is what the search screen takes:
braids search "project:braids since:30d lock"
project:, lane:, since: (or
after:), until: (or before:),
kind: and type:. Press / in braids and
the same words work there, with the header saying what it narrowed to. A flag
wins where both are given.
Pressing / with nothing typed lists them, which is where anyone actually finds out they exist, and the results carry the date each thing happened so a bound by date can be checked rather than taken on trust. On a narrow terminal the date is the first column to go, because a result whose text you cannot read is no result at all.
A word that looks like a filter but cannot be read as one stays part of the query. That matters because the field searches on every keystroke: halfway through typing since:30d you have since:3, and a parser that failed there would blank the screen while you type.
How it ranks, and why that took two goes
The index is SQLite FTS5 and the ranking is bm25, which prefers short documents. A filename is three words and a turn is several hundred, so ranked in one pool the filenames won everything and buried the conversations. Each kind is now queried and ranked separately, then merged by interleaving.
The first attempt at that shared one query across memories and work-product names, which starved the memories: a search for a word appearing in four memories returned none of them. Each kind gets its own query now.
Work products are matched by name, not by contents. Indexing the contents of 3.3 GB of scratch files would cost more than it is worth, and the name is what you remember.
