/skills
Skills
Markdown instruction sets discovered across a dozen agent directories. A match rides along as a hint — «this skill may apply, load it with the skill tool» — so capability discovery isn’t your job.
❯ /rag▊
Embeddings, keyword search and rank fusion, all on your CPU. This is what happens to every prompt before it reaches the model — and what happens when any part of it is missing.
0.927
MRR — skills
0.836
MRR — MCP tools
120 MB
model, downloaded once
3
corpora, one engine
── the pipeline
Neither half is trusted alone: embeddings catch the paraphrase, keywords catch the identifier embeddings smooth away, and reciprocal rank fusion settles the argument.
01
Quantized ONNX through fastembed, multilingual, 384 dimensions. It runs on a blocking thread, so the event loop never waits on an embedding.
02
Snowball stemming for English and Russian, so release, releasing and «релиз» collapse onto the same stem before scoring.
03
Reciprocal rank fusion over both rankings, then a cosine floor (min_dense_score = 0.80) for candidates with no keyword overlap. Top 3 per corpus, per turn.
semantic/index.rs — the shape of a hit
// dense + lexical, fused by reciprocal rank
skill releasing dense 0.93 kw 0.71 → rrf 1
mcp playwright.click dense 0.88 kw 0.55 → rrf 2
history 2026-08-29 checkpoints dense 0.81 kw 0.64 → rrf 3
── three corpora
Skills, tools and your own history are indexed the same way and searched by the same code — the difference is only what a hit is allowed to do next.
/skills
Markdown instruction sets discovered across a dozen agent directories. A match rides along as a hint — «this skill may apply, load it with the skill tool» — so capability discovery isn’t your job.
/mcp · tool_search
Every connected server’s tools are indexed by name and description. Matches get their full schema inlined; everything else stays a one-line summary until it is asked for.
/search · history_search
Sessions are chunked, embedded and persisted to data_dir/semantic/history.json, incrementally, with a per-session watermark so a restart re-reads a marker and not the corpus.
── deferred schemas
One Playwright server is about 25 tool definitions. Sending all of them on every request is how a context window disappears before the work starts.
every request, the usual way
tools: [
{"name":"playwright__browser_click",
"description":"Perform click on a web page…",
"inputSchema":{"type":"object","properties":{…}}},
{"name":"playwright__browser_type", …},
{"name":"playwright__browser_navigate", …},
… 22 more, every request, whether or not
this turn has anything to do with a browser
]every request, deferred
mcp servers:
playwright (25 tools)
github (18 tools)
// the turn mentions a browser →
+ playwright__browser_click (full schema, inlined)
// or the model asks for more:
tool_search("scrape a page")mcp_schemas = "auto" defers above twelve tools, "full" never defers, "deferred" always does. Turn RAG off entirely and full schemas come back on their own — the model is never left guessing what exists.
── your own history
The agent has solved things with you before. That transcript is an index, not an archive — both you and the model can query it.
/search compaction
❯ /search how did we fix the PoW stall
sort: relevance role: any unique: on
1. 2026-08-29 · checkpoints 0.91
"…the solver moved to a blocking thread so the
event loop never waits on SHA-3…"
2. 2026-08-14 · deepseek auth 0.78
↵ opens that session s sort r role u unique── controls
A layer you can’t turn off is a liability. This one is four commands and four config keys.
config.toml
[semantic]
enabled = true # /rag on|off flips this
top_k = 3 # hints per corpus per turn
min_dense_score = 0.80 # cosine floor without keyword overlap
mcp_schemas = "auto" # auto | full | deferred
── failure modes
Every dependency here is optional at runtime, and each one has a defined answer for being missing.