jfox-cli 0.2.2__tar.gz → 0.3.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/CLAUDE.md +4 -2
  2. jfox_cli-0.3.2/PKG-INFO +463 -0
  3. jfox_cli-0.3.2/README.md +424 -0
  4. jfox_cli-0.3.2/docs/installation.md +72 -0
  5. jfox_cli-0.3.2/docs/superpowers/plans/2026-04-14-sync-docs-daemon-show.md +486 -0
  6. jfox_cli-0.3.2/docs/superpowers/specs/2026-04-14-show-command-design.md +44 -0
  7. jfox_cli-0.3.2/docs/troubleshooting.md +43 -0
  8. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/jfox/__init__.py +1 -1
  9. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/jfox/cli.py +124 -0
  10. jfox_cli-0.3.2/jfox/daemon/__init__.py +15 -0
  11. jfox_cli-0.3.2/jfox/daemon/__main__.py +5 -0
  12. jfox_cli-0.3.2/jfox/daemon/client.py +99 -0
  13. jfox_cli-0.3.2/jfox/daemon/process.py +226 -0
  14. jfox_cli-0.3.2/jfox/daemon/server.py +126 -0
  15. jfox_cli-0.3.2/jfox/embedding_backend.py +112 -0
  16. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/pyproject.toml +4 -2
  17. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/skills-recommend/README.md +2 -0
  18. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/skills-recommend/claude-code/jfox-common/SKILL.md +11 -0
  19. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/skills-recommend/claude-code/jfox-ingest/SKILL.md +7 -0
  20. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/skills-recommend/claude-code/jfox-organize/SKILL.md +5 -0
  21. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/skills-recommend/claude-code/jfox-search/SKILL.md +3 -1
  22. jfox_cli-0.3.2/skills-recommend/claude-code/jfox-session-summary/SKILL.md +96 -0
  23. jfox_cli-0.3.2/tests/unit/test_show.py +73 -0
  24. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/uv.lock +34 -1
  25. jfox_cli-0.2.2/PKG-INFO +0 -639
  26. jfox_cli-0.2.2/README.md +0 -602
  27. jfox_cli-0.2.2/jfox/embedding_backend.py +0 -64
  28. jfox_cli-0.2.2/skill/evals/evals.json +0 -185
  29. jfox_cli-0.2.2/skill/knowledge-base-notes/SKILL.md +0 -278
  30. jfox_cli-0.2.2/skill/knowledge-base-workspace/SKILL.md +0 -242
  31. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/.githooks/pre-push +0 -0
  32. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/.github/workflows/integration-test.yml +0 -0
  33. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/.github/workflows/publish.yml +0 -0
  34. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/.gitignore +0 -0
  35. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/.python-version +0 -0
  36. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/AGENTS.md +0 -0
  37. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/CHANGELOG.md +0 -0
  38. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/DEVELOPMENT_PLAN.md +0 -0
  39. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/SESSION.md +0 -0
  40. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/SESSION_SUMMARY.md +0 -0
  41. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/docs/superpowers/plans/2026-04-11-bulk-import-bm25-fix.md +0 -0
  42. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/docs/superpowers/plans/2026-04-11-edit-command.md +0 -0
  43. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/docs/superpowers/plans/2026-04-11-unify-format-option.md +0 -0
  44. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/docs/superpowers/plans/2026-04-12-ci-coverage-optimization.md +0 -0
  45. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/docs/superpowers/plans/2026-04-12-edit-content-file.md +0 -0
  46. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/docs/superpowers/plans/2026-04-12-fix-index-rebuild-clear.md +0 -0
  47. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/docs/superpowers/plans/2026-04-12-fix-index-verify-id-mismatch.md +0 -0
  48. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/docs/superpowers/plans/2026-04-12-fix-jfox-health-skill-kb-param.md +0 -0
  49. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/docs/superpowers/plans/2026-04-12-index-kb-param.md +0 -0
  50. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/docs/superpowers/plans/2026-04-12-lazy-import-perf.md +0 -0
  51. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/docs/superpowers/plans/2026-04-12-skill-redesign.md +0 -0
  52. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/docs/superpowers/specs/2026-04-03-bugfixes-design.md +0 -0
  53. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/docs/superpowers/specs/2026-04-12-skill-redesign-design.md +0 -0
  54. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/docs/superpowers/specs/2026-04-13-pr-auto-code-review-design.md +0 -0
  55. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/jessica-jones-static-cable.md +0 -0
  56. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/jfox/__main__.py +0 -0
  57. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/jfox/bm25_index.py +0 -0
  58. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/jfox/config.py +0 -0
  59. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/jfox/formatters.py +0 -0
  60. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/jfox/git_extractor.py +0 -0
  61. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/jfox/global_config.py +0 -0
  62. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/jfox/graph.py +0 -0
  63. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/jfox/indexer.py +0 -0
  64. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/jfox/kb_manager.py +0 -0
  65. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/jfox/models.py +0 -0
  66. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/jfox/note.py +0 -0
  67. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/jfox/performance.py +0 -0
  68. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/jfox/search_engine.py +0 -0
  69. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/jfox/template.py +0 -0
  70. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/jfox/template_cli.py +0 -0
  71. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/jfox/vector_store.py +0 -0
  72. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/pytest.ini +0 -0
  73. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/run_full_test.ps1 +0 -0
  74. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/COVERAGE_PLAN.md +0 -0
  75. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/MIGRATION.md +0 -0
  76. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/TESTS.md +0 -0
  77. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/conftest.py +0 -0
  78. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/integration/__init__.py +0 -0
  79. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/integration/test_backlinks.py +0 -0
  80. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/performance/__init__.py +0 -0
  81. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/performance/test_performance.py +0 -0
  82. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/test_advanced_features.py +0 -0
  83. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/test_cli_format.py +0 -0
  84. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/test_config_unit.py +0 -0
  85. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/test_core_workflow.py +0 -0
  86. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/test_hybrid_search.py +0 -0
  87. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/test_integration.py +0 -0
  88. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/test_kb_current.py +0 -0
  89. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/test_suggest_links.py +0 -0
  90. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/unit/__init__.py +0 -0
  91. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/unit/test_bm25_batch.py +0 -0
  92. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/unit/test_edit.py +0 -0
  93. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/unit/test_format_unify.py +0 -0
  94. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/unit/test_formatters.py +0 -0
  95. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/unit/test_git_extractor.py +0 -0
  96. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/unit/test_global_config.py +0 -0
  97. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/unit/test_index_kb_param.py +0 -0
  98. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/unit/test_indexer_clear_before_rebuild.py +0 -0
  99. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/unit/test_indexer_verify.py +0 -0
  100. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/unit/test_kb_manager.py +0 -0
  101. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/unit/test_lazy_import.py +0 -0
  102. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/unit/test_logging_config.py +0 -0
  103. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/unit/test_template.py +0 -0
  104. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/unit/test_template_cli.py +0 -0
  105. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/unit/test_vector_store_clear.py +0 -0
  106. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/utils/__init__.py +0 -0
  107. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/utils/assertions.py +0 -0
  108. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/utils/jfox_cli.py +0 -0
  109. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/utils/note_generator.py +0 -0
  110. {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/utils/temp_kb.py +0 -0
@@ -56,7 +56,7 @@ Notes are Markdown files with YAML frontmatter stored under `~/.zettelkasten/<kb
56
56
 
57
57
  | Module | Role |
58
58
  |--------|------|
59
- | `cli.py` | All CLI commands (~1800 lines). Commands follow pattern: `@app.command()` → `_xxx_impl()` helper for reuse |
59
+ | `cli.py` | All CLI commands (~2500 lines). Commands follow pattern: `@app.command()` → `_xxx_impl()` helper for reuse |
60
60
  | `config.py` | `ZKConfig` + `use_kb()` context manager for multi-KB switching |
61
61
  | `global_config.py` | `GlobalConfigManager` managing `~/.zk_config.json` |
62
62
  | `kb_manager.py` | Knowledge base lifecycle (create, rename, remove) |
@@ -66,7 +66,8 @@ Notes are Markdown files with YAML frontmatter stored under `~/.zettelkasten/<kb
66
66
  | `models.py` | `Note` data model with frontmatter serialization |
67
67
  | `search_engine.py` | `HybridSearchEngine` with `SearchMode` enum, RRF fusion |
68
68
  | `bm25_index.py` | BM25 keyword search index |
69
- | `embedding_backend.py` | Sentence-transformers embedding backend |
69
+ | `embedding_backend.py` | Sentence-transformers embedding backend(支持 daemon 代理) |
70
+ | `daemon/` | Embedding 模型 HTTP 守护进程,`jfox daemon start/stop/status` |
70
71
  | `vector_store.py` | ChromaDB vector store for semantic search |
71
72
  | `graph.py` | NetworkX knowledge graph from links/backlinks |
72
73
  | `template.py` / `template_cli.py` | Jinja2 template system for structured note creation |
@@ -97,6 +98,7 @@ Notes are Markdown files with YAML frontmatter stored under `~/.zettelkasten/<kb
97
98
  - **Adding a CLI command**: Add `@app.command()` in `cli.py`, implement `_xxx_impl()` helper, add `--kb` and `--format json` support
98
99
  - **Adding a search mode**: Add to `SearchMode` enum in `search_engine.py`, implement in `HybridSearchEngine.search()`, update CLI `--mode` help text
99
100
  - **Modifying data models**: Update `Note` class in `models.py`, update `to_markdown()`/`from_markdown()`, consider backward compat
101
+ - **Viewing note content**: `jfox show <id_or_title>` 复用 `find_note_id_by_title_or_id` 定位笔记,只读输出完整 Markdown
100
102
 
101
103
  ## Test Infrastructure
102
104
 
@@ -0,0 +1,463 @@
1
+ Metadata-Version: 2.4
2
+ Name: jfox-cli
3
+ Version: 0.3.2
4
+ Summary: JFox - Zettelkasten 知识管理 CLI 工具
5
+ Project-URL: Homepage, https://github.com/zhuxixi/jfox
6
+ Project-URL: Repository, https://github.com/zhuxixi/jfox
7
+ Author-email: User <user@example.com>
8
+ License: MIT
9
+ Keywords: cli,jfox,knowledge-management,note-taking,zettelkasten
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Requires-Python: >=3.10
19
+ Requires-Dist: chromadb>=0.5.0
20
+ Requires-Dist: fastapi>=0.110.0
21
+ Requires-Dist: jinja2>=3.0
22
+ Requires-Dist: networkx>=3.0
23
+ Requires-Dist: pydantic>=2.0
24
+ Requires-Dist: pyyaml>=6.0
25
+ Requires-Dist: rank-bm25>=0.2.2
26
+ Requires-Dist: rich>=13.0.0
27
+ Requires-Dist: sentence-transformers>=3.0
28
+ Requires-Dist: typer>=0.12.0
29
+ Requires-Dist: uvicorn[standard]>=0.27.0
30
+ Requires-Dist: watchdog>=3.0
31
+ Provides-Extra: dev
32
+ Requires-Dist: black>=23.0; extra == 'dev'
33
+ Requires-Dist: pytest-cov>=4.0; extra == 'dev'
34
+ Requires-Dist: pytest-timeout>=2.0; extra == 'dev'
35
+ Requires-Dist: pytest-xdist>=3.0; extra == 'dev'
36
+ Requires-Dist: pytest>=7.0; extra == 'dev'
37
+ Requires-Dist: ruff>=0.1.0; extra == 'dev'
38
+ Description-Content-Type: text/markdown
39
+
40
+ # JFox
41
+
42
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
43
+ [![Python](https://img.shields.io/badge/python-3.10+-blue.svg)](pyproject.toml)
44
+ [![Platform](https://img.shields.io/badge/platform-Windows%20%7C%20macOS%20%7C%20Linux-lightgrey.svg)](#)
45
+
46
+ > A local-first Zettelkasten knowledge management CLI.
47
+ > Bidirectional links, semantic search, knowledge graphs — all offline, all on CPU.
48
+
49
+ **JFox** (**J** + **Fox** / "box") is a command-line tool that helps you build a personal knowledge base using the [Zettelkasten method](https://en.wikipedia.org/wiki/Zettelkasten). Notes live as plain Markdown files on your disk, connected by `[[wiki links]]` and indexed for instant semantic search.
50
+
51
+ ---
52
+
53
+ ## Table of Contents
54
+
55
+ - [Features](#features)
56
+ - [Architecture](#architecture)
57
+ - [Data Flows](#data-flows)
58
+ - [Quick Start](#quick-start)
59
+ - [Command Reference](#command-reference)
60
+ - [Note Format](#note-format)
61
+ - [Contributing](#contributing)
62
+ - [License](#license)
63
+
64
+ ---
65
+
66
+ ## Features
67
+
68
+ - **Three note types** — Fleeting (quick capture), Literature (reading notes), Permanent (refined knowledge)
69
+ - **Bidirectional links** — Write `[[Note Title]]` to connect notes; backlinks are auto-generated
70
+ - **Hybrid search** — BM25 keyword search + semantic vector search, fused with Reciprocal Rank Fusion
71
+ - **Knowledge graph** — NetworkX-powered link analysis: clusters, orphans, hubs, shortest paths
72
+ - **File watcher** — Real-time index updates when you edit notes with any editor
73
+ - **Multi knowledge bases** — Manage separate KBs for work, personal, research, etc.
74
+
75
+ ---
76
+
77
+ ## Architecture
78
+
79
+ ### Three-Layer Design
80
+
81
+ ```mermaid
82
+ graph TB
83
+ subgraph CLI ["CLI Layer"]
84
+ cmd["jfox commands<br/>(Typer)"]
85
+ end
86
+ subgraph Storage ["Storage Layer"]
87
+ note[note.py]
88
+ models[models.py]
89
+ md[("Markdown Files<br/>YAML Frontmatter")]
90
+ end
91
+ subgraph Index ["Index Layer"]
92
+ se[search_engine.py<br/>HybridSearchEngine]
93
+ vs[vector_store.py<br/>ChromaDB]
94
+ bm[bm25_index.py<br/>BM25Okapi]
95
+ emb[embedding_backend.py<br/>all-MiniLM-L6-v2]
96
+ daemon["daemon/<br/>HTTP Server"]
97
+ end
98
+ subgraph Analysis ["Analysis Layer"]
99
+ gph["graph.py<br/>NetworkX DiGraph"]
100
+ end
101
+ subgraph Watcher ["File Watcher"]
102
+ idx[indexer.py<br/>watchdog]
103
+ end
104
+
105
+ cmd --> note & se & gph
106
+ note --> models --> md
107
+ se --> vs & bm
108
+ vs --> emb
109
+ emb -.->|"preferred"| daemon
110
+ idx --> vs
111
+ ```
112
+
113
+ ### Module Map
114
+
115
+ | Module | Role |
116
+ |--------|------|
117
+ | `cli.py` | All CLI commands (~2500 lines). Each command delegates to a `_xxx_impl()` helper |
118
+ | `config.py` | Per-KB config (`ZKConfig`) + `use_kb()` context manager for KB switching |
119
+ | `global_config.py` | Multi-KB registry in `~/.zk_config.json` |
120
+ | `kb_manager.py` | KB lifecycle: create, rename, remove, switch |
121
+ | `note.py` | CRUD on Markdown files with dual-index updates |
122
+ | `models.py` | `Note` dataclass with YAML frontmatter serialization |
123
+ | `search_engine.py` | `HybridSearchEngine` — dispatches to semantic/keyword/hybrid with RRF fusion |
124
+ | `vector_store.py` | ChromaDB wrapper with cosine similarity search |
125
+ | `bm25_index.py` | BM25 keyword index with Chinese/English tokenizer |
126
+ | `embedding_backend.py` | Lazy-loaded SentenceTransformer (`all-MiniLM-L6-v2`, 384-dim vectors) |
127
+ | `daemon/` | Embedding HTTP 守护进程,常驻模型避免重复加载 |
128
+ | `graph.py` | NetworkX DiGraph built from links + wiki links; BFS, clusters, hubs |
129
+ | `indexer.py` | File watcher (watchdog) with debounce for incremental ChromaDB updates |
130
+ | `formatters.py` | Output in JSON, CSV, YAML, Table, Paths, Tree formats |
131
+ | `performance.py` | Batch processing, model caching, bulk import pipeline |
132
+
133
+ ---
134
+
135
+ ## Data Flows
136
+
137
+ ### Note Creation
138
+
139
+ When you run `jfox add`, the system parses wiki links, creates the Markdown file, updates both indexes, and propagates backlinks:
140
+
141
+ ```mermaid
142
+ sequenceDiagram
143
+ participant U as User
144
+ participant CLI as cli.py
145
+ participant NM as note.py
146
+ participant MD as Filesystem
147
+ participant VS as VectorStore
148
+ participant BM as BM25Index
149
+ participant T as Target Note
150
+
151
+ U->>CLI: jfox add "content with [[Link]]"
152
+ CLI->>CLI: extract_wiki_links() → ["Link"]
153
+ CLI->>CLI: find_note_id_by_title_or_id()
154
+ Note over CLI: Match: exact ID → exact title → substring
155
+ CLI->>NM: create_note(content, links=[id1])
156
+ NM->>NM: generate_id() → timestamp + random
157
+ NM->>MD: write Markdown + YAML frontmatter
158
+ NM->>VS: add_note() → embed + store in ChromaDB
159
+ NM->>BM: add_document() → tokenize + update index
160
+ CLI->>T: load target → append backlink → save
161
+ ```
162
+
163
+ ### Index Rebuild
164
+
165
+ `jfox index rebuild` reconstructs both the vector index and the keyword index from all Markdown files on disk:
166
+
167
+ ```mermaid
168
+ sequenceDiagram
169
+ participant U as User
170
+ participant CLI as cli.py
171
+ participant IDX as Indexer
172
+ participant VS as VectorStore
173
+ participant BM as BM25Index
174
+ participant FS as Filesystem
175
+
176
+ U->>CLI: jfox index rebuild
177
+ CLI->>VS: clear() — wipe ChromaDB collection
178
+ CLI->>FS: rglob("*.md") — scan all notes
179
+ loop Each note file
180
+ FS-->>IDX: parse Markdown + frontmatter
181
+ IDX->>VS: add_or_update_note()
182
+ Note over VS: embed → store in ChromaDB
183
+ end
184
+ CLI->>FS: list all notes
185
+ CLI->>BM: rebuild_from_notes()
186
+ Note over BM: tokenize all → rebuild BM25Okapi → persist
187
+ ```
188
+
189
+ ### Hybrid Search (BM25 + Semantic → RRF)
190
+
191
+ `jfox search` runs two independent search paths in parallel and fuses results using Reciprocal Rank Fusion:
192
+
193
+ ```mermaid
194
+ sequenceDiagram
195
+ participant U as User
196
+ participant SE as HybridSearchEngine
197
+ participant VS as VectorStore
198
+ participant BM as BM25Index
199
+ participant EMB as EmbeddingBackend
200
+
201
+ U->>SE: search("knowledge management", mode=hybrid)
202
+ par Semantic Path
203
+ SE->>EMB: encode(query) → 384-dim vector
204
+ EMB-->>VS: cosine similarity search
205
+ VS-->>SE: ranked results with scores
206
+ and Keyword Path
207
+ SE->>BM: tokenize(query) → BM25 scoring
208
+ BM-->>SE: ranked results with scores
209
+ end
210
+ Note over SE: Graceful fallback if one path fails
211
+ SE->>SE: RRF Fusion: score = Σ 1/(k + rank), k=60
212
+ SE-->>U: merged, re-ranked results
213
+ ```
214
+
215
+ ### Query with Graph Traversal
216
+
217
+ `jfox query` combines hybrid search with knowledge graph BFS to find semantically related notes and their neighbors:
218
+
219
+ ```mermaid
220
+ sequenceDiagram
221
+ participant U as User
222
+ participant CLI as cli.py
223
+ participant SE as SearchEngine
224
+ participant KG as KnowledgeGraph
225
+ participant NX as NetworkX
226
+
227
+ U->>CLI: jfox query "Luhmann's methodology" --depth 2
228
+ CLI->>SE: hybrid search → top results
229
+ SE-->>CLI: ranked search results
230
+ CLI->>KG: build() — 3-pass graph construction
231
+ Note over KG: Pass 1: nodes from files<br/>Pass 2: edges from frontmatter links<br/>Pass 3: edges from [[wiki links]]
232
+ loop For each search result
233
+ CLI->>KG: get_related(note_id, depth=2)
234
+ KG->>NX: BFS traversal (predecessors + successors)
235
+ NX-->>KG: neighbors grouped by depth
236
+ end
237
+ CLI-->>U: results enriched with graph context
238
+ ```
239
+
240
+ ---
241
+
242
+ ## Quick Start
243
+
244
+ ### Install
245
+
246
+ ```bash
247
+ # Recommended
248
+ uv tool install "git+https://github.com/zhuxixi/jfox.git"
249
+
250
+ # Or with pip
251
+ pip install -e ".[dev]"
252
+ ```
253
+
254
+ See [Installation Guide](docs/installation.md) for details, Windows PATH setup, and uninstall instructions.
255
+
256
+ ### Create Your First Note
257
+
258
+ ```bash
259
+ jfox init
260
+ jfox add "The Zettelkasten method uses atomic notes connected by links" \
261
+ --title "Zettelkasten Introduction" --type permanent
262
+ ```
263
+
264
+ ### Add Links
265
+
266
+ ```bash
267
+ jfox add "[[Zettelkasten Introduction]] was invented by Niklas Luhmann" \
268
+ --title "Luhmann and the Card Box" --type permanent
269
+ ```
270
+
271
+ The `[[Zettelkasten Introduction]]` syntax automatically creates a bidirectional link. Backlinks are propagated to the target note.
272
+
273
+ ### Search
274
+
275
+ ```bash
276
+ # Semantic + keyword hybrid search
277
+ jfox search "knowledge management method"
278
+
279
+ # Hybrid search + graph traversal
280
+ jfox query "Luhmann's methodology" --depth 2
281
+ ```
282
+
283
+ ---
284
+
285
+ ## Command Reference
286
+
287
+ ### Knowledge Base
288
+
289
+ | Command | Description |
290
+ |---------|-------------|
291
+ | `jfox init` | Initialize a knowledge base |
292
+ | `jfox init --name work --desc "Work notes"` | Initialize a named KB |
293
+ | `jfox kb list` | List all knowledge bases |
294
+ | `jfox kb use work` | Switch default KB |
295
+ | `jfox kb info work` | Show KB details and stats |
296
+ | `jfox kb rename old new` | Rename a KB |
297
+ | `jfox kb remove name --force` | Delete a KB and its data |
298
+
299
+ ### Notes
300
+
301
+ | Command | Description |
302
+ |---------|-------------|
303
+ | `jfox add "content" --title "Title" --type permanent` | Create a note |
304
+ | `jfox add --content-file note.txt --title "Title"` | Create from file content |
305
+ | `jfox list` | List all notes |
306
+ | `jfox list --type permanent --limit 20` | Filter by type |
307
+ | `jfox status` | Show knowledge base status |
308
+ | `jfox edit NOTE_ID` | Edit note in `$EDITOR` |
309
+ | `jfox delete NOTE_ID --force` | Delete a note |
310
+ | `jfox daily` | Show today's notes |
311
+ | `jfox daily --date 2026-03-20` | Show notes for a date |
312
+ | `jfox inbox` | Show fleeting notes |
313
+ | `jfox suggest-links "content"` | Suggest notes to link from content |
314
+ | `jfox bulk-import notes.json` | Bulk import from JSON (optimized) |
315
+ | `jfox ingest-log` | Import git commit history as notes |
316
+ | `jfox show NOTE_ID` | View full note content in terminal |
317
+
318
+ ### Search & Analysis
319
+
320
+ | Command | Description |
321
+ |---------|-------------|
322
+ | `jfox search "query"` | Hybrid search (default) |
323
+ | `jfox search "query" --mode semantic` | Semantic search only |
324
+ | `jfox search "query" --mode keyword` | BM25 keyword search only |
325
+ | `jfox query "concept" --depth 2` | Search + graph traversal |
326
+ | `jfox refs` | Show link statistics for all notes |
327
+ | `jfox refs --search "keyword"` | Filter refs by title |
328
+ | `jfox refs --note NOTE_ID` | Show links for a specific note |
329
+ | `jfox graph --stats` | Graph statistics |
330
+ | `jfox graph --orphans` | Find isolated notes |
331
+ | `jfox graph --note NOTE_ID --depth 2` | Subgraph around a note |
332
+
333
+ ### Index Management
334
+
335
+ | Command | Description |
336
+ |---------|-------------|
337
+ | `jfox index status` | Show index health |
338
+ | `jfox index rebuild` | Rebuild vector + BM25 indexes |
339
+ | `jfox index verify` | Cross-check files vs indexed entries |
340
+
341
+ ### Templates
342
+
343
+ | Command | Description |
344
+ |---------|-------------|
345
+ | `jfox template list` | List built-in and custom templates |
346
+ | `jfox template show quick` | Display template content |
347
+ | `jfox template create my-template` | Create a custom template |
348
+ | `jfox template edit my-template` | Edit in `$EDITOR` |
349
+ | `jfox template remove my-template` | Delete a custom template |
350
+
351
+ ### Performance & Debug
352
+
353
+ | Command | Description |
354
+ |---------|-------------|
355
+ | `jfox perf report` | Show performance metrics |
356
+ | `jfox perf clear-cache` | Clear embedding model cache |
357
+
358
+ ### Daemon
359
+
360
+ | Command | Description |
361
+ |---------|-------------|
362
+ | `jfox daemon start` | Start embedding daemon (background process) |
363
+ | `jfox daemon stop` | Stop embedding daemon |
364
+ | `jfox daemon status` | Show daemon PID, port, model info |
365
+
366
+ ### Global Options
367
+
368
+ | Option | Description |
369
+ |--------|-------------|
370
+ | `--kb NAME` | Target a specific knowledge base |
371
+ | `--format json\|table\|csv\|yaml\|paths\|tree` | Output format |
372
+ | `--json` | Shortcut for `--format json` |
373
+ | `--version` | Show version |
374
+
375
+ ---
376
+
377
+ ## Note Format
378
+
379
+ ### Directory Structure
380
+
381
+ ```
382
+ ~/.zettelkasten/
383
+ ├── default/ # Default knowledge base
384
+ │ ├── notes/
385
+ │ │ ├── fleeting/ # Quick captures
386
+ │ │ ├── literature/ # Reading notes
387
+ │ │ └── permanent/ # Refined knowledge
388
+ │ └── .zk/
389
+ │ ├── chroma_db/ # Vector index
390
+ │ ├── bm25_index.pkl # Keyword index
391
+ │ ├── templates/ # Jinja2 templates
392
+ │ └── config.yaml # KB config
393
+ ├── work/ # Named KB example
394
+ │ ├── notes/
395
+ │ └── .zk/
396
+ └── ~/.zk_config.json # Global KB registry
397
+ ```
398
+
399
+ ### File Format
400
+
401
+ Each note is a Markdown file with YAML frontmatter:
402
+
403
+ ```markdown
404
+ ---
405
+ id: '20260321011528'
406
+ title: Machine Learning Overview
407
+ type: permanent
408
+ created: '2026-03-21T01:15:28'
409
+ updated: '2026-03-21T01:15:28'
410
+ tags:
411
+ - ml
412
+ - ai
413
+ links:
414
+ - 20260321011546
415
+ backlinks:
416
+ - 20260321011550
417
+ ---
418
+
419
+ # Machine Learning Overview
420
+
421
+ [[Deep Learning]] is a subfield of machine learning...
422
+ ```
423
+
424
+ ### Note Types
425
+
426
+ | Type | Purpose | Filename |
427
+ |------|---------|----------|
428
+ | `fleeting` | Quick ideas, temporary captures | `YYYYMMDD-HHMMSSNNNN.md` |
429
+ | `literature` | Reading notes, paper summaries | `YYYYMMDDHHMMSSNNNN-slug.md` |
430
+ | `permanent` | Refined, lasting knowledge | `YYYYMMDDHHMMSSNNNN-slug.md` |
431
+
432
+ ### Link Resolution
433
+
434
+ `[[Link Text]]` matches notes by priority:
435
+
436
+ 1. **Exact ID** — if text matches a note ID
437
+ 2. **Exact title** — case-insensitive title match
438
+ 3. **Substring** — title contains the link text
439
+
440
+ ---
441
+
442
+ ## Contributing
443
+
444
+ ```bash
445
+ git clone https://github.com/zhuxixi/jfox.git
446
+ cd jfox
447
+ uv sync --extra dev
448
+ uv run pytest tests/ -v
449
+ ```
450
+
451
+ See [Troubleshooting](docs/troubleshooting.md) for common issues.
452
+
453
+ ## License
454
+
455
+ [MIT](LICENSE)
456
+
457
+ ## Acknowledgments
458
+
459
+ - [sentence-transformers](https://www.sbert.net/) — text embeddings
460
+ - [ChromaDB](https://www.trychroma.com/) — vector database
461
+ - [NetworkX](https://networkx.org/) — graph algorithms
462
+ - [Typer](https://typer.tiangolo.com/) — CLI framework
463
+ - [Rich](https://rich.readthedocs.io/) — terminal formatting