Docs
Library & search
How anymd saves your conversions and searches them with BM25, full-text, semantic and hybrid modes, query fan-out, RRF and Jev.
Sign in (or use an API key) and every conversion lands in your private library. Then you can find it again the way you remember it: by exact words, by a phrase, or by the idea.
What gets saved
- One document per source URL. Converting the same URL again refreshes the document instead of duplicating it.
- Markdown plus metadata: title, author, domain, site, published date, language, source kind, word count, and your tags.
- Only yours. Every query, keyword and semantic, is filtered to your user id. Nobody else's documents can appear in your results.
- Opt out per call with
save=0(URL API),"save": false(REST),--no-save(CLI) orsave: false(MCP).
Semantic indexing runs in the background right after a save. A brand-new document is findable by keyword immediately and by meaning a moment later.
The Free plan keeps up to 1,000 documents; paid plans are unlimited. See Billing & credits.
Search modes
| Mode | Best for | How |
|---|---|---|
hybrid (default) |
Most queries | bm25 + semantic, fused with Reciprocal Rank Fusion |
bm25 |
Keywords you remember | SQLite FTS5 BM25 over title, description, body, domain and tags. Title and tag matches weigh most. |
fulltext |
Precise queries | Raw FTS5 syntax (see below) |
semantic |
Ideas, not words | bge-m3 embeddings in Cloudflare Vectorize |
Search costs 0 credits in every mode.
Full-text syntax
mode=fulltext passes your query to SQLite FTS5:
| Syntax | Example |
|---|---|
| Phrase | "reciprocal rank fusion" |
| Boolean | cloudflare AND workers NOT pages |
| Prefix | embed* |
| Column filter | title:markdown, domain:github.com |
If the syntax is invalid, anymd falls back to plain keyword matching instead of failing the request.
Query fan-out
Add fanout=1 and a small, fast language model rewrites your query into up to three variants: one with synonyms, one more specific, one more general. anymd runs every variant through the selected mode and fuses all the lists. The variants come back in the response so you can see what was searched.
Fan-out helps most with short or vague queries ("that post about pricing"). It adds a little latency; if the rewrite fails, the search simply runs with your original query.
Reciprocal Rank Fusion
Hybrid mode and fan-out produce several ranked lists. anymd merges them with Reciprocal Rank Fusion using k = 60: each document scores the sum of 1 / (60 + rank) over every list it appears in. Documents that rank well in several lists rise to the top; no score normalisation between BM25 and vectors is needed.
Each hit's matched array tells you which retrievers found it (bm25, fulltext, semantic).
Jev: breaking near-ties
Sometimes the top two fused results are too close to call. When the gap between #1 and #2 is under 25% of #1's score, anymd can ask Jev (TypeSafe System One) which candidate most directly answers the query.
- Jev only sees candidates that were already filtered to your library.
- It only reorders when it is confident (a high top probability with a clear margin over the runner-up). Otherwise the fused order stands.
- Timeouts or errors fall back to the fused order. Search never fails because of Jev.
- Emails and API-key-looking strings are masked in the query before it is sent.
The jev field in the response reports what happened: used, choice, confidence and a reason such as decided, low_confidence, none or disabled.
Request
curl -G https://anymd.cc/api/v1/search \
-H "Authorization: Bearer $ANYMD_API_KEY" \
--data-urlencode "q=why markdown for agents" \
-d mode=hybrid -d fanout=1 -d limit=10
| Param | Default | Notes |
|---|---|---|
q |
required | Up to 500 characters are used |
mode |
hybrid |
hybrid, bm25, fulltext, semantic |
limit |
10 |
1 to 50 |
fanout |
off | 1 to enable query fan-out. Pro and above |
decide |
off | 1 lets Jev break near-ties. Pro and above |
On Free, fanout and decide are skipped and named in the response's gated array; results use standard ranking.
Same fields work as a JSON body on POST /api/v1/search, via anymd search in the CLI, and via the search_library MCP tool.
Response
{
"query": "why markdown for agents",
"mode": "hybrid",
"variants": ["markdown benefits for AI agents", "…"],
"hits": [
{
"id": "doc_…",
"title": "Why Markdown is the language of AI agents",
"url": "https://…",
"domain": "anymd.cc",
"source_kind": "web",
"snippet": "…models read <mark>markdown</mark> structure…",
"score": 0.03252,
"matched": ["bm25", "semantic"],
"created_at": 1790000000000,
"word_count": 1480
}
],
"jev": null,
"took_ms": 212
}
Values are illustrative. Snippets from keyword matches wrap hits in <mark> tags; escape or strip them before rendering. created_at is a Unix timestamp in milliseconds.
Tips
- Remember exact words?
bm25. Remember a phrase?fulltextwith quotes. Remember the gist?semanticorhybrid. - Tag documents with
PATCH /api/v1/library/:id({"tags": ["rag", "research"]}); tags are indexed and weighted highly. - Browse instead of search with
GET /api/v1/library?domain=github.comor?kind=youtube.
Updated 2026-09-26 · Edit on GitHub