Semantic Search, /recall¶
What it indexes¶
memory/(daily logs, general, handoffs, sessions)nexus/(shared brain: fleet, architecture, steering)docs/(infra docs, playbooks, operations)brands/(brand context)CLAUDE.md(bootstrap)
Skips binary/large files (>1MB), .venv, node_modules, .git, screenshots.
Stack¶
- Embeddings:
fastembedwithBAAI/bge-small-en-v1.5(ONNX, 384-dim, ~150MB footprint). CPU-only. - Storage: sqlite +
sqlite-vecextension. DB atdata/search/index.db. - Chunking: Markdown-aware, splits by heading then by 800-char windows with 100-char overlap.
- Venv:
~/.forge-venvs/search/(independent fromassets/andintegrations/venvs).
v2 three-layer retrieval (2026-05-04)¶
/recall no longer dumps full chunk bodies on every query. Three modes:
| Layer | Flag | Returns |
|---|---|---|
| 1, search | bare query | [chunk_id] path date \| summary score=0.NN per hit |
| 2, timeline | --timeline <id> --window N |
Same-file neighbors ordered by chunk_idx, anchor marked |
| 3, details | --get a3f2,b8c1 |
Full chunk bodies for explicit IDs |
Layer 1 is gated behind FORGE_RECALL_V2=1 during the dogfood week; without
the env var, the bare query form still prints v1-style full bodies. Use
--full to force v1 behavior even with the env var set.
Schema additions backing v2:
- chunks.chunk_id (4-hex sha1 of path:chunk_idx, collision-extended)
- chunks.summary (first 80 chars, word-boundary truncation, ellipsized)
- meta(key, value) table tracking schema_version=2
v1->v2 upgrade drops chunks + chunk_vecs and clears files to force
a single full re-embed (~1-2 min on current corpus, ~5200 chunks).
Invocation¶
Via skill (preferred in-session):
/recall how does the task dispatcher route workers
/recall -k 10 eight sleep credentials
/recall --json frigate config
/recall --get 1b14
/recall --timeline 1b14 --window 3
/recall --full <query>
Direct CLI:
FORGE_RECALL_V2=1 /home/justinwieb/.forge-venvs/search/bin/python \
/home/justinwieb/forge/scripts/forge_search_query.py "query here"
Reindex (incremental, only changed files):
/home/justinwieb/.forge-venvs/search/bin/python \
/home/justinwieb/forge/scripts/forge_search_index.py
Full rebuild:
/home/justinwieb/.forge-venvs/search/bin/python \
/home/justinwieb/forge/scripts/forge_search_index.py --rebuild
Maintenance¶
- Nightly cron at 03:30 re-runs
forge_search_index.py --quiettologs/search-index.log. - First run after corpus change: ~1-2 min for ~5200 chunks on Console CPU.
- Incremental runs complete in seconds.
- Bench harness
scripts/forge_recall_bench.pylogs v1-vs-v2 sizes todata/recall-bench/<date>.jsonl.
When to use vs grep¶
grepfor exact strings, literal filenames, or known symbols./recallfor "where did we decide", "how was X set up", fuzzy concepts./recall --timelineonce you've found the right chunk and want surrounding context./recall --getonce you've found the right chunk and want full body.
Files¶
scripts/forge_search_index.py, walker + chunker + embedderscripts/forge_search_query.py, three-layer CLI frontendscripts/forge_recall_bench.py, v1-vs-v2 bench harness.claude/skills/recall/SKILL.md, slash-command wrapperdata/search/index.db, sqlite DB (gitignored, ~3-20MB depending on corpus)data/search/models/, cached ONNX modeldata/recall-bench/<date>.jsonl, bench results