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.
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/CLAUDE.md +4 -2
- jfox_cli-0.3.2/PKG-INFO +463 -0
- jfox_cli-0.3.2/README.md +424 -0
- jfox_cli-0.3.2/docs/installation.md +72 -0
- jfox_cli-0.3.2/docs/superpowers/plans/2026-04-14-sync-docs-daemon-show.md +486 -0
- jfox_cli-0.3.2/docs/superpowers/specs/2026-04-14-show-command-design.md +44 -0
- jfox_cli-0.3.2/docs/troubleshooting.md +43 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/jfox/__init__.py +1 -1
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/jfox/cli.py +124 -0
- jfox_cli-0.3.2/jfox/daemon/__init__.py +15 -0
- jfox_cli-0.3.2/jfox/daemon/__main__.py +5 -0
- jfox_cli-0.3.2/jfox/daemon/client.py +99 -0
- jfox_cli-0.3.2/jfox/daemon/process.py +226 -0
- jfox_cli-0.3.2/jfox/daemon/server.py +126 -0
- jfox_cli-0.3.2/jfox/embedding_backend.py +112 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/pyproject.toml +4 -2
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/skills-recommend/README.md +2 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/skills-recommend/claude-code/jfox-common/SKILL.md +11 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/skills-recommend/claude-code/jfox-ingest/SKILL.md +7 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/skills-recommend/claude-code/jfox-organize/SKILL.md +5 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/skills-recommend/claude-code/jfox-search/SKILL.md +3 -1
- jfox_cli-0.3.2/skills-recommend/claude-code/jfox-session-summary/SKILL.md +96 -0
- jfox_cli-0.3.2/tests/unit/test_show.py +73 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/uv.lock +34 -1
- jfox_cli-0.2.2/PKG-INFO +0 -639
- jfox_cli-0.2.2/README.md +0 -602
- jfox_cli-0.2.2/jfox/embedding_backend.py +0 -64
- jfox_cli-0.2.2/skill/evals/evals.json +0 -185
- jfox_cli-0.2.2/skill/knowledge-base-notes/SKILL.md +0 -278
- jfox_cli-0.2.2/skill/knowledge-base-workspace/SKILL.md +0 -242
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/.githooks/pre-push +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/.github/workflows/integration-test.yml +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/.github/workflows/publish.yml +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/.gitignore +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/.python-version +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/AGENTS.md +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/CHANGELOG.md +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/DEVELOPMENT_PLAN.md +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/SESSION.md +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/SESSION_SUMMARY.md +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/docs/superpowers/plans/2026-04-11-bulk-import-bm25-fix.md +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/docs/superpowers/plans/2026-04-11-edit-command.md +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/docs/superpowers/plans/2026-04-11-unify-format-option.md +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/docs/superpowers/plans/2026-04-12-ci-coverage-optimization.md +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/docs/superpowers/plans/2026-04-12-edit-content-file.md +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/docs/superpowers/plans/2026-04-12-fix-index-rebuild-clear.md +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/docs/superpowers/plans/2026-04-12-fix-index-verify-id-mismatch.md +0 -0
- {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
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/docs/superpowers/plans/2026-04-12-index-kb-param.md +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/docs/superpowers/plans/2026-04-12-lazy-import-perf.md +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/docs/superpowers/plans/2026-04-12-skill-redesign.md +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/docs/superpowers/specs/2026-04-03-bugfixes-design.md +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/docs/superpowers/specs/2026-04-12-skill-redesign-design.md +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/docs/superpowers/specs/2026-04-13-pr-auto-code-review-design.md +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/jessica-jones-static-cable.md +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/jfox/__main__.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/jfox/bm25_index.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/jfox/config.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/jfox/formatters.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/jfox/git_extractor.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/jfox/global_config.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/jfox/graph.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/jfox/indexer.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/jfox/kb_manager.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/jfox/models.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/jfox/note.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/jfox/performance.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/jfox/search_engine.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/jfox/template.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/jfox/template_cli.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/jfox/vector_store.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/pytest.ini +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/run_full_test.ps1 +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/COVERAGE_PLAN.md +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/MIGRATION.md +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/TESTS.md +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/conftest.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/integration/__init__.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/integration/test_backlinks.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/performance/__init__.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/performance/test_performance.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/test_advanced_features.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/test_cli_format.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/test_config_unit.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/test_core_workflow.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/test_hybrid_search.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/test_integration.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/test_kb_current.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/test_suggest_links.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/unit/__init__.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/unit/test_bm25_batch.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/unit/test_edit.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/unit/test_format_unify.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/unit/test_formatters.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/unit/test_git_extractor.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/unit/test_global_config.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/unit/test_index_kb_param.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/unit/test_indexer_clear_before_rebuild.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/unit/test_indexer_verify.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/unit/test_kb_manager.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/unit/test_lazy_import.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/unit/test_logging_config.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/unit/test_template.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/unit/test_template_cli.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/unit/test_vector_store_clear.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/utils/__init__.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/utils/assertions.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/utils/jfox_cli.py +0 -0
- {jfox_cli-0.2.2 → jfox_cli-0.3.2}/tests/utils/note_generator.py +0 -0
- {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 (~
|
|
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
|
|
jfox_cli-0.3.2/PKG-INFO
ADDED
|
@@ -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)
|
|
43
|
+
[](pyproject.toml)
|
|
44
|
+
[](#)
|
|
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
|