vector-search
Skill19 starsChanged 3 months agoMITView on GitHub
Semantic vector search with moflo — RAG over your own documents, similarity matching, context-aware retrieval via HNSW (node:sqlite-backed). Use when building retrieval layers for chat, search, or context-assembly.
2 other projects use a version of this.
Adopted by
Most recently taken up by
- mozilla/rag-skillstheir own version, first seen Jun 19, 2026
- jpoindexter/theft-kittheir own version, first seen May 20, 2026
Other versions2 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 2
- mozilla/rag-skills★ 2same name
- jpoindexter/theft-kit★ 1same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository30 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- src/CLAUDE.mdCLAUDE.md
- communeSkill
- connector-builderSkill
- distillSkill
- divineSkill
- eldarSkill
- flflSkill
- flo-simplifySkill
- floSkill
- floSkill
- guidanceSkill
- healerSkill
- luminariumSkill
- meditateSkill
- memory-optimizationSkill
- memory-patternsSkill
- memory-teamSkill
- memory-worktreeSkill
- optimize-learningsSkill
- perf-auditSkill
- publishSkill
- quickenSkill
- reasoningbank-intelligenceSkill
- reset-epicSkill
- spell-builderSkill
- spell-scheduleSkill
- test-gapsSkill
- verifySkill
- wardSkill
The file
We split this skill into the rules it gives an agent
3 rules. About 0 are common, 1 is distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 37
Use moflo's shipped indexers (cross-platform, skip unchanged chunks via a hash file):
- Very specific: line 79
Search with threshold: 0.2 and limit: 20 — inspect the ranked results.
- Distinctive: line 129
Don't mix namespaces: Keep each corpus in its own namespace so scores are comparable and threshold tuning actually works.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
MoFlo Vector Search (RAG)
Semantic search over your own documents, backed by moflo's HNSW index in .moflo/moflo.db (node:sqlite, Node 22+ built-in). Small enough to ship in a devDependency; fast enough for interactive retrieval at 100k–1M vectors.
When to Use This vs memory-patterns
memory-patterns— structured, namespaced memory you own (sessions, learnings, patterns). Keys matter. Entries are conceptual units.- This skill (
vector-search) — search over documents you've ingested for retrieval. Entries are content chunks. Keys are just stable IDs for dedupe.
Both use the same index; the difference is how you chunk and what you put in the value field.
Ingest
Two paths. Pick the one that matches your source of truth:
A. Ad-hoc ingest from Claude Code
for (const [id, text] of chunks) {
await mcp.memory_store({
namespace: 'docs', // your RAG corpus
key: id, // stable ID for this chunk (file path + offset, etc.)
value: text, // the chunk content — what gets embedded
tags: ['doc', docType],
upsert: true,
});
}B. Repeatable ingest from the filesystem
Use moflo's shipped indexers (cross-platform, skip unchanged chunks via a hash file):
# Guidance docs → namespace 'guidance'
node .claude/scripts/index-guidance.mjs
# Code structure → namespace 'code-map'
node .claude/scripts/generate-code-map.mjs
# Your own corpus — write a small indexer that loops over files and calls
# memory_store. Model it on bin/index-patterns.mjs.Retrieve
const hits = await mcp.memory_search({
namespace: 'docs',
query: userQuestion,
limit: 8,
threshold: 0.35, // drop irrelevant noise; tune per-corpus
});
// hits[] = [{ key, namespace, value, similarity, ... }]Plug the retrieved value strings into your prompt as context. Filter or rerank higher up if needed.
Chunking Rules That Actually Matter
- One idea per chunk. 200–800 tokens. Smaller for code, larger for prose.
- Include enough context for the chunk to stand alone. A bare "it does X" chunk won't retrieve well because the embedding has no subject.
- Deduplicate by stable ID. Re-ingest is a no-op if
key+valuehash match. Cheap to re-run. - Keep metadata minimal in
value. The embedding is built from the full value — noisy prefixes dilute the vector. Put structured metadata intagsor a separatemeta:${id}key.
Threshold Tuning
The threshold parameter is a similarity floor (0–1, cosine). No universal number.
Workflow for a new corpus:
- Pick 10 queries you care about.
- Search with
threshold: 0.2andlimit: 20— inspect the ranked results. - Note the similarity score where results go from "relevant" to "noise."
- Set
thresholdjust under that cliff. Expect values between 0.3 and 0.6 for most corpora.
Cheaper than trying to predict it.
Hybrid: Semantic + Metadata Filter
moflo's memory_search doesn't have metadata filtering built-in. Do it in two steps:
const candidates = await mcp.memory_search({
namespace: 'docs',
query: q,
limit: 50, // over-fetch
threshold: 0.25,
});
const filtered = candidates.filter(c => c.tags?.includes('api-v2'));
const topK = filtered.slice(0, 8);This is "search then filter" — works well when the filter is permissive. For highly selective filters, reverse the order: list by tag first, then re-rank against the query.
RAG Pattern: Context Assembly
async function answer(question: string) {
const hits = await mcp.memory_search({
namespace: 'docs',
query: question,
limit: 8,
threshold: 0.35,
});
const context = hits
.map((h, i) => `[Source ${i + 1}] ${h.value}`)
.join('\n\n');
return callModel({
system: 'Answer using ONLY the sources below. Cite by source number.',
user: `${context}\n\nQuestion: ${question}`,
});
}Anti-Patterns
- Don't store 50-page documents as single entries. Chunk. Embeddings capture one topic at a time; big values average their meaning into mush.
- Don't set
threshold: 0. You'll get the whole table sorted by similarity — including total noise at the bottom — and waste tokens on worthless context. - Don't re-embed on every query. The embedding cost is in the ingest path; queries reuse the HNSW graph. If you find yourself re-embedding, you're doing it wrong.
- Don't mix namespaces. Keep each corpus in its own namespace so scores are comparable and threshold tuning actually works.
Performance
- 100k chunks, dim 1536: ~5–15ms per search on commodity hardware.
- Cold-start: ~5s to load/build HNSW on first query in a process. Keep the process warm.
- Tuning: see
memory-optimizationskill for M/ef/quantization knobs.
See Also
memory-patternsskill — non-RAG memory usage (sessions, knowledge, patterns)memory-optimizationskill — scaling past ~100k vectorsbin/semantic-search.mjs/flo-searchCLI — shell access to the same index
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

