mosaic search
Searches every enabled source for a query, merges the duplicates and prints one table. The results go to the local cache; with --cached or --semantic the search runs on the cache alone, with no network.
Usage
mosaic search "hall thruster particle-in-cell" # every enabled source, 10 results each
mosaic search "hall thruster" --source arxiv --year 2020-2025 # one source, a range of years
mosaic search "hall thruster" --field title --sort citations # the words in the title, most cited first
mosaic search "hall thruster" --author Boeuf --oa-only # one author, open access only
mosaic search "hall thruster" --download # and fetch the PDFs
mosaic search "thruster simulation" --cached --sort year # the cache only, newest first
mosaic search "hall thruster" -o refs.bib -o refs.csv # write two files
mosaic search "hall thruster" --json | jq '.count' # JSON on stdoutBehaviour
Duplicates. The same paper from several sources appears once. Papers match on DOI, then arXiv ID, then Elsevier PII, then the first 80 characters of the lower-case title; the merged record keeps the richer value of each field.
--max is per source: with 15 sources answering, --max 5 returns up to 75 rows before merging.
--year takes one year (2020), an inclusive range (2018-2022) or a list (2019,2021,2023). Papers with no year pass the filter.
--author matches a substring of any author name, ignoring case, accents and ligatures: Boeuf matches Bœuf, garrigues matches Garrigués. Repeat it to accept any of several authors.
--journal matches a substring of the journal name, ignoring case: -j Nature also matches Nature Communications.
Where filters apply. Sources whose API supports a filter get it in the query; every result is then filtered again locally, so the table never shows a paper outside the filters.
--field scopes the query to title or abstract, in each source's own syntax; all (the default) is a full-text search.
--raw-query sends a string unchanged to every queried source (for example arXiv's ti:transformer AND au:vaswani), bypassing --field, --author and --journal translation. The local filters still apply.
--sort: citations puts the most cited first and adds a Cited column (papers whose source gives no count go last); year puts the newest first; relevance scores each paper against the query (BM25, or the configured LLM) and adds a Rel. column from 0 to 1.
--cached matches papers whose title or abstract contains every word of the query, in any order. An empty query ("") matches the whole cache.
--semantic ranks the vector index (built by mosaic index) by similarity to the query and adds a Sim. column. --sort citations and --sort year reorder the results; --sort relevance is ignored. --downloaded-only keeps the papers whose PDF is on disk, with --cached or --semantic.
--sort relevance | --semantic | |
|---|---|---|
| Method | BM25 keywords, or an LLM | embedding similarity |
| Needs | nothing (BM25) or an LLM | mosaic index and an embedding model |
| Searches | the results of this search | the local index only |
| Column | Rel. | Sim. |
--prefer-cache replaces a fetched paper with its cached record when the cached one has an abstract, a year and authors.
--output picks the format from the extension: .bib (BibTeX), .ris, .csv, .json, .md (one table) or .markdown (one section per paper, all fields). Repeat it for several files.
--json prints {status, query, count, papers, errors} (plus summary with --summarise) on stdout and nothing else, for scripts and agents.
--summarise asks the configured LLM for one paragraph over the titles and abstracts of the first 40 results (1000 characters of each abstract), citing rows as [n].
--stats prints the results per source and how many were merged. Sources that failed are hidden unless you add the global --verbose: mosaic --verbose search ....
Exit code 1 for an unknown --source, a source that is not active (disabled, or missing its key), a bad --year or --field.
See also: tutorial 1, tutorial 2, searching recipes, sources.
Options
mosaic search [OPTIONS] QUERY| Argument | Value | Description |
|---|---|---|
QUERY | TEXT | Search query |
| Option | Value | Default | Description |
|---|---|---|---|
--max, -n | INTEGER | 10 | Max results per source |
--download, -d | Download available PDFs | ||
--oa-only | Show only open access papers | ||
--pdf-only | Show only papers with a downloadable PDF | ||
--source, -s | TEXT | Limit to one source (arxiv, ss, sd, sp, springer, doaj, epmc, cochrane, oa, base, core, ads, ieee, zenodo, crossref, dblp, hal, pubmed, pmc, rxiv, pedro, scopus) | |
--year, -y | TEXT | Year filter: "2020", "2020-2024", or "2020,2022,2024" | |
--author, -a | TEXT | Author name filter (repeatable) | |
--journal, -j | TEXT | Journal name filter (substring match) | |
--field, -f | TEXT | all | Scope query to "title", "abstract", or "all" (default) |
--raw-query | TEXT | Raw query sent directly to source APIs, bypassing all field transforms | |
--output, -o | PATH | Save results to file (.md, .markdown, .csv, .json, .bib, .ris); repeatable | |
--download-dir | TEXT | Override PDF download directory for this run | |
--sort | TEXT | Sort results: "citations" (most cited first), "year" (newest first), or "relevance" (most relevant first) | |
--zotero | Export results to Zotero | ||
--zotero-collection | TEXT | Zotero collection name (created if missing) | |
--zotero-local | Force Zotero local API even when an API key is configured | ||
--obsidian | Export results as notes to an Obsidian vault | ||
--obsidian-folder | TEXT | Override Obsidian vault subfolder for this run | |
--pedro-fetch-details | Fetch each PEDro record page to get authors, year, DOI and abstract (overrides config for this run) | ||
--stats | Print per-source counts and deduplication stats | ||
--cached | Search only the local cache — no network requests | ||
--semantic | Search the local vector index by meaning instead of keywords (requires 'mosaic index' to have been run) | ||
--downloaded-only | Limit results to papers with a locally downloaded PDF (only with --cached or --semantic) | ||
--prefer-cache | Prefer rich cached records over freshly fetched data for known papers | ||
--json | Emit structured JSON to stdout instead of a table (useful for scripting and AI agents) | ||
--summarise, --summarize | Add a one-paragraph LLM synthesis of the results (requires an LLM set via mosaic config) |

