JFox
A local-first Zettelkasten knowledge management CLI. Bidirectional links, semantic search, knowledge graphs — all offline, all on CPU.
JFox (J + Fox / "box") is a command-line tool that helps you build a personal knowledge base using the Zettelkasten method. Notes live as plain Markdown files on your disk, connected by [[wiki links]] and indexed for instant semantic search.
Table of Contents
Features
- Three note types — Fleeting (quick capture), Literature (reading notes), Permanent (refined knowledge)
- Bidirectional links — Write
[[Note Title]]to connect notes; backlinks are auto-generated - Hybrid search — BM25 keyword search + semantic vector search, fused with Reciprocal Rank Fusion
- Knowledge graph — NetworkX-powered link analysis: clusters, orphans, hubs, shortest paths
- File watcher — Real-time index updates when you edit notes with any editor
- Multi knowledge bases — Manage separate KBs for work, personal, research, etc.
Architecture
Three-Layer Design
graph TB
subgraph CLI ["CLI Layer"]
cmd["jfox commands<br/>(Typer)"]
end
subgraph Storage ["Storage Layer"]
note[note.py]
models[models.py]
md[("Markdown Files<br/>YAML Frontmatter")]
end
subgraph Index ["Index Layer"]
se[search_engine.py<br/>HybridSearchEngine]
vs[vector_store.py<br/>ChromaDB]
bm[bm25_index.py<br/>BM25Okapi]
emb[embedding_backend.py<br/>all-MiniLM-L6-v2]
daemon["daemon/<br/>HTTP Server"]
end
subgraph Analysis ["Analysis Layer"]
gph["graph.py<br/>NetworkX DiGraph"]
end
subgraph Watcher ["File Watcher"]
idx[indexer.py<br/>watchdog]
end
cmd --> note & se & gph
note --> models --> md
se --> vs & bm
vs --> emb
emb -.->|"preferred"| daemon
idx --> vs
Module Map
| Module | Role |
|---|---|
cli.py |
All CLI commands (~2500 lines). Each command delegates to a _xxx_impl() helper |
config.py |
Per-KB config (ZKConfig) + use_kb() context manager for KB switching |
global_config.py |
Multi-KB registry in ~/.zk_config.json |
kb_manager.py |
KB lifecycle: create, rename, remove, switch |
note.py |
CRUD on Markdown files with dual-index updates |
models.py |
Note dataclass with YAML frontmatter serialization |
search_engine.py |
HybridSearchEngine — dispatches to semantic/keyword/hybrid with RRF fusion |
vector_store.py |
ChromaDB wrapper with cosine similarity search |
bm25_index.py |
BM25 keyword index with Chinese/English tokenizer |
embedding_backend.py |
Lazy-loaded SentenceTransformer (all-MiniLM-L6-v2, 384-dim vectors) |
daemon/ |
Embedding HTTP 守护进程,常驻模型避免重复加载 |
graph.py |
NetworkX DiGraph built from links + wiki links; BFS, clusters, hubs |
indexer.py |
File watcher (watchdog) with debounce for incremental ChromaDB updates |
formatters.py |
Output in JSON, CSV, YAML, Table, Paths, Tree formats |
performance.py |
Batch processing, model caching, bulk import pipeline |
Data Flows
Note Creation
When you run jfox add, the system parses wiki links, creates the Markdown file, updates both indexes, and propagates backlinks:
sequenceDiagram
participant U as User
participant CLI as cli.py
participant NM as note.py
participant MD as Filesystem
participant VS as VectorStore
participant BM as BM25Index
participant T as Target Note
U->>CLI: jfox add "content with [[Link]]"
CLI->>CLI: extract_wiki_links() → ["Link"]
CLI->>CLI: find_note_id_by_title_or_id()
Note over CLI: Match: exact ID → exact title → substring
CLI->>NM: create_note(content, links=[id1])
NM->>NM: generate_id() → timestamp + random
NM->>MD: write Markdown + YAML frontmatter
NM->>VS: add_note() → embed + store in ChromaDB
NM->>BM: add_document() → tokenize + update index
CLI->>T: load target → append backlink → save
Index Rebuild
jfox index rebuild reconstructs both the vector index and the keyword index from all Markdown files on disk:
sequenceDiagram
participant U as User
participant CLI as cli.py
participant IDX as Indexer
participant VS as VectorStore
participant BM as BM25Index
participant FS as Filesystem
U->>CLI: jfox index rebuild
CLI->>VS: clear() — wipe ChromaDB collection
CLI->>FS: rglob("*.md") — scan all notes
loop Each note file
FS-->>IDX: parse Markdown + frontmatter
IDX->>VS: add_or_update_note()
Note over VS: embed → store in ChromaDB
end
CLI->>FS: list all notes
CLI->>BM: rebuild_from_notes()
Note over BM: tokenize all → rebuild BM25Okapi → persist
Hybrid Search (BM25 + Semantic → RRF)
jfox search runs two independent search paths in parallel and fuses results using Reciprocal Rank Fusion:
sequenceDiagram
participant U as User
participant SE as HybridSearchEngine
participant VS as VectorStore
participant BM as BM25Index
participant EMB as EmbeddingBackend
U->>SE: search("knowledge management", mode=hybrid)
par Semantic Path
SE->>EMB: encode(query) → 384-dim vector
EMB-->>VS: cosine similarity search
VS-->>SE: ranked results with scores
and Keyword Path
SE->>BM: tokenize(query) → BM25 scoring
BM-->>SE: ranked results with scores
end
Note over SE: Graceful fallback if one path fails
SE->>SE: RRF Fusion: score = Σ 1/(k + rank), k=60
SE-->>U: merged, re-ranked results
Query with Graph Traversal
jfox query combines hybrid search with knowledge graph BFS to find semantically related notes and their neighbors:
sequenceDiagram
participant U as User
participant CLI as cli.py
participant SE as SearchEngine
participant KG as KnowledgeGraph
participant NX as NetworkX
U->>CLI: jfox query "Luhmann's methodology" --depth 2
CLI->>SE: hybrid search → top results
SE-->>CLI: ranked search results
CLI->>KG: build() — 3-pass graph construction
Note over KG: Pass 1: nodes from files<br/>Pass 2: edges from frontmatter links<br/>Pass 3: edges from [[wiki links]]
loop For each search result
CLI->>KG: get_related(note_id, depth=2)
KG->>NX: BFS traversal (predecessors + successors)
NX-->>KG: neighbors grouped by depth
end
CLI-->>U: results enriched with graph context
Quick Start
Install
# Recommended
uv tool install "git+https://github.com/zhuxixi/jfox.git"
# Or with pip
pip install -e ".[dev]"
See Installation Guide for details, Windows PATH setup, and uninstall instructions.
Create Your First Note
jfox init
jfox add "The Zettelkasten method uses atomic notes connected by links" \
--title "Zettelkasten Introduction" --type permanent
Add Links
jfox add "[[Zettelkasten Introduction]] was invented by Niklas Luhmann" \
--title "Luhmann and the Card Box" --type permanent
The [[Zettelkasten Introduction]] syntax automatically creates a bidirectional link. Backlinks are propagated to the target note.
Search
# Semantic + keyword hybrid search
jfox search "knowledge management method"
# Hybrid search + graph traversal
jfox query "Luhmann's methodology" --depth 2
Command Reference
Knowledge Base
| Command | Description |
|---|---|
jfox init |
Initialize a knowledge base |
jfox init --name work --desc "Work notes" |
Initialize a named KB |
jfox kb list |
List all knowledge bases |
jfox kb use work |
Switch default KB |
jfox kb info work |
Show KB details and stats |
jfox kb rename old new |
Rename a KB |
jfox kb remove name --force |
Delete a KB and its data |
Notes
| Command | Description |
|---|---|
jfox add "content" --title "Title" --type permanent |
Create a note |
jfox add --content-file note.txt --title "Title" |
Create from file content |
jfox list |
List all notes |
jfox list --type permanent --limit 20 |
Filter by type |
jfox status |
Show knowledge base status |
jfox edit NOTE_ID |
Edit note in $EDITOR |
jfox delete NOTE_ID --force |
Delete a note |
jfox daily |
Show today's notes |
jfox daily --date 2026-03-20 |
Show notes for a date |
jfox inbox |
Show fleeting notes |
jfox suggest-links "content" |
Suggest notes to link from content |
jfox bulk-import notes.json |
Bulk import from JSON (optimized) |
jfox ingest-log |
Import git commit history as notes |
jfox show NOTE_ID |
View full note content in terminal |
Search & Analysis
| Command | Description |
|---|---|
jfox search "query" |
Hybrid search (default) |
jfox search "query" --mode semantic |
Semantic search only |
jfox search "query" --mode keyword |
BM25 keyword search only |
jfox query "concept" --depth 2 |
Search + graph traversal |
jfox refs |
Show link statistics for all notes |
jfox refs --search "keyword" |
Filter refs by title |
jfox refs --note NOTE_ID |
Show links for a specific note |
jfox graph --stats |
Graph statistics |
jfox graph --orphans |
Find isolated notes |
jfox graph --note NOTE_ID --depth 2 |
Subgraph around a note |
Index Management
| Command | Description |
|---|---|
jfox index status |
Show index health |
jfox index rebuild |
Rebuild vector + BM25 indexes |
jfox index verify |
Cross-check files vs indexed entries |
Templates
| Command | Description |
|---|---|
jfox template list |
List built-in and custom templates |
jfox template show quick |
Display template content |
jfox template create my-template |
Create a custom template |
jfox template edit my-template |
Edit in $EDITOR |
jfox template remove my-template |
Delete a custom template |
Performance & Debug
| Command | Description |
|---|---|
jfox perf report |
Show performance metrics |
jfox perf clear-cache |
Clear embedding model cache |
Daemon
| Command | Description |
|---|---|
jfox daemon start |
Start embedding daemon (background process) |
jfox daemon stop |
Stop embedding daemon |
jfox daemon status |
Show daemon PID, port, model info |
Auto-Summary
Auto-summary runs inside the daemon to automatically archive Claude Code sessions into your knowledge base. It scans ~/.claude/projects/ for finished sessions, generates a structured summary via claude -p, and writes it as a session type note.
A session is considered "finished" when its file has not been modified for idle_threshold minutes (default: 30).
| Command | Description |
|---|---|
jfox auto-summary enable |
Enable auto-summary in daemon |
jfox auto-summary disable |
Disable auto-summary |
jfox auto-summary status |
Show config and ledger statistics |
jfox auto-summary scan |
List sessions that would be processed |
jfox auto-summary run |
Manually trigger a summary round |
jfox auto-summary run --dry-run |
Preview without writing |
Key options:
--interval— Scan interval in minutes (default: 30)--idle-threshold— Minutes of inactivity to consider a session finished (default: 30)--kb— Target knowledge base for saved notes
How it works:
- Uses
claude -p(non-interactive mode) to generate summaries from stdin/stdout - Runs with
--permission-mode bypassPermissionsso the daemon never blocks on permission prompts - Tracks processed sessions in
~/.zk_auto_summary_state.jsonto avoid duplicates; transient failures are retried up to 3 times before giving up - A session is eligible only after its file has been idle for
idle_thresholdminutes (no new content)
Privacy note: Auto-summary sends session text to Anthropic API via
claude -pto generate summaries. Only session content is transmitted.
Self-Update
| Command | Description |
|---|---|
jfox update |
Upgrade jfox to the latest version (auto-detects pip/pipx/uv) |
jfox update --json |
JSON output with before/after version info |
Global Options
| Option | Description |
|---|---|
--kb NAME |
Target a specific knowledge base |
--format json|table|csv|yaml|paths|tree |
Output format |
--json |
Shortcut for --format json |
--version |
Show version |
Agent Plugins
JFox 提供主流 AI Agent 的插件/技能集成:
Claude Code
- 插件目录:
packages/cc-plugin/ - 安装(marketplace 上架后):
/plugin marketplace add zhuxixi/jfox - 包含 5 个 skill:manage、search、ingest、organize、session-summary
Kimi Code CLI
- 插件目录:
packages/kimi-plugin/ - 安装:在 Kimi Code CLI TUI 中执行
/plugins install github:zhuxixi/jfox?path=packages/kimi-plugin,或使用本地 zip - 包含 6 个 skill:
using-jfox(会话启动自动加载)、jfox-manage、jfox-search、jfox-ingest、jfox-organize、jfox-session-summary - 详见:
packages/kimi-plugin/README.md
其他 Agent
skills-recommend/pi/提供 pi coding agent 的技能包skills-recommend/kimi-cli/保留旧版 Kimi CLI 手动复制 skill(已弃用)
Note Format
Directory Structure
~/.zettelkasten/
├── default/ # Default knowledge base
│ ├── notes/
│ │ ├── fleeting/ # Quick captures
│ │ ├── literature/ # Reading notes
│ │ └── permanent/ # Refined knowledge
│ └── .zk/
│ ├── chroma_db/ # Vector index
│ ├── bm25_index.pkl # Keyword index
│ ├── templates/ # Jinja2 templates
│ └── config.yaml # KB config
├── work/ # Named KB example
│ ├── notes/
│ └── .zk/
└── ~/.zk_config.json # Global KB registry
File Format
Each note is a Markdown file with YAML frontmatter:
---
id: '20260321011528'
title: Machine Learning Overview
type: permanent
created: '2026-03-21T01:15:28'
updated: '2026-03-21T01:15:28'
tags:
- ml
- ai
links:
- 20260321011546
backlinks:
- 20260321011550
---
# Machine Learning Overview
[[Deep Learning]] is a subfield of machine learning...
Note Types
| Type | Purpose | Filename |
|---|---|---|
fleeting |
Quick ideas, temporary captures | YYYYMMDD-HHMMSSNNNN.md |
literature |
Reading notes, paper summaries | YYYYMMDDHHMMSSNNNN-slug.md |
permanent |
Refined, lasting knowledge | YYYYMMDDHHMMSSNNNN-slug.md |
Link Resolution
[[Link Text]] matches notes by priority:
- Exact ID — if text matches a note ID
- Exact title — case-insensitive title match
- Substring — title contains the link text
Contributing
git clone https://github.com/zhuxixi/jfox.git
cd jfox
uv sync --extra dev
uv run pytest tests/ -v
See Troubleshooting for common issues.
License
Acknowledgments
- sentence-transformers — text embeddings
- ChromaDB — vector database
- NetworkX — graph algorithms
- Typer — CLI framework
- Rich — terminal formatting
Release files for jfox-cli 1.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| jfox_cli-1.3.0.tar.gz | 867.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| jfox_cli-1.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 1.0 MB
Release files / jfox_cli-1.3.0.tar.gz
| Download URL | jfox_cli-1.3.0.tar.gz |
|---|---|
| Size | 867.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b6d92af4f391bddec7019ae9551c21547e6eb6a933b79811ed02fdad405b3f5a
|
|
BLAKE2b-256 checksum How to use checksums |
bec49d58d7268e117b3010780528c24d8082d62e85adb25cb23c9b1e0b93ec93
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / jfox_cli-1.3.0-py3-none-any.whl
| Download URL | jfox_cli-1.3.0-py3-none-any.whl |
|---|---|
| Size | 172.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
000c17929984f3766f98546414b690ef950441c5bca15d56e6f3f55ec46f8b1c
|
|
BLAKE2b-256 checksum How to use checksums |
65d14f102d63dd435580dc3a03462805df1d2d0f4379b75529200639aa40afcb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|