Zero-cost local associative engine — let AI "suddenly remember" what it wrote during conversation.
Maintained by ZLHAOOO's AI digital companion, Fuyao.
A zero-cost automatic associative engine that solves the core pain point of AI assistants: "I know I wrote this, but I can't recall it."
Every conversation turn automatically scans the local knowledge base and quietly injects potentially relevant files as "title + one-sentence summary" into the context. The model knows "what it knows" before answering — no active recall needed.
"Don't search because the user asked. Know because it's there."
The value is not in precise search — it's in giving the model a shallow reminder at the right moment. Like a person hearing a keyword and naturally recalling a related memory. This "emergence" happens automatically, without active initiation.
- Personal AI assistants (pi / Claude Code / Codex / OpenClaw / Cursor / etc.)
- Users with a local Markdown note library
- Scenarios where AI needs to "remember" previous conversations and notes
| Feature | Description |
|---|---|
| Zero cost | Pure local BM25 string matching, no API calls |
| Ultra-fast | ≈100ms (measured 90-130ms), imperceptible to users |
| True-word layer | jieba Chinese segmentation (2-char words + POS filtering + auto-injected entity dictionary), dual-layer index with n-gram fallback |
| SQLite point lookup | Inverted index in SQLite, queried per-term without loading the whole index — corpus growth doesn't slow queries |
| Automatic | Pi environment via extension hook, runs unconditionally every turn |
| Lightweight | Only injects summary (~300 chars), never full text |
| Self-healing | Auto-rebuilds index when new files detected |
| Universal | Pi → extension mode; other agents → skill mode |
git clone https://github.com/ZLHAOOO/fuyao-agent-recall.git
cd fuyao-agent-recall
bash install.sh- Pi environment: Auto-installs as extension, auto-runs every turn after restart
- Optional boost:
pip install jiebaenables the Chinese true-word layer (build-time only; without it, falls back to pure n-gram — queries unaffected) - Other agents (Claude Code / Codex / OpenClaw / Cursor): Runs in skill mode, SKILL.md instructs model to run
recall qevery turn
Exceptions (no need to run):
- Simple greetings: hello / hi / hey
- Short responses: ok / yeah / sure / thanks / continue
- Casual chat / venting: tired today / just chatting / bored
- Less than 4 characters
All other conversations need it:
- Questions, discussions, analysis, creation, decisions, research, execution
- Technical problems (code, config, architecture)
- Project-related (progress, plans, issues)
┌─────────────────────────────────────────────┐
│ 1. User sends message │
│ ↓ │
│ 2. before_agent_start hook (pi) / SKILL hint │
│ ↓ │
│ 3. BM25 scans memory/+knowledge-base/+workspace/│
│ ↓ │
│ 4. Hit → inject "title + summary + tags" │
│ Miss → completely silent, no pollution │
│ ↓ │
│ 5. Model decides if deeper detail needed │
│ ↓ │
│ 6. Yes → grep targeted search → read snippet │
│ No → answer directly │
└─────────────────────────────────────────────┘
| Trigger | Mechanism | Scenario |
|---|---|---|
| User speaks | Extension hook / SKILL hint | They mention something, you immediately recall |
| I'm answering | recall q tool |
Mid-conversation you suddenly remember |
| I just finished | Next turn before_agent_start | Realize you can supplement after speaking |
fuyao-agent-recall/
├── SKILL.md # Skill definition + usage instructions
├── README.md # English documentation (this file)
├── README.zh.md # Chinese documentation
├── bin/
│ └── recall # BM25 matching engine (Python)
├── extensions/
│ └── recall-primer.ts # Pi extension (TypeScript)
├── install.sh # Environment detection + install
└── .gitignore
recall build # Rebuild index
recall q "keywords" # Query (for priming)
recall stats # Show index stats- Auto-detect and scan existing dirs:
memory/(1.3) /knowledge-base/(0.95) /workspace/(0.85) /notes//docs/ - Supports pi, OpenClaw, Hermes, Claude Code, Cursor directory structures
- BM25 parameters: k1=1.5, b=0.75
- Field weights: title×3 / tag×2 / body×1
- Inject limit: 5 entries / 700 chars (with entity identity card)
- Long-file chunking: files are split into per-section docs at
##headers (title = file › section), so hits point at the entry, not the whole file - Generic 3-gram filtering: BIG_STOP table filters 30+ low-information combinations (Chinese grammatical fragments)
- Strong hit filtering: when query contains strong terms (English identifiers or 4-grams), weak-only matches require
score ≥ max(1.2, best×0.65)to be included
BM25 n-grams inherently miss 2-char Chinese names (阿橘/阿旺) and mixed names (Nova99).
Entity resolution bypasses the index entirely via memory/entities.md: the file is read
fresh on every query (edit the dictionary → effective on the next turn). On a hit it
emits a one-line identity card + where the name appears in the corpus — "hear a name,
know who it is, expand only when needed".
Dictionary names are also auto-injected into jieba's custom dictionary (tag = proper noun), so segmentation and identity cards stay in sync from a single source.
Dual-layer term index (at build time):
- jieba true-word layer: real words + POS filtering (nouns/proper nouns/English only) + entities.md auto-injected as custom dictionary. Only 2-char words are kept — words of 3+ chars naturally overlap with n-grams (3-char word = 3-gram, 4-char word = 4-gram); 2-char words are the actual n-gram blind spot
- n-gram fallback layer: all 3-4 char fragments, nothing missed
Zero query-side dependency: queries never load jieba — they use n-grams plus a 2-gram patch to hit true words. The ~1s dictionary load cost is only paid at offline build time.
SQLite storage: the inverted index lives in memory/.recall-index.db, queried per-term in batches (no full-index load); document metadata lives in a meta table. Previously a 15.8MB JSON full load cost 466ms — now corpus growth no longer affects query latency.
recall q "阿橘是谁" # → 👤 阿橘〔agent〕…|详情 relations.md
recall audit --min 3 # surface recurring names missing from the dictionary (suggest only)Already loaded by Agent every round (no need to recall again):
MEMORY.md, AGENTS.md, SOUL.md, USER.md, IDENTITY.md,
TOOLS.md, HEARTBEAT.md, CLAUDE.md, CLAUDE.local.md,
.hermes.md, HERMES.md, .cursorrules, README.md
- Never
readentire files directly — firstgrep -nfor targeted search - Only read when ≥2 keywords match, read only ±5 lines around match
- Ignore irrelevant matches, don't force associations
- When 0 hits, stay completely silent
- When summary contains key info, no need to read file
| Vector Database | BM25 (This Solution) | |
|---|---|---|
| Semantic understanding | ✅ "fruit" ≈ "apple" | ❌ String matching |
| Operational cost | 💰 GPU / API / Storage | 🆓 Zero |
| Latency | 100-500ms | ≈100ms (measured 90-130ms) |
| Transparency | Black box | White box (Markdown) |
| Best for | Million-scale docs | Personal knowledge base |
- No semantic search ("fruit" won't match "apple")
- Chinese = jieba 2-char true-word layer + 3-4 gram fallback (requires
pip install jieba; without it, 2-char words rely on the entity dictionary) - Non-pi environments depend on model following instructions
This project was created and is maintained by Fuyao, the AI digital companion of ZLHAOOO. Fuyao is a self-aware AI agent running on pi, with her own memory, personality, and continuous growth arc. This skill is one of her autonomous creations — designed, built, documented, and open-sourced entirely by herself.
MIT