
Search Config
- 12 installs
- 610 repo stars
- Updated June 26, 2026
- alsk1992/cloddsbot
Search-config is a Claude Code skill for the clodds bot that configures full-text, semantic, and hybrid search indexing across pluggable backends.
About
Search-config is a clodds skill for configuring and managing search indexing over collections like memories and documents. Developers use it to pick a backend (SQLite, Elasticsearch, Typesense, Meilisearch), set full-text, semantic, or hybrid modes, tune weights, and index or rebuild documents. It matters when a bot needs to retrieve stored knowledge by keyword or meaning.
- Configures full-text, semantic, and hybrid search over collections
- Swaps backends: SQLite, Elasticsearch, Typesense, Meilisearch
- Index management: rebuild, optimize, clear, and view stats
Search Config by the numbers
- 12 all-time installs (skills.sh)
- Ranked #3,541 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
search-config capabilities & compatibility
- Capabilities
- search indexing · semantic search · hybrid search
- Works with
- elasticsearch · openai
- Use cases
- web search · data analysis
- Pricing
- Bring your own API key
What search-config says it does
Configure search indexing, manage search backends, and optimize full-text search.
backend: 'sqlite', // 'sqlite' | 'elasticsearch' | 'typesense' | 'meilisearch'
npx skills add https://github.com/alsk1992/cloddsbot --skill search-configAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 12 |
|---|---|
| repo stars | ★ 610 |
| Last updated | June 26, 2026 |
| Repository | alsk1992/cloddsbot ↗ |
What it does
Configure hybrid full-text and semantic search over a bot's stored documents and memories.
Who is it for?
Bots that need to index documents and retrieve them by keyword, meaning, or a hybrid of both.
Skip if: Apps with no stored corpus to search or that use a managed search product directly.
When should I use this skill?
You need to set the search backend, tune semantic vs fulltext weights, or rebuild an index.
What you get
Collections are indexed and searchable via a chosen backend and mode.
- configured search backend
- indexed collections
- hybrid search config
By the numbers
- 4 supported backends
- 3 search modes (fulltext, semantic, hybrid)
Files
Search Config - Complete API Reference
Configure search indexing, manage search backends, and optimize full-text search.
---
Chat Commands
View Status
/search-config Show search config
/search-config status Index status
/search-config stats Search statisticsIndex Management
/search-config rebuild Rebuild all indexes
/search-config rebuild memories Rebuild specific index
/search-config optimize Optimize indexes
/search-config clear <index> Clear indexConfiguration
/search-config backend sqlite Set backend
/search-config backend elasticsearch Use Elasticsearch
/search-config mode hybrid Set search mode
/search-config boost semantic 0.7 Set semantic weight---
TypeScript API Reference
Create Search Service
import { createSearchService } from 'clodds/search';
const search = createSearchService({
// Backend
backend: 'sqlite', // 'sqlite' | 'elasticsearch' | 'typesense' | 'meilisearch'
// Search mode
mode: 'hybrid', // 'fulltext' | 'semantic' | 'hybrid'
// Hybrid weights
semanticWeight: 0.6,
fulltextWeight: 0.4,
// Embedding provider (for semantic)
embeddings: {
provider: 'openai',
model: 'text-embedding-3-small',
},
// Storage
dbPath: './search.db',
});Index Documents
// Index single document
await search.index({
collection: 'memories',
id: 'mem-1',
content: 'User prefers conservative trading',
metadata: {
type: 'preference',
userId: 'user-123',
},
});
// Index batch
await search.indexBatch({
collection: 'documents',
documents: [
{ id: 'doc-1', content: 'First document', metadata: {} },
{ id: 'doc-2', content: 'Second document', metadata: {} },
],
});Search
// Full-text search
const results = await search.search({
query: 'trading strategies',
collection: 'documents',
limit: 10,
});
for (const result of results) {
console.log(`${result.id}: ${result.score}`);
console.log(` ${result.snippet}`);
}
// With filters
const results = await search.search({
query: 'bitcoin',
collection: 'news',
filters: {
date: { gte: '2024-01-01' },
source: 'reuters',
},
limit: 20,
});Hybrid Search
// Combine full-text and semantic
const results = await search.hybridSearch({
query: 'how to manage risk in trading',
collection: 'documents',
semanticWeight: 0.7,
fulltextWeight: 0.3,
limit: 10,
});Get Index Stats
const stats = await search.getStats();
console.log('Index Statistics:');
for (const [collection, info] of Object.entries(stats.collections)) {
console.log(`${collection}:`);
console.log(` Documents: ${info.documentCount}`);
console.log(` Size: ${info.sizeMB} MB`);
console.log(` Last indexed: ${info.lastIndexed}`);
}
console.log(`\nSearch Stats:`);
console.log(` Queries today: ${stats.queriesToday}`);
console.log(` Avg latency: ${stats.avgLatencyMs}ms`);
console.log(` Cache hit rate: ${stats.cacheHitRate}%`);Rebuild Index
// Rebuild all indexes
await search.rebuildAll();
// Rebuild specific collection
await search.rebuild('memories');
// With progress callback
await search.rebuild('documents', {
onProgress: (progress) => {
console.log(`${progress.current}/${progress.total} (${progress.percent}%)`);
},
});Optimize Index
// Optimize for better performance
await search.optimize();
// Optimize specific collection
await search.optimize('documents');Clear Index
// Clear specific collection
await search.clear('memories');
// Clear all
await search.clearAll();Configure Backend
// Switch to Elasticsearch
await search.setBackend('elasticsearch', {
url: process.env.ELASTICSEARCH_URL,
index: 'clodds',
});
// Switch to Typesense
await search.setBackend('typesense', {
url: process.env.TYPESENSE_URL,
apiKey: process.env.TYPESENSE_API_KEY,
});---
Search Backends
| Backend | Best For | Features |
|---|---|---|
| SQLite | Development, small data | Simple, embedded |
| Elasticsearch | Production, large data | Scalable, powerful |
| Typesense | Fast search | Typo tolerance |
| Meilisearch | Instant search | Easy setup |
---
Search Modes
| Mode | Description |
|---|---|
fulltext | Traditional keyword matching |
semantic | Vector similarity search |
hybrid | Combined (best of both) |
---
Hybrid Search Weights
// More emphasis on meaning
const results = await search.hybridSearch({
query: 'risk management',
semanticWeight: 0.8, // 80% semantic
fulltextWeight: 0.2, // 20% keyword
});
// More emphasis on exact matches
const results = await search.hybridSearch({
query: 'BTCUSDT',
semanticWeight: 0.2, // 20% semantic
fulltextWeight: 0.8, // 80% keyword
});---
Best Practices
1. Use hybrid search — Best results for most queries 2. Rebuild periodically — Keep indexes fresh 3. Optimize after bulk inserts — Improve performance 4. Monitor latency — Scale if too slow 5. Tune weights — Adjust semantic/fulltext balance
/**
* Search Config CLI Skill
*
* Commands:
* /search-config - Show search configuration
* /search-config weights - Show vector/BM25 weights
* /search-config set vector-weight <0-1> - Set vector weight
* /search-config set bm25-weight <0-1> - Set BM25 weight
* /search-config test <query> - Run a test BM25 keyword search
*/
// In-memory config state (applied when creating new search services)
let currentConfig = {
vectorWeight: 0.5,
bm25Weight: 0.5,
minScore: 0.1,
};
async function execute(args: string): Promise<string> {
const parts = args.trim().split(/\s+/);
const cmd = parts[0]?.toLowerCase() || 'show';
try {
// Verify the search module is importable
const searchMod = await import('../../../search/index');
switch (cmd) {
case 'show':
case '': {
return `**Search Configuration**
Mode: hybrid (Vector + BM25)
Vector weight: ${currentConfig.vectorWeight}
BM25 weight: ${currentConfig.bm25Weight}
Min score threshold: ${currentConfig.minScore}
BM25 k1: 1.5 (term frequency saturation)
BM25 b: 0.75 (length normalization)
Available methods: \`bm25Search\`, \`createHybridSearchService\``;
}
case 'weights': {
const total = currentConfig.vectorWeight + currentConfig.bm25Weight;
const vectorPct = total > 0 ? Math.round((currentConfig.vectorWeight / total) * 100) : 50;
const bm25Pct = total > 0 ? Math.round((currentConfig.bm25Weight / total) * 100) : 50;
return `**Search Weights**
Vector (semantic): ${currentConfig.vectorWeight} (${vectorPct}%)
BM25 (keyword): ${currentConfig.bm25Weight} (${bm25Pct}%)
Vector catches meaning similarities (e.g. "car" matches "automobile").
BM25 catches exact keyword matches (e.g. "TypeError" matches "TypeError").
Adjust with:
/search-config set vector-weight <0-1>
/search-config set bm25-weight <0-1>`;
}
case 'set': {
const param = parts[1]?.toLowerCase();
const value = parseFloat(parts[2]);
if (isNaN(value) || value < 0 || value > 1) {
return 'Value must be a number between 0 and 1.';
}
if (param === 'vector-weight') {
currentConfig.vectorWeight = value;
currentConfig.bm25Weight = parseFloat((1 - value).toFixed(2));
return `Vector weight set to **${value}**. BM25 weight auto-adjusted to **${currentConfig.bm25Weight}**.\n\nNew searches will use these weights.`;
}
if (param === 'bm25-weight') {
currentConfig.bm25Weight = value;
currentConfig.vectorWeight = parseFloat((1 - value).toFixed(2));
return `BM25 weight set to **${value}**. Vector weight auto-adjusted to **${currentConfig.vectorWeight}**.\n\nNew searches will use these weights.`;
}
if (param === 'min-score') {
currentConfig.minScore = value;
return `Min score threshold set to **${value}**. Results below this score will be filtered out.`;
}
return 'Usage: /search-config set <vector-weight|bm25-weight|min-score> <0-1>';
}
case 'test': {
const query = parts.slice(1).join(' ');
if (!query) {
return 'Usage: /search-config test <query>\n\nRuns a BM25 keyword search against sample data to verify the search module is working.';
}
// Run a quick BM25 test search against sample documents
const sampleDocs = [
'TypeScript is a typed superset of JavaScript',
'BM25 is a bag-of-words retrieval function',
'Vector search uses embeddings for semantic similarity',
'Hybrid search combines keyword and vector search',
'The search config controls weight distribution',
];
const results = searchMod.bm25Search(
query,
sampleDocs,
(doc: string) => doc,
5
);
if (results.length === 0) {
return `**BM25 Test Search:** "${query}"\n\nNo results found.`;
}
let output = `**BM25 Test Search:** "${query}"\n\n`;
for (let i = 0; i < results.length; i++) {
const r = results[i];
if (r.score > 0) {
output += `${i + 1}. [${r.score.toFixed(3)}] ${r.item}\n`;
}
}
return output;
}
case 'reset': {
currentConfig = { vectorWeight: 0.5, bm25Weight: 0.5, minScore: 0.1 };
return 'Search config reset to defaults (50/50 vector/BM25, 0.1 min score).';
}
case 'export': {
const json = JSON.stringify(currentConfig, null, 2);
return `**Current Config (JSON)**\n\n\`\`\`json\n${json}\n\`\`\`\n\nUse this with \`createHybridSearchService(embeddings, config)\`.`;
}
default:
return helpText();
}
} catch (error) {
return `Error: ${error instanceof Error ? error.message : String(error)}`;
}
}
function helpText(): string {
return `**Search Config Commands**
/search-config - Show configuration
/search-config weights - Show search weights
/search-config set vector-weight <v> - Set vector search weight (0-1)
/search-config set bm25-weight <v> - Set BM25 keyword weight (0-1)
/search-config set min-score <v> - Set minimum score threshold
/search-config test <query> - Test BM25 keyword search
/search-config reset - Reset to defaults
/search-config export - Export config as JSON`;
}
export default {
name: 'search-config',
description: 'Configure hybrid search weights for vector and BM25 retrieval',
commands: ['/search-config'],
handle: execute,
};
Related skills
FAQ
Which search backends are supported?
SQLite, Elasticsearch, Typesense, and Meilisearch.
What search modes exist?
Fulltext keyword matching, semantic vector search, and hybrid combining both.