Use

Search

This page is for anyone looking something up in their own corpus: how a search is ranked, the filters you can type into a query, the commands that read, trace and delete what you find, and read-only SQL over structured data. The same search runs in the portal, the CLI and the mobile apps; the agent uses it too when it answers a question.

Searching

A search runs your query two ways at once: as BM25 keyword matching over full-text chunks, and as vector similarity against embeddings of the same chunks. The two ranked lists are merged with Reciprocal Rank Fusion (RRF), which rewards a document for ranking high on either list, so a document that matches your exact words or only your meaning still surfaces near the top.

Small indexed scopes use bounded exact vector scoring, so unrelated source updates do not change their nearest-neighbor ranking. Larger scopes use approximate search; its recall can change as the index evolves. Visibility and source filters apply to both.

During a backfill, completed indexing pages become searchable while later pages are still processing. Results remain incomplete until indexing catches up; a completed scan can still contain documents that were skipped or could not be embedded.

Keyword matching ranks from a copy of the full-text index that the gateway holds in memory, so it takes milliseconds even for queries made of common words. The copy is built in the background after the gateway starts and rebuilt as your corpus changes; until it is ready, searches rank from the index on disk. It uses memory in proportion to your corpus, about 0.7 GB for 200,000 emails, files and messages, and up to twice that while a rebuild runs. Set search.bm25.memoryIndex to false in omnesis.json and restart the gateway to rank from disk only.

  1. Queryinvoice from:maya after:2026-01-01
  2. ParseInline filters split from the free text; person filters resolved to people

Keyword

  1. BM25Full-text match over chunks

Always runs.

Semantic

  1. EmbedThe free text becomes a vector
  2. Nearest chunksVector index lookup

Skipped until an embedder is assigned and chunks are embedded.

  1. FuseReciprocal Rank Fusion of both lists
  2. RankType boosts from search.boosts and a balance across sources
  3. ResultsDuplicates dropped, top results kept, each with a short ID
  4. Readomnesis show <id>
A query is parsed into filters and free text, searched by keyword and by meaning within those filters, fused into one ranking, and returned with short IDs you can open.

Filters restrict every lane before anything is ranked. The ranking settings, including search.boosts.typeBoosts, are described under Operating → Configuration.

The semantic lane needs an embedder assigned (see Operating → Models) and chunks that have already been embedded. Documents are indexed for keyword search even without an embedding model. Until both hold, keyword matching alone carries queries, and meaning-aware ranking joins in for each document as its vectors land. There is nothing to switch on; the pipeline uses whatever signals exist at query time. When embeddings become available after keyword-only indexing, vectors are rebuilt for the retained corpus while keyword results remain available. Search responses report the active embedding model as assignments change, without requiring a gateway restart. The semantic lane also stays off while the vector index does not fit in the gateway's memory budget; see Semantic search is degraded.

A query made only of filters, with no free text (from:maya type:email), skips ranking altogether and lists the matching documents newest first.

❯ omnesis search "lease renewal"

1. Re: Lease renewal — 12-month extension  (8.3%)
   a1b2c3d4  gmail  email  05/14/26  Maya Reeves
   Attached is the signed renewal for the 12-month extension starting July 1...
   https://mail.google.com/mail/u/0/?authuser=you%40example.com#all/18f2a9c4e7b1d3a0

2. Lease renewal checklist  (6.1%)
   e5f6a7b8  apple-notes  note  05/02/26
   Confirm the deposit terms, ask about bike storage, forward the signed copy...

2 results in 41ms, bm25:8ms, vec:23ms

# narrow with inline filters and a result cap

❯ omnesis search "invoice from:maya after:2026-01-01" --limit 5

Each result leads with a short document ID you can paste straight into omnesis show, and ends with a link to the original when the source provides one. The portal's search page and the apps run the same pipeline against the same index, with the same query language. The portal's search address carries its query (/portal/search?q=lease%20renewal), so a search can be bookmarked or linked.

Time in queries

Words that name a time, such as last week, tomorrow, in March, Q3 2025 or 15 juin, are read as a calendar window. A third lane then ranks only the documents inside that window by the rest of the query, within the same filters, and its list is fused with the keyword and semantic lists. A document is inside the window when it was sent or written there, or when it is about a day there: a calendar event, a booking, or a date mentioned in its text. So dentist next month finds the confirmation that arrived weeks ago, and invoice from last March prefers that March's invoice over older ones that use the same words.

The window is a preference, not a filter: a strong match from another time still appears. To restrict results to a range, use after: and before: (see Query syntax). A day or month written without a year reads as its nearer occurrence, or as both the last and the next one when they are close or when the period is a month or longer; words like last, ago and paid, or next, upcoming and tomorrow, settle the direction. English, French and Spanish phrases are read, in the time zone the client sends (the portal, the CLI and the agents send theirs) or else the gateway's. The lane is on by default; set search.temporal.enabled to false in omnesis.json and restart the gateway to turn it off. search.temporal.weight sets its weight in the fusion.

Graph context is enabled by default for unrestricted agent search. Set search.v2.enabled to false in omnesis.json and restart the gateway to restore the legacy projection or run an A/B comparison. Operator portal sessions with read and admin access show additional facts beside search results: other documents with matching text, device paths and observed connections described in ordinary sentences. Up to five other document titles are linked inline, with a source icon before each title. The current document is omitted from that list; IDs and internal edge codes are hidden. The CLI's --agent-context option exposes the corresponding agent search projection. Matching extracted text does not establish identical file bytes, and bounded trails do not establish a complete sharing history. Built-in agents receive readable graph facts with a document reference table and explicit traversal limits, on the leading results and on later results that several documents link to. References resolve to document IDs and available links; matching text does not establish identical file bytes.

The iOS and Android Search screens also show these facts beneath the highest-ranked results when the gateway supports graph context and search.v2.enabled is enabled. Linked document titles open in the app. Search rankings and snippets remain unchanged. An older gateway, or one with graph context disabled, continues to serve ordinary search results; older apps continue to search an upgraded gateway.

Query syntax

Filters are typed inline, mixed freely with search text. Whatever is left after the filters are stripped becomes the query.

Filter Matches Example
from: Person is the sender, author, or owner. Alias: by: from:maya
to: Person is a recipient of a message or an attendee of an event to:"Jamie Lopez"
with: Person appears in any role with:maya
type: Document type. Alias: in: type:email
source: A source or provider — bare type, full source ID, or provider source:gmail
after: Date lower bound. Alias: since: since:"last week"
before: Date upper bound. Alias: until: before:2026-03-01
#tag Tagged documents. Alias: tag: #travel

Values with spaces take quotes (with:"Maya Reeves"). Dates are ISO YYYY-MM-DD or a relative keyword: today, yesterday, "last week", "last month", "last year". A date that fails to parse is dropped, and the response carries a notice saying so (visible with --json) rather than silently pretending the filter applied. Relative keywords resolve to a UTC calendar date on the gateway's clock, not the device you are searching from; pass an absolute date when a day boundary is what the query turns on.

Person filters resolve to people, not strings. A value is matched as an exact email address, then as an exact phone number, then as part of a name, so from:maya matches every person whose name contains "maya" (up to ten). Use a full name to narrow the match or an email address to pin one person, and me (from:me) for yourself.

Once resolved, every identity merged into that person counts: Omnesis merges identities across sources into one person (see People & graphs), so from:"Maya Reeves" finds her whether a document carries her work email, her personal address, or her phone number. A value that matches no one is reported as a notice (visible with --json). Repeating a person filter widens it (from:maya from:jamie means either); different filters combine with AND.

Search finds documents; these commands work with what you found. The document commands — show, trail, and delete — accept the short IDs printed in search results; any unambiguous prefix works.

# read one document in full

❯ omnesis show a1b2c3d4

# find the indexed document for a page you have open

❯ omnesis lookup "https://docs.google.com/document/d/1AbC.../edit"

# the latest documents from one source (IDs from: omnesis sources)

❯ omnesis recent gmail:you@example.com

# the chronological story around a document — replies, attachments, related events

❯ omnesis trail a1b2c3d4

# the same neighbourhood as a graph: documents, people and the links between them

❯ omnesis graph walk a1b2c3d4

# fuzzy people lookup by name, email, phone, or handle

❯ omnesis people search maya

# delete a document for good (a later sync or capture will not add it back)

❯ omnesis delete a1b2c3d4

# delete only this copy; the next sync or capture may add it again

❯ omnesis delete a1b2c3d4 --copy

trail walks the reference graph — thread replies, attachments, links, shared people — outward from a document and lays the connected documents out in time order. One invoice becomes the whole story: the quote before it, the chat where it was discussed, the calendar event it paid for.

graph walk follows the same links but returns the neighbourhood as a graph rather than a timeline: every document and person reachable from the seed, and the edge that connects each pair. --edges and --vertex-types limit what the walk follows, --hops bounds how far it goes (at most 15), --bound-rows adds the analytics rows bound to the documents it reaches, and --json prints the raw result.

Deleting has two forms, and the CLI, the portal and the phone apps all offer both. Delete for good removes the document and its extracted attachments, and records that it must stay gone: the source that produced it will not add it back on a later sync or capture, and the analytics rows that were about that page go with it. Removing the whole source clears that record, so a re-added source starts clean. Delete this copy removes the document as well, but the next sync or capture may add it again. Neither touches the original in the provider or on the phone, and neither removes the tasks or memories built on the document: they stay, without their link to it, along with any text they quoted from it.

omnesis delete asks you to confirm, with Cancel preselected unless you passed --copy; in a script, or with --json, pass --yes. A day document built from quick captures cannot be deleted directly: delete or amend its notes on the portal's Tell Omnesis page instead.

SQL over your analytics

Structured sources — health metrics, screen time, workouts, browser visits — land as typed rows in an analytics database (DuckDB) alongside the document index. omnesis analytics lists every table with its description and row count (add --json for column schemas); omnesis sql queries them directly, as does the Debug → Data tools → SQL tab in the portal.

# which apps ate the last 30 days?

❯ omnesis sql "SELECT app_name, round(sum(total_seconds)/3600.0, 1) AS hours FROM screen_time_daily WHERE date >= current_date - INTERVAL 30 DAY GROUP BY app_name ORDER BY hours DESC LIMIT 3"

app_name  hours
───────────────
Safari    31.4
Mail      18.2
Messages  12.9

3 rows (12ms)

# monthly running volume this year

❯ omnesis sql "SELECT strftime(start_time_local, '%Y-%m') AS month, round(sum(distance_m)/1000.0, 1) AS km FROM strava_activities WHERE sport_type = 'Run' GROUP BY 1 ORDER BY 1"

Queries are read-only by construction: each one runs inside a read-only transaction on the gateway's own database instance, whose access to the filesystem is switched off, so SQL can inspect your data but never modify it or reach outside the database. Which tables exist depends on which sources you have connected.

A timestamp stored with its zone comes back as a UTC instant (2026-10-18T17:28:00.000Z), a date as YYYY-MM-DD, and a timestamp stored without a zone as the wall-clock time the source recorded.

From your own tools

Everything on this page is a thin client over the gateway's authenticated HTTPS API. The portal, the CLI and the apps all call the same endpoints, and so can any script holding a token; Setup → Tokens covers minting one with omnesis tokens create and choosing its scopes. To let an AI tool such as Claude or ChatGPT search your corpus, connect it over MCP instead: see Agents & MCP. The full command list is in omnesis --help.

The graph walk behind omnesis graph walk is one endpoint, POST /graph/walk, open to any token with the read scope. It starts from up to 50 documents, named by ID or unambiguous prefix, takes the same limits as the command's flags, and returns the vertices and edges it reached, with truncated set when a limit cut the walk short.

curl -s -X POST "$OMNESIS_GATEWAY_URL/graph/walk" \
  -H "Authorization: Bearer $OMNESIS_TOKEN" -H "Content-Type: application/json" \
  -d '{"start": [{"kind": "document", "id": "a1b2c3d4"}], "maxHops": 2}'