Skip to content

[Obsidian] Add Exact Content Match Navigation - #30150

Open
SWHL wants to merge 4 commits into
raycast:mainfrom
SWHL:main
Open

[Obsidian] Add Exact Content Match Navigation#30150
SWHL wants to merge 4 commits into
raycast:mainfrom
SWHL:main

Conversation

@SWHL

@SWHL SWHL commented Aug 12, 2026

Copy link
Copy Markdown

Description

Enhances the existing Obsidian Search Note command with exact content-match results and navigation.

  • Show each exact content occurrence as a separate search result
  • Display highlighted context with line and column information
  • Open and select matches through the official Obsidian CLI
  • Filter out fuzzy-only candidates without literal matches
  • Preserve existing primary-action preferences and action ordering
  • Automatically launch Obsidian when it is not already running
  • Reliably position matches after a cold start
  • Close the Raycast window immediately while navigation completes
  • Avoid unnecessary selection updates that could cause cursor jumping

Navigation mechanism

When opening a content match, the extension:

  1. Opens the target note through the existing obsidian:// URI mechanism. This launches Obsidian when it is not already running.
  2. Uses the official Obsidian CLI to wait until workspace.layoutReady confirms that workspace initialization has completed.
  3. Opens the target note again through the CLI because Obsidian's cold-start workspace restoration may supersede the initial URI request.
  4. Waits until the target note is active and its editor is available.
  5. Selects and scrolls to the exact line and column through an Obsidian CLI eval command.
  6. Verifies the resulting editor selection once. If the selection is already correct, the verification is read-only and does not focus, scroll, or modify the editor.

Readiness and activation checks use bounded exponential backoff, and the entire navigation operation is limited to 15 seconds. Permanent CLI errors fail immediately. The extension does not create a persistent process, listener, or background service; all activity stops after successful positioning, an unrecoverable error, or timeout.

The Raycast window closes concurrently with navigation, so the user is taken to Obsidian immediately instead of waiting for workspace initialization and positioning to finish.

Title-only search and regular note results remain unchanged. Search results and match previews work without the Obsidian CLI. Exact navigation requires Obsidian 1.12.7 or later with Settings > General > Advanced > Command line interface enabled.

This implementation was developed with coding assistance from GPT-5.6. The generated changes were manually reviewed, refined, tested, and verified before submission.

Screencast

Aug-12-2026 11-32-36

Verification

  • 326 tests passed
  • Raycast lint passed
  • TypeScript check passed
  • Distribution build passed
  • Manually verified exact navigation on macOS
  • Manually verified navigation while Obsidian is running
  • Manually verified automatic launch and exact navigation after fully quitting Obsidian
  • Manually verified that Raycast closes immediately after opening a match
  • Manually verified that selection verification does not cause repeated cursor movement

Checklist

SWHL added 3 commits August 12, 2026 10:01
- show each exact content occurrence as a separate search result
- display highlighted context with line and column information
- open and select matches through the Obsidian CLI
- filter out fuzzy-only candidates without literal matches
- preserve existing primary-action preferences
@SWHL
SWHL requested a review from pernielsentikaer as a code owner August 12, 2026 03:34
@raycastbot raycastbot added extension fix / improvement Label for PRs with extension's fix improvements extension: obsidian Issues related to the obsidian extension AI Extension platform: macOS platform: Windows labels Aug 12, 2026
@raycastbot

Copy link
Copy Markdown
Collaborator

Thank you for your first contribution! 🎉

🔔 @marcjulianschwarz @KevinBatdorf @iancanderson @pernielsentikaer @ofalvai @AdamAdamsMusic @FServais @rakoort @MuuNU @theherk @vicampuzano @ErBlack @byheaven @tofrankie @alexibuild you might want to have a look.

You can use this guide to learn how to check out the Pull Request locally in order to test it.

📋 Quick checkout commands
BRANCH="main"
FORK_URL="https://github.com/SWHL/extensions.git"
EXTENSION_NAME="obsidian"
REPO_NAME="extensions"

git clone -n --depth=1 --filter=tree:0 -b $BRANCH $FORK_URL
cd $REPO_NAME
git sparse-checkout set --no-cone "extensions/$EXTENSION_NAME"
git checkout
cd "extensions/$EXTENSION_NAME"
npm install && npm run dev

We're currently experiencing a high volume of incoming requests. As a result, the initial review may take up to 15 business days.

@greptile-apps

greptile-apps Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR adds per-occurrence exact-content search results and Obsidian CLI navigation while retaining regular note-result behavior.

  • Adds literal content-match extraction with context and coordinates.
  • Adds CLI-based note activation, selection, verification, retry, and timeout handling.
  • Updates result rendering, actions, documentation, changelog, and tests.

Confidence Score: 3/5

The PR does not yet appear safe to merge because exact-match coordinates can be wrong for length-changing Unicode case mappings and stale asynchronous searches can replace current results.

Exact matching still applies offsets from locale-lowercased strings to original note content, while the list search still lacks request ownership or cancellation after asynchronous work starts; these leave both previously reported user-visible failures reachable.

Files Needing Attention: extensions/obsidian/src/api/search/content-match.service.ts; extensions/obsidian/src/components/NoteList/NoteList.tsx

Important Files Changed

Filename Overview
extensions/obsidian/src/api/search/content-match.service.ts Adds exact occurrence extraction and result expansion, but transformed Unicode offsets can still produce incorrect match coordinates.
extensions/obsidian/src/components/NoteList/NoteList.tsx Integrates occurrence-level asynchronous search results, but older in-flight requests can still replace the latest result state.
extensions/obsidian/src/api/open-match/open-match.service.ts Adds bounded CLI readiness, note activation, selection, and verification logic.
extensions/obsidian/src/components/NoteList/NoteListItem/NoteListItem.tsx Renders occurrence previews, highlighting, coordinates, and match-aware actions.
extensions/obsidian/src/utils/actions.tsx Adds match-specific Obsidian opening while preserving the existing primary-action composition.

Reviews (2): Last reviewed commit: "fix(obsidian): preserve search coordinat..." | Re-trigger Greptile

Comment on lines +57 to +60
if (offset === -1) break;

const start = positionAt(content, offset);
const end = positionAt(content, offset + trimmedQuery.length);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Transformed offsets select wrong text

When locale-sensitive lowercasing changes a Unicode string's UTF-16 length, indexOf returns an offset into the transformed content that is then applied to the original note. This produces incorrect preview highlighting and selects the wrong range in Obsidian; advancing by the original query length also omits or duplicates subsequent occurrences.

Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/obsidian/src/api/search/content-match.service.ts
Line: 57-60

Comment:
**Transformed offsets select wrong text**

When locale-sensitive lowercasing changes a Unicode string's UTF-16 length, `indexOf` returns an offset into the transformed content that is then applied to the original note. This produces incorrect preview highlighting and selects the wrong range in Obsidian; advancing by the original query length also omits or duplicates subsequent occurrences.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Comment on lines +89 to 91
setFilteredResults(sorted.slice(0, MAX_RENDERED_NOTES));
} finally {
setIsSearching(false);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Superseded searches overwrite current results

If the user changes the query or sort order while a content search is reading notes, an older request can finish later and unconditionally replace the current results and clear the shared loading state. The list then exposes stale notes for opening or deletion while the latest search is still running.

Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/obsidian/src/components/NoteList/NoteList.tsx
Line: 89-91

Comment:
**Superseded searches overwrite current results**

If the user changes the query or sort order while a content search is reading notes, an older request can finish later and unconditionally replace the current results and clear the shared loading state. The list then exposes stale notes for opening or deletion while the latest search is still running.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

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

Labels

AI Extension extension fix / improvement Label for PRs with extension's fix improvements extension: obsidian Issues related to the obsidian extension platform: macOS platform: Windows

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants