vecfinder

Document searching tool based on embedding vectors
git clone git://git.finwo.net/app/vecfinder
Log | Files | Refs

commit 5d1bf412d6266ccb37a618e30b7f3a0f7cc3bfa5
parent 98cf85840d8e67a0f0fde4156bf40eb7b25965a1
Author: finwo <finwo@pm.me>
Date:   Sat, 21 Mar 2026 19:07:12 +0100

Add non-interactive mode

Diffstat:
Mvecfinder.js | 63++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 62 insertions(+), 1 deletion(-)

diff --git a/vecfinder.js b/vecfinder.js @@ -623,15 +623,76 @@ class UI { } } +function waitForIndexing(store) { + return new Promise(resolve => { + const check = () => { + if (store.consumersActive === 0 && store.documents.size > 0) { + store.removeListener('documentAdded', check); + resolve(); + } + }; + store.on('documentAdded', check); + check(); + }); +} + +function printUsage() { + stdout.write(`Usage: vecfinder [options] + vecfinder --query <text> [-k N] + +Options: + -h, --help Show this help message + --query <text> Search directory for best match (non-interactive) + -k <number> Number of results to return (default: 1, requires --query) + --no-bat Disable bat syntax highlighting (interactive mode) +`); +} + // Main async function main() { const args = process.argv.slice(2); - const useBatFlag = args.includes('--no-bat') ? false : null; + const queryArgIdx = args.indexOf('--query'); + const hasQueryFlag = queryArgIdx >= 0; + const queryText = hasQueryFlag ? (args[queryArgIdx + 1] || null) : null; + const kArgIdx = args.indexOf('-k'); + const k = kArgIdx >= 0 ? Math.max(1, parseInt(args[kArgIdx + 1], 10) || 1) : 1; + const showHelp = args.includes('--help') || args.includes('-h'); await loadConfig(); await fs.mkdir(CACHE_DIR, { recursive: true }); + if (showHelp) { + printUsage(); + process.exit(0); + } + const store = new DocumentStore(); + + if (hasQueryFlag) { + if (!queryText) { + printUsage(); + stderr.write('Error: --query requires a text argument\n'); + process.exit(1); + } + + indexDirectory(store, process.cwd()); + + try { + await waitForIndexing(store); + const raw = await fetchEmbedding(queryText); + store.queryVec = normalize(raw); + const results = store.getResults().slice(0, k); + for (const r of results) { + stdout.write(r.id + '\n'); + } + process.exit(0); + } catch (err) { + stderr.write(`Error: ${err.message}\n`); + process.exit(1); + } + } + + const useBatFlag = args.includes('--no-bat') ? false : null; const ui = new UI(store, useBatFlag); ui.init();