feat(search): menubar global cross-window FTS5 search (scaffold, P1) - #3868
Supersynergy wants to merge 5 commits into
Conversation
P1 scaffold for manaflow-ai#3865. Adds: - SearchIndex: actor wrapping SQLite FTS5 store at ~/Library/Application Support/cmux/search.db, upsert/search/purge. - MenubarSearchPopover: NSPopover + SwiftUI palette, anchored to the existing NSStatusItem. Emits .cmuxJumpToSearchHit on pick. - GlobalSearchHotkey: Carbon-registered ⌥⌘F toggle. - docs/menubar-global-search.md: phase plan (wire-up, capture sources, ranking polish). No behavior change yet — files are not in GhosttyTabs.xcodeproj; P2 adds them and wires AppDelegate.
|
@Supersynergy is attempting to deploy a commit to the Manaflow Team on Vercel. A member of the Team first needs to authorize it. |
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Revised placement: inline search field in the titlebar accessory,
directly left of the + new-workspace button (the same TitlebarControls
host attached at .layoutAttribute = .left). System-menubar popover is
kept as an opt-in fallback.
Smart stack (parallel per keystroke, ~10-20 ms warm):
Synapse hybrid (/tmp/synapse.sock, SimSIMD, MRL-128, 8 ms)
+ SQLite FTS5 (lex)
+ SmartRanker (BM25-inv + recency + Thompson click-history prior)
Synapse is optional — bridge is a graceful no-op with 60 s back-off
when the daemon is unreachable, so the field still works on plain
FTS5.
Adds:
- Sources/Search/SynapseBridge.swift — line-delimited JSON over Unix
socket; off-main I/O; parses hits or returns [].
- Sources/Search/SmartRanker.swift — Beta(picks, hits) prior per
(kind, panel), persisted to
~/Library/Application Support/cmux/search-clicks.json. Records
impressions + rewards, hook for recency boost (P4 when SearchIndex
threads ts into Hit).
- Sources/Search/TitlebarSearchField.swift — SwiftUI inline field with
magnifier glyph, clear button, results popover (⌘1..9 hotkey hints),
warmup on appear, Esc to dismiss.
- Hotkey ⌥⌘F now focuses the inline field (key-window) and only opens
the menubar popover when no window is key.
- Notification .cmuxFocusTitlebarSearch glues hotkey -> field.
Placeholder string uses String(localized:) per project policy.
docs/menubar-global-search.md rewritten with new placement, P2 wire-up
snippet (one TitlebarSearchField line inserted before the plus button
in UpdateTitlebarAccessory.swift), capture-source plan, and locale
note.
|
Update: revised placement per user feedback — moved from system menubar (NSStatusItem) to an inline search field in the titlebar accessory, directly left of the New smart stack (parallel fan-out, ~10-20 ms warm):
Wire-up reduces to one line in Files added this revision: |
Adds the 6 Search/* files to the GhosttyTabs target via xcodeproj-rb; inserts the inline TitlebarSearchField in TitlebarControls just before the + new-workspace button (Sources/Update/UpdateTitlebarAccessory.swift around the SF-symbol "plus" site); adds a lazy AppDelegate.searchIndex backed by SearchIndex against ~/Library/Application Support/cmux/search.db; installs GlobalSearchHotkey (⌥⌘F → focus inline field) in applicationDidFinishLaunching. Build state: swiftc -parse clean on all six files; full xcodebuild gated by Xcode.app (CLT only here). CI will exercise. After this commit the inline field is visible and types into FTS5 + Synapse. Capture sources (P3: browser innerText, markdown save hook, ghostty C shim for terminal scrollback) wire next and start populating the index.
- Drop SynapseBridge (file + xcodeproj ref). Local-only by default;
semantic backend is a P-later opt-in plug behind SearchIndex.
- TitlebarSearchField now:
* Scope prefixes: t: (terminal) b: (browser) m: (markdown)
w: (window/title). Parsed pre-recall, narrows results without
leaving the keyboard.
* Up/Down arrows step through hits; Enter accepts.
* Cmd+1..9 direct-jump to N-th hit.
* Esc dismisses.
- Focus bridge: AppDelegate observes .cmuxJumpToSearchHit and forwards
to the existing FeedCoordinator.focus(workspaceId:surfaceId:)
pathway — so accepting a hit drops the user directly into the
matching window/workspace/panel (no new routing invented; reuses
the same notification the Feed already uses).
- docs/menubar-global-search.md rewritten to reflect local-only stack
and the keyboard contract.
|
Update: dropped Synapse — local-only by default (zero external deps). Semantic backend stays a future opt-in behind Smart nav added:
Direct focus on accept: |
P3 capture stubs (one-line call-sites; no edits to the giant BrowserPanel/CmuxWebView/MarkdownPanel files yet): - BrowserCaptureHook: WKWebView extension that chains the existing navigationDelegate, debounces 600 ms on didFinish, extracts document.body.innerText via JS, then upserts (title + URL + body) into SearchIndex under .browser. Self-retains via objc associated object; releases when the webview does. - MarkdownCaptureHook: tiny static helper; off-main upsert into SearchIndex under .markdown. Cheap enough to call inline on save. Preview-on-arrow: - TitlebarSearchField fires .cmuxPreviewSearchHit on ↑/↓ with a 120 ms debounce so holding arrow keys doesn't thrash the focus path. - AppDelegate observes both .cmuxJumpToSearchHit (Enter — focus + reward) and .cmuxPreviewSearchHit (arrow — focus only) and routes both through the existing FeedCoordinator.focus(workspaceId:surfaceId:) pathway. Net effect: the user types, arrows to a hit, sees the matching panel/workspace come into focus instantly; Enter locks it in and records a SmartRanker reward for next time. Terminal capture (P3 last leg) still requires a ghostty-side text subscription or a PTY-tap; deferred as documented in docs/menubar-global-search.md.
Scaffold for #3865. Adds SearchIndex (SQLite FTS5 actor), MenubarSearchPopover (NSPopover + SwiftUI palette anchored to existing NSStatusItem), GlobalSearchHotkey (Carbon ⌥⌘F), and a phase plan in docs/. No behavior change yet — three new files under Sources/Search/ are not in GhosttyTabs.xcodeproj; P2 wires them into AppDelegate. See docs/menubar-global-search.md for the wire-up snippet and capture-source plan (browser→innerText, markdown→save hook, terminal→ghostty C shim).
Draft for review of approach before P2 wiring + Xcode project edits.
Summary by cubic
Implements global cross‑window search for #3865 with an inline titlebar field, local FTS5 indexing, and a ⌥⌘F hotkey; adds browser/markdown capture hooks and preview‑on‑arrow focus. P2 is wired and P3 stubs are in: the field is visible, results rank smartly, arrowing previews the right panel, and Enter jumps to it.
SearchIndex(SQLite FTS5 withbm25/snippet()) +SmartRanker(BM25‑inv + Thompson click‑history prior, persisted). Local‑only; semantic backend deferred.TitlebarSearchField(inline field with results popover; scope prefixest:,b:,m:,w:; ↑/↓ nav with.cmuxPreviewSearchHit, Enter accept,⌘1..9, Esc; emits.cmuxJumpToSearchHit) withMenubarSearchPopoveras fallback.BrowserCaptureHook(debounceddocument.body.innerTextonWKWebView.didFinish) andMarkdownCaptureHook(save‑time feed) upsert into the index; terminal capture deferred.TitlebarSearchFieldbefore the “+” button, createdAppDelegate.searchIndexat~/Library/Application Support/cmux/search.db, installed the ⌥⌘F hotkey, and bridged.cmuxJumpToSearchHitand.cmuxPreviewSearchHittoFeedCoordinator.focus(workspaceId:surfaceId:).Written for commit a678c40. Summary will update on new commits.