Skip to content

feat(search): menubar global cross-window FTS5 search (scaffold, P1) - #3868

Draft
Supersynergy wants to merge 5 commits into
manaflow-ai:mainfrom
Supersynergy:feat/menubar-global-search
Draft

Supersynergy wants to merge 5 commits into
manaflow-ai:mainfrom
Supersynergy:feat/menubar-global-search

Conversation

@Supersynergy

@Supersynergy Supersynergy commented May 11, 2026 •

Copy link
Copy Markdown

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.

  • New Features
    • Index and ranking: SearchIndex (SQLite FTS5 with bm25/snippet()) + SmartRanker (BM25‑inv + Thompson click‑history prior, persisted). Local‑only; semantic backend deferred.
    • UI: TitlebarSearchField (inline field with results popover; scope prefixes t:, b:, m:, w:; ↑/↓ nav with .cmuxPreviewSearchHit, Enter accept, ⌘1..9, Esc; emits .cmuxJumpToSearchHit) with MenubarSearchPopover as fallback.
    • Capture hooks: BrowserCaptureHook (debounced document.body.innerText on WKWebView.didFinish) and MarkdownCaptureHook (save‑time feed) upsert into the index; terminal capture deferred.
    • App wiring: Added Search files to target, inserted TitlebarSearchField before the “+” button, created AppDelegate.searchIndex at ~/Library/Application Support/cmux/search.db, installed the ⌥⌘F hotkey, and bridged .cmuxJumpToSearchHit and .cmuxPreviewSearchHit to FeedCoordinator.focus(workspaceId:surfaceId:).

Written for commit a678c40. Summary will update on new commits.

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.
@vercel

vercel Bot commented May 11, 2026

Copy link
Copy Markdown

@Supersynergy is attempting to deploy a commit to the Manaflow Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented May 11, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: c12b0bc9-4624-4794-96b8-35bf87adacfe

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

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.
@Supersynergy

Copy link
Copy Markdown
Author

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-workspace button (same TitlebarControls host at .layoutAttribute = .left).

New smart stack (parallel fan-out, ~10-20 ms warm):

  • Synapse hybrid via local Unix socket (/tmp/synapse.sock, SimSIMD MRL-128, 8 ms) — semantic recall, optional dep with 60 s back-off on miss.
  • SQLite FTS5 lex recall (SearchIndex).
  • SmartRanker — BM25-inverted + recency boost hook + Thompson click-history prior per (kind, panel), persisted to app-support.

Wire-up reduces to one line in TitlebarControls before the + button (snippet in docs/menubar-global-search.md). Hotkey ⌥⌘F focuses the inline field; menubar popover kept as fallback only.

Files added this revision: SynapseBridge.swift, SmartRanker.swift, TitlebarSearchField.swift. Strings via String(localized:).

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.
@Supersynergy

Copy link
Copy Markdown
Author

Update: dropped Synapse — local-only by default (zero external deps). Semantic backend stays a future opt-in behind SearchIndex.

Smart nav added:

  • Scope prefixes t: b: m: w: parsed pre-recall.
  • ↑ / ↓ step, ↵ accept, ⌘1..9 direct-jump, Esc dismiss.

Direct focus on accept: AppDelegate observes .cmuxJumpToSearchHit and forwards to the existing FeedCoordinator.focus(workspaceId:surfaceId:) pathway. No new routing — reuses the notification the Feed layer already uses. User lands in the matching window/workspace/panel on ↵.

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.
@teamleaderleo teamleaderleo added area: command-palette Command palette, quick open, find needs a call Finished and held for a team design or product decision (see #13742 and the gallery in #15427) labels Sep 30, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: command-palette Command palette, quick open, find needs a call Finished and held for a team design or product decision (see #13742 and the gallery in #15427)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants