Skip to content
Back to skills

Vector Search

ASecurity

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.

  • 18 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 20, 2026
ai-agentstypescriptgoshellbashsqlnodeapiperformance

Works with

  • claude code
  • cli
  • api
  • mcp

Security analysis

A100/100

Scanned September 20, 2026

npx -y skills add eric-cielo/moflo --skill vector-search --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Vector Search?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Vector Search
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/eric-cielo-vector-search/badge)](https://www.skillsdirectory.com/skills/eric-cielo-vector-search)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: "vector-search"
description: "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."
---

# 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

```typescript
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):

```bash
# 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

```typescript
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

1. **One idea per chunk.** 200–800 tokens. Smaller for code, larger for prose.
2. **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.
3. **Deduplicate by stable ID.** Re-ingest is a no-op if `key` + `value` hash match. Cheap to re-run.
4. **Keep metadata minimal in `value`.** The embedding is built from the full value — noisy prefixes dilute the vector. Put structured metadata in `tags` or a separate `meta:${id}` key.

## Threshold Tuning

The `threshold` parameter is a similarity floor (0–1, cosine). No universal number.

Workflow for a new corpus:

1. Pick 10 queries you care about.
2. Search with `threshold: 0.2` and `limit: 20` — inspect the ranked results.
3. Note the similarity score where results go from "relevant" to "noise."
4. Set `threshold` just 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:

```typescript
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

```typescript
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-optimization` skill for M/ef/quantization knobs.

## See Also

- `memory-patterns` skill — non-RAG memory usage (sessions, knowledge, patterns)
- `memory-optimization` skill — scaling past ~100k vectors
- `bin/semantic-search.mjs` / `flo-search` CLI — shell access to the same index

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.