Jotura

Docs / Using the app / Search

Search

Quick open, the sidebar keyword pane, the three-mode search page, semantic search setup, and finding text inside imported PDFs and Word files.

Jotura has four ways to find something, and each one matches a different thing. Quick open matches file names. The sidebar search pane matches note titles and note bodies with keyword search. The search page matches the same titles and bodies but adds semantic and smart modes. The command palette matches command names rather than your notes.

Your queries and your indexes stay on your machine. The keyword index lives in your vault at .jotura/index/, and the semantic vector index lives in the same folder at .jotura/vectors.db. The only network request search ever makes is the one-time download of the embedding model, described below. Search also never waits on cloud sync: a vault whose sync key is not cached still reads, writes, and searches normally. See Sync and sharing for what pausing sync does and does not affect.

The four surfaces at a glance

SurfaceHow to openWhat it matchesNotes
Quick openCmd/Ctrl+PFile names onlyFastest way to jump to a file you can name
Sidebar search paneThe Search icon in the sidebar, or the Open Search Panel commandNote titles and note bodies, keyword onlyHas the case, whole-word, and phrase toggles
Search pageCmd/Ctrl+Shift+F, or the Search Vault commandNote titles and note bodies, in keyword, semantic, or smart modeOpens as a pinned tab
Command paletteCmd/Ctrl+Shift+PCommand names, not your notesFuzzy match over the 18 built-in commands

All four search the vault. There is no find inside the note you are currently editing. Cmd/Ctrl+F is not bound to anything, and source mode installs no CodeMirror search keymap, so neither the WYSIWYG editor nor source mode has an in-pane find or a find-and-replace. If you need to locate a phrase within one long note, search the vault for it and open the result, or edit the file with another tool. See The editor for what the editing surface does provide.

Two quirks on the Dashboard, the screen shown when no tab is active, are worth knowing before you go further. Its four quick actions are New note, Quick open, Search vault, and Command palette, and the Search vault action opens the sidebar pane, while the command palette entry named Search Vault opens the search page. The Dashboard also prints macOS glyphs (⌘P, ⌘⇧F, ⌘⇧P) on every platform, so on Windows and Linux the chord shown there is not the chord you press. The real chords are in the shortcuts table at the end of this page.

Quick open

Cmd/Ctrl+P toggles quick open. It matches the file name only, not the folder path and not the content, using a fuzzy matcher that is always case-insensitive.

BehaviorDetail
What is searchedThe file name including its extension
What is listedFiles whose extension Jotura recognizes: the text extensions listed further down, plus documents (pdf, docx and the other office formats, epub, rtf) and images. A file with no extension, or with an unrecognized one such as mp4, mp3, or zip, is never offered
Result limit20
Debounce80 ms
Empty queryEvery listed file scores zero and the list is truncated to 20, so opening quick open shows files straight away
NavigationArrowUp and ArrowDown move, Enter opens, and the list clamps at both ends rather than wrapping
MouseHovering a row makes it the active row
PlaceholderSearch files by name…
Empty stateNo files match., shown only once the query is non-empty
ClosingEscape, clicking outside the dialog, or Cmd/Ctrl+P again

The query is deliberately not cleared when you close quick open, so reopening restores what you last typed. The input is selected on open, so typing immediately replaces it.

Quick open has no > command prefix and no #tag filter. Commands live in the command palette, and tags have their own sidebar pane.

One consequence of listing documents as well as notes: an imported document and its converted text note both appear. Searching for report can show both report.pdf and report.pdf.md. Opening either one lands you in the same converted text.

The sidebar search pane

Open the pane from the sidebar’s Search icon, or run Open Search Panel from the command palette. This command has no keyboard shortcut of its own.

The pane is keyword only. It runs against the same index as the search page’s Keyword mode, but it exposes three query controls that the search page does not.

ToggleLabel in the UIEffect
Case sensitiveAaMatches against a case-preserving copy of the body text instead of the lowercased one
Whole wordWEach term must match a whole token. With it off, each term is matched as a substring
Phrase""Rewrites the query: existing double quotes are stripped and the whole query is wrapped in quotes

The phrase toggle is a convenience, not a separate backend mode. Typing "quarterly review" with the quotes yourself has the same effect, and it works in the search page too.

BehaviorDetail
PlaceholderSearch vault…, one word shorter than the search page’s placeholder
Debounce150 ms
Result limit50
Empty statesType to search. while the query is empty, No results. when a query found nothing
GroupingResults are split into two labeled groups, Titles (N) and Content (N)
NavigationArrowUp and ArrowDown move through the combined list, Enter opens the active result, and Escape blurs the input and returns you to the Files pane

Two separate indexing messages can appear here. A live counter reading indexing… {done}/{total} sits in the toggles row whenever an index build is running. Separately, when your last search ran against an incomplete index, a notice reads Still indexing… results may be incomplete (N%).

Clicking a hashtag inside the editor switches the sidebar to this pane, fills in the tag as the query, and focuses the input.

The search page

Cmd/Ctrl+Shift+F opens the search page. It opens rather than toggles: pressing it again while the page is open just refocuses the input. The same thing happens from the palette command Search Vault.

The page is a tab. It is pinned to the first position, it cannot be dragged or used as a drop target, and you close it with Escape while it is the active tab or with Cmd/Ctrl+W.

BehaviorDetail
PlaceholderSearch your vault…
Debounce250 ms
Keyword result limit50
Semantic and smart result limit30
Empty statesType to search. before the first search and again every time you clear the input, No results. after a search that found nothing
NavigationResults are plain buttons reached with Tab. There is no arrow-key navigation on this page
Result rowTitle, score to two decimal places, folder breadcrumb, a heading path when the row has one, and a snippet

The mode buttons sit under the input, with an info button labeled About search modes that opens a short explainer. Clicking outside the explainer closes it. Escape does more than that: the global handler sees Escape first and closes the whole search tab, because the active tab is the search tab.

The selected mode and the query live in memory only. Closing and reopening the tab keeps both, and both reset when you restart the app.

Keyword mode

Keyword search runs in two passes and merges them.

  1. A fuzzy pass over file names, matching against the name with the extension stripped. This pass contributes at most 20 results, and it is always case-insensitive, so the case and whole-word options do not apply to it.
  2. A body pass over the full-text index. Terms are combined with AND, so every term must appear.

Results from the body pass are deduplicated against the title pass, and the merged list is truncated to the limit.

How the body pass ranks depends on the whole-word setting. With whole word on, or for a phrase query, each term becomes a term query and tantivy ranks the matches with BM25, so a word that is frequent in a note and rare across the vault pushes that note up. With whole word off, each term becomes a substring pattern instead, which decides whether a note matches but does not rank by term frequency, so those scores carry much less information. The in-app explainer describes the BM25 behavior without drawing this distinction.

The search page always runs keyword mode with case sensitivity off and whole word off, so it takes the substring path. If you want exact-token or case-sensitive matching, use the sidebar pane’s toggles.

Wrapping your query in double quotes turns it into a phrase query in either surface. A phrase query skips the file-name pass entirely, on the assumption that you asked for an exact run of words in the body.

Semantic mode

Semantic search compares meaning rather than words. Your query and every chunk of every note are turned into embeddings by a small model running on your machine, and the closest chunks win. It finds a note about cooking pasta when you search for boiling noodles.

DetailValue
ChunkingNotes are split along headings, targeting about 320 tokens per chunk with a hard cap of 480
RetrievalThe 50 closest chunks are fetched, then grouped by note
Per noteOne result per note, from its best-scoring chunk
Result labelThe chunk’s heading path is shown under the title
Modelbge-small-en-v1.5-int8, 384-dimension embeddings

An empty or whitespace-only query returns nothing rather than an error.

Smart mode

Smart mode runs both searches and merges them by rank, not by raw score, using reciprocal rank fusion with a constant of 60. A keyword ranking of the top 50 notes is fused with the semantic note ranking, so a note that does reasonably well in both lists beats a note that tops only one.

Display text depends on where the note came from. A note that appears in the semantic ranking shows its best chunk’s snippet and heading path. A note that ranked only on the keyword side shows the keyword snippet and no heading path at all, so a smart-mode result list can mix rows with heading paths and rows without.

Smart is the default mode. When semantic search is not ready for the current vault, the page silently falls back to Keyword.

Semantic and Smart stay disabled until semantic search is ready for the vault you have open. Ready means that vault’s vector database is open with semantic search enabled in it, not merely that the model files exist on the machine. Enabling semantic search in one vault leaves the modes grayed out in every other vault until you enable it there too. The disabled buttons carry the tooltip Enable semantic search to use this mode, and the search page shows a banner reading Semantic search is off with an Enable button. The same control lives in Settings under the Semantic search section.

Enabling does three things in order.

  1. It downloads two files, model.onnx and tokenizer.json, from https://releases.jotura.io/models/bge-small-en-v1.5-int8/v1/. The settings helper quotes the size as about 34 MB. Each file’s SHA-256 is verified after download.
  2. It opens the vector store at <vault>/.jotura/vectors.db, registers the model name, version, and 384-dimension size, and marks semantic search enabled for that vault.
  3. It starts a background worker that embeds every note in that vault, and queues a full reconcile so nothing is missed.

Only step 1 is shared across vaults. The model files land in your config directory rather than in the vault, so a second vault reuses the same download and skips straight to building its own index.

PlatformModel directory
Windows%APPDATA%\jotura\models\bge-small-en-v1.5-int8\v1\
macOS~/Library/Application Support/jotura/models/bge-small-en-v1.5-int8/v1/
Linux~/.config/jotura/models/bge-small-en-v1.5-int8/v1/

Download progress appears as a percentage both in Settings and as a progress bar on the search page.

Reading the status rows

Once the model is ready, the Settings section shows two rows, refreshed every two seconds while the modal is open.

RowWhat it shows
StatusThe model version, and the compute backend: GPU (CUDA), GPU (DirectML), GPU (CoreML), CPU, or Unknown
Index<n> chunks · <n> pending, plus an estimated time remaining while embedding is running

If something failed, a Last error row appears with the message and the word Failed.

While the embedding queue is draining, the search page shows one of two notices. With the worker running it reads Still indexing: {n} of {m} remaining · {eta} left; results may be incomplete. With the worker idle but a backlog outstanding it reads Still indexing: {n} notes pending; results may be incomplete. The status bar at the bottom of the sidebar reports the same background work.

Re-indexing and turning it off

ControlWhat it does
Re-index vaultClears the chunks and rebuilds from scratch. There is no confirmation dialog: the rebuild starts on the click, and the row’s helper text is replaced with Re-index queued. Notes are re-embedded in the background.
Turn off & delete indexAsks Turn off semantic search and delete the local index? Your notes are untouched; re-enabling rebuilds the index. and, if you confirm, deletes vectors.db along with its -wal and -shm sidecar files

Turning semantic search off never touches your notes, and keyword search keeps working exactly as before. Re-enabling downloads nothing again if the model files are still present, and rebuilds the index.

Semantic search needs no account and no subscription. The embedding and the querying both happen on your machine, and no note text is uploaded. See Security for the wider picture.

What gets indexed, and what does not

Both the keyword index and the semantic index walk the same file set, so the rules below apply to every mode.

RuleDetail
Text files onlyIndexing covers a fixed list of text extensions: md, markdown, mdc, txt, rst, org, tex, json, yaml, yml, toml, csv, tsv, xml, html, htm, css, scss, sass, js, mjs, ts, tsx, jsx, py, rb, rs, go, java, kt, swift, c, cpp, h, hpp, sh, bash, zsh, fish, ini, conf, env, sql, log, ps1, bat
Size capFiles larger than 25 MB are skipped
Hidden entriesAny file or folder whose name starts with a dot is skipped, so .jotura/ and its contents never appear in results
FrontmatterThe YAML block is split off before indexing. Only the body is searched
TitlesThe title shown on a result is the file name with its extension removed
Shared notesNotes inside a share mount under Shared with me/ are indexed like any other note. Sharing itself requires a paid Sync subscription, priced at /pricing

Because frontmatter is not indexed, a tag written only in frontmatter will not be found by body search. Use the sidebar’s Tags pane for that, or search for the inline #tag form, which is ordinary body text.

Quick open is the exception to the text-only rule. It lists documents and images as well, because it matches names rather than content.

Finding text inside PDFs and Word files

When you import a document, Jotura converts it to markdown and saves the result as a sibling note next to the original: report.pdf gets report.pdf.md. That sibling is a normal note on disk, so it is indexed like any other note and it is searchable in keyword, semantic, and smart modes.

What this means in practice:

  • Searching for a phrase that appears inside a PDF returns a result titled report.pdf, because the title is the sibling’s file name with .md removed.
  • The file tree hides the sibling’s own row, so you see one entry per document. Clicking the document row opens the converted text.
  • Quick open does show both rows, since it matches file names rather than content.
  • If you edit a converted note, Jotura stops regenerating it. Conversion writes a body hash into the note’s frontmatter, and a body that no longer matches that hash is treated as protected and never overwritten.
  • A failed conversion still produces a searchable sibling, but its body is a stub rather than the document’s text. When the converter is unavailable the stub reads The markdown converter is not available yet, so this document could not be indexed., and other failures write a stub naming the reason. So a search can return the document with placeholder text instead of nothing.
  • Clicking a document row that has no sibling yet converts it on demand. The app announces Converting {name}…, then opens the result. If the conversion does not succeed it announces {name} was not converted; its note is user-owned and nothing opens.
  • Conversion is skipped rather than run without OS sandboxing unless you turn on Allow unsandboxed conversion in Settings, and password-protected or corrupt files fail. Settings has Retry failed conversions and Reconvert stale documents actions for this.

Full detail on the import and conversion pipeline is in Documents, and the conversion settings are listed in the Settings reference.

Searching from the command line

The jotura CLI gives scripts and agents their own search commands. Full reference: Reading and searching.

The two surfaces do not share a keyword index. jotura search builds an in-memory index over the whole vault on every invocation and never reads .jotura/index/. The vector database at .jotura/vectors.db is the one index the CLI genuinely shares with the app.

CommandWhat it does
jotura search <QUERY>Full-text search. --limit defaults to 20 and is clamped to 1 through 100 in semantic and smart modes, but passed through unclamped in keyword mode. --mode is keyword, semantic, or smart and defaults to keyword. --in <SCOPE> restricts results to a path prefix
jotura quick-open <QUERY>Fuzzy file-name match, --limit defaults to 20. JSON is [{ "path", "score" }]
jotura search-documents <QUERY>Searches converted document text and returns the original document paths. --limit defaults to 20. JSON is [{ "documentPath", "mdStorePath", "title", "snippet", "score" }], where mdStorePath is the converted sibling. Hits whose sibling cannot be mapped back to an original document are silently dropped, so a result count below --limit is expected
jotura grep <PATTERN>Regular-expression search across note bodies, with -i, -w, -x, -c, -l, -L, --max-count, --include, and --exclude
jotura search "recovery phrase" --json
jotura search "how do I pause uploads" --mode smart --limit 10
jotura search "deadline" --in projects/ --json
jotura quick-open standup --json
jotura search-documents "invoice total" --json
jotura grep -i "TODO" --include "projects/**"

The JSON shape of jotura search differs by mode. Keyword results are [{ "path", "title", "snippet", "score" }], while semantic and smart results are [{ "path", "headingPath", "snippet", "score" }]. A script that reads title from a --mode smart result gets nothing back, so branch on the mode you asked for.

Four more differences from the desktop app are worth knowing before you rely on these.

  • jotura search runs keyword mode with whole-word matching on, while the desktop search page runs it with whole word off. The same query can return different results in the two places, and the CLI results are the BM25-ranked ones.
  • --in works in keyword mode only. Combining it with --mode semantic or --mode smart exits with code 9 (InvalidArgs).
  • The CLI is query-only for semantic search. It embeds your query but never indexes notes, so a note written by the CLI is not semantically searchable until the desktop app indexes it. If semantic search has not been enabled in the app for that vault, or the model or vector database is missing, the command exits with code 13 (SemanticUnavailable) and the message names the missing prerequisite.
  • Building that in-memory keyword index on every invocation is fine for thousands of notes, but do not call jotura search in a tight loop.

Two settings affect which vault and which model the CLI uses.

ControlEffect
--vault <PATH>Chooses the vault for this invocation. Resolution order is --vault, then $JOTURA_VAULT, then the desktop app’s last-opened vault. An inaccessible path or a non-directory exits with code 6 (NoVault)
JOTURA_MODEL_DIROverrides the embedding model directory, which otherwise defaults to the platform paths in the table above. An empty value falls through to the default

Pass --json for machine-readable output on these commands. Errors are JSON on stderr regardless. See Exit codes and JSON output and Documents from the CLI.

Keyboard shortcuts

The global shortcut handler treats Cmd and Ctrl as interchangeable on every platform, and every chord below requires that Alt is not held.

ActionMacWindows and LinuxWhere it works
Toggle quick openCmd+PCtrl+PAnywhere
Open the search pageCmd+Shift+FCtrl+Shift+FAnywhere
Toggle the command paletteCmd+Shift+PCtrl+Shift+PAnywhere
Close the active tab, including the search tabCmd+WCtrl+WAnywhere, when a tab is active
Toggle the sidebarCmd+\Ctrl+\Anywhere
DismissEscapeEscapeAnywhere, see the order below

Escape follows a strict order and stops at the first match: it closes the command palette, then the Settings modal, then quick open, then the search tab if that tab is active. Nothing here searches inside the open note, and no chord is bound to Cmd/Ctrl+F.

Inside the result lists:

KeyQuick openSidebar search paneSearch page
ArrowDown, ArrowUpMove the selection, clamped at both endsMove the selection, clamped at both endsNot handled, use Tab
EnterOpen the selected fileOpen the selected resultActivates the focused result button
EscapeClose quick openBlur the input and return to the Files paneClose the search tab

The full list of app shortcuts is in Keyboard shortcuts.

Troubleshooting

SymptomLikely cause
A note you just created is missing from resultsThe index is still catching up. The sidebar pane and the search page both say so while indexing is in progress
Semantic and Smart are grayed outSemantic search is not enabled for this vault. Enable it in Settings, or from the banner on the search page
Semantic and Smart are grayed out in a second vault after you enabled them in the firstThe enable flag is per vault. The model download is reused, so enabling the second vault only rebuilds its index
Semantic results look thin right after enablingThe embedding queue is still draining. The search page reports how many notes are pending
A large file never matchesFiles over 25 MB are not indexed
Quick open cannot find a video or archive by nameOnly recognized extensions are listed, and media such as mp4 and archives such as zip are not among them
Text inside a PDF is not found, or the result is a placeholderThe document was not converted, or conversion failed and wrote a stub. Check the conversion status and the retry actions in Settings
A frontmatter value is not foundFrontmatter is excluded from the body index by design
Cmd/Ctrl+F does nothingThere is no find inside a note. Search the vault instead

More recovery steps are in Troubleshooting. If you are new to the app, Getting started covers opening a vault and the first index build.