cmux NEXT Home: search finds message text and lists matching messages, as in Messages
Fixes https://github.com/manaflow-ai/cmux/issues/27950
Changelog
Changed: searching the Home (Chief) list now also finds messages whose text matches, under a Messages section with the conversation, the matching text and its time, as in Messages. Choosing one opens the conversation at that message.
What was wrong
- Content: the list's search matched only conversation names, participants and each one's newest preview. The conversation owner already answers a full-text message search (
conversation-search,HomeStore.search), but the list never asked it. - Icon layout: the magnifier, the "Search" text and the filter circle drew off-centre, and the typed text slid over the magnifier. https://github.com/manaflow-ai/cmux/pull/28021 fixed that today for https://github.com/manaflow-ai/cmux/issues/27967, and this PR does not change the field or the header. The captures below re-check it at this head: the magnifier, the text and the filter share one centre line at rest and while typing.
Change
- Vendored list (
MessagesLabSidebar): takes any number of host search sections, each under its own title. The singleextraStart/extraTitlebecameSidebarSectionMarks, which owns the row geometry: row top and its inverse, title rects, hit testing, separators, and the search queue's prerender. A request can answer twice: the quick sections first, then the slow ones replace that answer. Cancelling the request (the next keystroke, or an emptied field) cancels the slow task, and an older query's answer is dropped. CmuxSidebarView:searchSections(sync, shown at once) pluslaterSearchSections(async). A result can carry an avatar and a date. VoiceOver reads that date.HomeSidebarView: Teammates show at once. Messages arrive fromsearchMessages; a hit is shown only for a conversation the list shows, and gets that conversation's name and avatar. Choosing one callsonOpenMessage.TopHomePageView:searchMessagesishomeStore.search(query, limit: 20), local owner only (the router's cloud has nohome.searchyet, so Cloud conversations get no message hits).onOpenMessageuses the permalink pathshow(HomeDockSelection(conversation:message:)), which reveals the message.- DEBUG only:
debug.home.sidebar_fixturetakesmessages[{row, text}] andqueryfor screenshots. There's a new tour,home-search. One new string,home.list.searchMessages("Messages"), translated in all 21 catalog locales.
Tests
SearchSectionsTests (MessagesLabSidebar) drives a real CmuxSidebarView in a window:
everySectionShowsUnderItsOwnTitleAfterTheConversations: Teammates shows before the held message search answers. Then the Messages section joins: each title sits on its first row, no row overlaps a title, every row's middle hits that row, a title hits nothing, and a message row carries its text and time and reports its host id when chosen.anOlderQuerysLateAnswerIsNeverShown: holds the "lun" answer past its cancellation and releases it after "lunch" has shown. The list keeps "lunch"'s sections only.
Fleet runs:
- Step
8c084307974df7d15d2508e3at be6ae7cedf68 (package-test-lane.sh suite Packages/Shared/CmuxMessagesLab SearchSectionsTests,PinnedUnreadDotLayoutTests,PinDragMotionTests): all 3 suites pass. - Step
d4e7a686571b10f06004be3fat b71cb3627513, the first version: all 3 pass. - Commits after be6ae7cedf68 change only the tour JSON.
These tests are new, so there is no red run on the base: the multi-section API they call does not exist there.
Dev build and captures
Tag 27950-chief-search-messages: fleet build 6e44e1550aa9a465b9d298c1 at a693f53402a5 (this head). The captures below come from build 30dcd0c39f9875137d3069b6 at 2781def26c96; the only later commit is the French heading text, which no capture shows.
Viewed after image: yes
Visual verdict: Yes: the Messages section reads like iMessage's search results, in the list's own row style, and the header stays on one centre line.
"lunch" (three messages, no name match), "Aziz" (the name match, then a message mentioning him), and Home at rest:
Capture steps-38032e9241 at 2781def26c96 (fleet build, capture mini, text checked for private data)
| Light | Dark |
|---|---|
![]() | ![]() |
Capture steps-e95fe29296 at 2781def26c96 (fleet build, capture mini, text checked for private data)
| Light | Dark |
|---|---|
![]() | ![]() |
Capture tour-home at 2781def26c96 (fleet build, capture mini, text checked for private data)
| Light | Dark |
|---|---|
![]() | ![]() |
Review
A correctness review subagent at edc61729e503 found nothing blocking. Its should-fix items are fixed in be6ae7cedf68:
- Teammates waited on the message search.
- An emptied field didn't cancel the slow task.
- The late-answer test didn't really hold the answer.
- VoiceOver skipped the result's time.
- The fixture copied the production wiring.
Not changed: one owner search per keystroke. Each search is local and cancelled by the next keystroke, and the repo rules say not to debounce visible work.
Observed / Not run
- Observed:
- Fleet suites above.
- Real-app captures on the tagged build at this head: the "lunch" and "Aziz" searches, and
tour:homefor the header at rest. - The base
tour:homeat 3e65269f80c9, the header before.
- Not run:
- A real daemon
conversation-searchround trip in the app. The captures use the DEBUG fixture's hits; the daemon command has its own Rust tests (conversation_tests.rs), unchanged here. - Clicking a message result in the app (the test selects the row under the point).
- Real keyboard typing (no focus-free route).
- The full CmuxNext suite.
- A real daemon
š¤ Generated with Claude Code
![View with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v3-3x.png)
![Autofix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark-3x.png)
Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
Home list search now matches message text, not just conversation names and latest previews. Matching messages appear in a new Messages section under Teammates ā each row shows the conversation's name, the matched text, and the message's time ā and choosing one opens the conversation at that message, as in Messages.
- Teammates show immediately; message results arrive asynchronously from the conversation owner's search.
- The vendored list now supports multiple search sections, each with its own title; a newer keystroke or an emptied field cancels an older query's answer.
- Message hits appear only for conversations the list already shows; Cloud conversations get none because the cloud router lacks
home.searchyet.
Tests
SearchSectionsTestsdrives a realCmuxSidebarView: every section shows under its own title after the conversations, no row overlaps a title, and choosing a message row reports its host id.- A late answer for an older query is never shown once a newer query has run.





