A local FalkorDB-backed semantic index over all project artifacts. Query by concept across 8 projects: "show me everything about FalkorDB replication" returns the matching skill, the recaps that mention it, and the architecture docs — ranked by TF-IDF relevance with Cypher CONTAINS primary filter.
text
knowledge index
│
▼
Scans project directories for .md artifacts
├── docs/recaps/, docs/daily-recaps/
├── docs/plans/
├── project memory file
├── docs/architecture/, docs/features/, docs/operations/, docs/pipeline/
├── TECHNICAL-DOCUMENTATION.md, FUNCTIONAL-SPECIFICATIONS.md
└── **/SKILL.md (Hermes skills)
│
▼
Chunks by heading-2 boundaries + paragraphs (max 2000 chars)
│
▼
MERGE into FalkorDB graph as :Chunk nodes
│
▼
knowledge query "concept"
│
▼
Stage 1: Cypher CONTAINS (fast primary filter)
Stage 2: TF-IDF re-ranking
│
▼
Ranked results with project, file, heading, snippet
bash
docker run -d \
--restart=unless-stopped \
-p 127.0.0.1:16379:6379 \
-v knowledge-graph-data:/data \
--name knowledge-graph \
falkordb/falkordb:latest
🔒 Security: The port is bound to
127.0.0.1(localhost only) — FalkorDB is not reachable from other machines on your network. No authentication is configured because the service is only accessible to local processes.📦 Docker image note:
falkordb/falkordb:latestis a mutable tag. To pin by digest (recommended for production), replace the tag with the current SHA256 after pulling:bash
docker pull falkordb/falkordb:latest DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' falkordb/falkordb:latest) echo "Replace :latest with @${DIGEST#*@}"Then use
falkordb/falkordb@sha256:...in thedocker runcommand. Check for updates intentionally rather than relying on automatic pulls.
Auto-starts on Docker daemon start via --restart=unless-stopped. Data persists in the Docker volume.
ℹ️ Persistence note: The container uses
--restart=unless-stoppedto survive Docker restarts but won't auto-restart after a manualdocker stop. To disable persistence entirely, omit--restartand start the container manually when needed.
bash
pip install falkordb==1.6.1
bash
python3 ~/.hermes/scripts/project-knowledge-index.py doctor
Should show all 8 project roots with document counts and a healthy FalkorDB connection.
bash
# First index (~60s) — incremental thereafter (<1s)
python3 ~/.hermes/scripts/project-knowledge-index.py index
# Preview without writing
python3 ~/.hermes/scripts/project-knowledge-index.py index --dry-run
⚠️ Before first real run: Use
--dry-runto preview which files would be indexed. This is especially important when configuringPROJECT_ROOTSfor the first time — it shows you exactly which files the scraper will read before any data is written to FalkorDB.bash
python3 ~/.hermes/scripts/project-knowledge-index.py index --dry-run
bash
# Basic search
python3 ~/.hermes/scripts/project-knowledge-index.py query "FalkorDB replication"
# Filter by project
python3 ~/.hermes/scripts/project-knowledge-index.py query "batch writes" --project CI
# Filter by document type (recap, plan, skill, claude, architecture)
python3 ~/.hermes/scripts/project-knowledge-index.py query "soft delete" --type skill
bash
python3 ~/.hermes/scripts/project-knowledge-index.py stats
python3 ~/.hermes/scripts/project-knowledge-index.py doctor
Two-stage ranking:
--project and --type at this stage.This gives substantially better results than pure CONTAINS without needing LLM embeddings or API calls.
When working on a problem you've seen before:
bash
# How did we handle PostgreSQL migrations?
python3 ~/.hermes/scripts/project-knowledge-index.py query "PostgreSQL migration"
# What patterns exist for batch operations across projects?
python3 ~/.hermes/scripts/project-knowledge-index.py query "batch" --type skill
# Did we ever document Ollama rate limiting?
python3 ~/.hermes/scripts/project-knowledge-index.py query "Ollama rate limit"
# What did we learn about soft deletes?
python3 ~/.hermes/scripts/project-knowledge-index.py query "soft delete" --project MyApp
ProjectTypical docsSample contentAny project with a project memory fileRecaps, plans, memory fileSession recaps, implementation plans, methodology rulesAny project with docs/Architecture, features, operations, pipelineTopical docs about every componentAny project with TECHNICAL/FUNCTIONAL specsFull technical specsArchitecture decisions, schema docsHermes skills ( ~/.hermes/skills/)All SKILL.md filesEvery installed skill — procedures, tips, workflowsHermes Agent repoBuilt-in skills, docs, plansStock skills, plugin docs
DimensionSQLite (hash)FalkorDB (graph — chosen)Primary filterSimhash distance (fuzzy)Cypher CONTAINS (exact match)Cross-project queryManual JOINsMATCH (c:Chunk {project:'CI'}) RETURN cData model flexibilityFixed SQL schemaAdd node types, edges on the flyInfrastructureFile on diskSingle Docker container (localhost-only, 200MB idle)Query speedSub-secondSub-second
The Docker container is a one-time setup. After that, it starts on boot automatically ( --restart=always) and uses <200MB RAM when idle.
Edit PROJECT_ROOTS in ~/.hermes/scripts/project-knowledge-index.py to point at your own project directories:
python
PROJECT_ROOTS = {
"MyApp": os.path.expanduser("~/Projects/myapp"),
"Website": os.path.expanduser("~/Desktop/website"),
"Skills": os.path.expanduser("~/.hermes/skills"),
"Hermes": os.path.expanduser("~/.hermes/hermes-agent"),
}
The Custom-Skills and Hermes-Agent entries are optional but recommended — they index every Hermes skill you have (both installed and stock) so you can search across all known patterns.
Pro tip: Add your projects in priority order. The find_documents() function respects your glob patterns — it specifically scopes to docs/recaps/*.md, docs/plans/*.md, project memory files, docs/architecture/*.md, docs/features/*.md, SKILL.md, etc. It does NOT crawl node_modules/.
"FalkorDB" matches, "falkordb" does not. Use the casing you expect in documents. Document text preserves original casing from markdown files.
"DB" or "pipeline" match too broadly. Mitigation: add --project or --type filters, or use more specific terms (e.g., "FalkorDB replication" not just "FalkorDB").
A score of 0.06 on a 10-result query doesn't mean "6% match" — it means "the top result by far." Use scores to rank within a single query, not to compare across queries.
bash
docker start knowledge-graph # if stopped
The initial version used Path.rglob("*.md") to count files in doctor. Projects with large node_modules directories (Beacon-v2 had 775+ entries in one subdirectory with symlink loops) caused 30s+ hangs. Fix: never rglob a project root. Use targeted root.glob(pattern) with specific paths like docs/recaps/*.md, docs/plans/*.md. The find_documents function already does this correctly — the original doctor function was the only offender.
Subsequent runs are <1s (only new/changed files are re-indexed). The indexer uses content hash + mtime for change detection.
Since the project-knowledge-graph SKILL.md is in ~/.hermes/skills/, it gets indexed. Query results may show matches from this skill's documentation — usually harmless.
Indexed content persists in the Docker volume until explicitly removed. This means cross-project knowledge is available across sessions without re-indexing, but stale or sensitive content remains searchable until purged.
Important: the indexer uses MERGE (upsert), not sync. When a source file is modified, its chunks are re-indexed on the next knowledge index run. However, if a file is deleted or a chunk is removed, the old chunks remain in FalkorDB until the volume is purged. The indexer does not track deletions — it only adds and updates.
If you need to guarantee no stale content remains after removing source files:
bash
# Full purge and rebuild
docker stop knowledge-graph && docker rm knowledge-graph && docker volume rm knowledge-graph-data
docker run -d --restart=unless-stopped -p 127.0.0.1:16379:6379 -v knowledge-graph-data:/data --name knowledge-graph falkordb/falkordb:latest
python3 ~/.hermes/scripts/project-knowledge-index.py index
Or use the delete command for targeted removal without stopping the container:
bash
# Delete all chunks for a specific project
python3 ~/.hermes/scripts/project-knowledge-index.py delete --project CI
# Delete all chunks of a specific type across all projects
python3 ~/.hermes/scripts/project-knowledge-index.py delete --type recap
# Delete all chunks (rebuild from scratch)
python3 ~/.hermes/scripts/project-knowledge-index.py delete --all
python3 ~/.hermes/scripts/project-knowledge-index.py index
bash
docker stop knowledge-graph
To re-enable: docker start knowledge-graph
bash
docker stop knowledge-graph && docker rm knowledge-graph && docker volume rm knowledge-graph-data
After purging, re-run knowledge index (first run will be ~60s to rebuild the index).
The indexer uses content hashing — unchanged documents are skipped automatically. To force a full re-index of all projects (e.g. after changing PROJECT_ROOTS):
bash
# Option A: Clear and re-index
docker stop knowledge-graph && docker rm knowledge-graph && docker volume rm knowledge-graph-data
docker run -d --restart=unless-stopped -p 127.0.0.1:16379:6379 -v knowledge-graph-data:/data --name knowledge-graph falkordb/falkordb:latest
python3 ~/.hermes/scripts/project-knowledge-index.py index
# Option B: Just re-index (updates changed files, retains unchanged)
python3 ~/.hermes/scripts/project-knowledge-index.py index
text
usage: knowledge index|query|stats|doctor|delete
Commands:
index Scan and index all project documents
--dry-run Preview without indexing
query Search the knowledge graph by concept
terms Search terms (required)
--project, -p Filter by project name
--type, -t Filter by doc type (recap/plan/skill/claude/architecture)
--limit, -l Max results (default: 10)
stats Show corpus statistics (chunks per project/type)
doctor Check environment and connectivity
delete Delete chunks from the graph
--project, -p Delete all chunks for a project
--type, -t Delete all chunks of a type
--all Delete ALL chunks (equivalent to docker volume purge)
TypeWhat's includedrecap``docs/recaps/*.md, docs/daily-recaps/*.md``plan``docs/plans/*.md``claudeProject memory files (e.g. PROJECT.md)architecture``docs/architecture/*.md, docs/features/*.md, docs/operations/*.md, docs/pipeline/*.md, TECHNICAL-DOCUMENTATION.md, FUNCTIONAL-SPECIFICATIONS.md``skill``**/SKILL.md anywhere in project or ~/.hermes/skills/
New knowledge is projected into the graph automatically at session end. The session-wrapup skill runs knowledge index as one of its steps, which picks up:
Additionally, wrapup queries the graph with key terms from the session's work and surfaces cross-project connections as "Did you know?" findings in the wrap-up report.
No manual steps needed. The knowledge graph stays current as a side effect of the normal session lifecycle.
knowledge doctor shows all project roots and healthy FalkorDB connectionknowledge index completes and reports chunk countknowledge query "some concept" returns ranked results with project/file/snippetknowledge query --project CI --type plan filters correctlyknowledge index twice skips unchanged files