coding-friend-cli 1.15.0 → 1.17.0

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 (75) hide show
  1. package/README.md +12 -0
  2. package/dist/{chunk-PYRGNY5P.js → chunk-C5LYVVEI.js} +9 -1
  3. package/dist/{chunk-X5WEODUD.js → chunk-CYQU33FY.js} +1 -0
  4. package/dist/{chunk-ITL5TY3B.js → chunk-G6CEEMAR.js} +3 -3
  5. package/dist/{chunk-4DB4XTSL.js → chunk-KTX4MGMR.js} +15 -1
  6. package/dist/{chunk-KJUGTLPQ.js → chunk-YO6JKGR3.js} +38 -2
  7. package/dist/{config-UQ742WPQ.js → config-LZFXXOI4.js} +276 -14
  8. package/dist/{dev-WJ5QQ35B.js → dev-R3IYWZ3M.js} +2 -2
  9. package/dist/{disable-AOZ7FLZD.js → disable-R6K5YJN4.js} +2 -2
  10. package/dist/{enable-MJVTT3RU.js → enable-HF4PYVJN.js} +2 -2
  11. package/dist/{host-NA7LZ4HX.js → host-SYZH3FVC.js} +4 -4
  12. package/dist/index.js +78 -18
  13. package/dist/{init-AHIEQ27W.js → init-YK6YRTOT.js} +271 -23
  14. package/dist/{install-EIN7Z5V3.js → install-Q4PWEU43.js} +4 -4
  15. package/dist/{mcp-DLS3J6QJ.js → mcp-TBEDYELW.js} +4 -4
  16. package/dist/memory-7RM67ZLS.js +668 -0
  17. package/dist/postinstall.js +1 -1
  18. package/dist/{session-E3CZJJZQ.js → session-H4XW2WXH.js} +1 -1
  19. package/dist/{statusline-6HQCDWBD.js → statusline-6Y2EBAFQ.js} +1 -1
  20. package/dist/{uninstall-2IOZZERP.js → uninstall-3PSUDGI4.js} +3 -3
  21. package/dist/{update-IZ5UEKZN.js → update-WL6SFGGO.js} +4 -4
  22. package/lib/cf-memory/CHANGELOG.md +15 -0
  23. package/lib/cf-memory/README.md +284 -0
  24. package/lib/cf-memory/package-lock.json +2790 -0
  25. package/lib/cf-memory/package.json +31 -0
  26. package/lib/cf-memory/scripts/migrate-frontmatter.ts +134 -0
  27. package/lib/cf-memory/src/__tests__/daemon-e2e.test.ts +223 -0
  28. package/lib/cf-memory/src/__tests__/daemon.test.ts +407 -0
  29. package/lib/cf-memory/src/__tests__/dedup.test.ts +103 -0
  30. package/lib/cf-memory/src/__tests__/embeddings.test.ts +292 -0
  31. package/lib/cf-memory/src/__tests__/lazy-install.test.ts +210 -0
  32. package/lib/cf-memory/src/__tests__/markdown-backend.test.ts +410 -0
  33. package/lib/cf-memory/src/__tests__/migration.test.ts +255 -0
  34. package/lib/cf-memory/src/__tests__/migrations.test.ts +288 -0
  35. package/lib/cf-memory/src/__tests__/minisearch-backend.test.ts +262 -0
  36. package/lib/cf-memory/src/__tests__/ollama.test.ts +48 -0
  37. package/lib/cf-memory/src/__tests__/schema.test.ts +128 -0
  38. package/lib/cf-memory/src/__tests__/search.test.ts +115 -0
  39. package/lib/cf-memory/src/__tests__/temporal-decay.test.ts +54 -0
  40. package/lib/cf-memory/src/__tests__/tier.test.ts +293 -0
  41. package/lib/cf-memory/src/__tests__/tools.test.ts +83 -0
  42. package/lib/cf-memory/src/backends/markdown.ts +318 -0
  43. package/lib/cf-memory/src/backends/minisearch.ts +203 -0
  44. package/lib/cf-memory/src/backends/sqlite/embeddings.ts +286 -0
  45. package/lib/cf-memory/src/backends/sqlite/index.ts +549 -0
  46. package/lib/cf-memory/src/backends/sqlite/migrations.ts +188 -0
  47. package/lib/cf-memory/src/backends/sqlite/schema.ts +120 -0
  48. package/lib/cf-memory/src/backends/sqlite/search.ts +296 -0
  49. package/lib/cf-memory/src/bin/cf-memory.ts +2 -0
  50. package/lib/cf-memory/src/daemon/entry.ts +99 -0
  51. package/lib/cf-memory/src/daemon/process.ts +220 -0
  52. package/lib/cf-memory/src/daemon/server.ts +166 -0
  53. package/lib/cf-memory/src/daemon/watcher.ts +90 -0
  54. package/lib/cf-memory/src/index.ts +45 -0
  55. package/lib/cf-memory/src/lib/backend.ts +23 -0
  56. package/lib/cf-memory/src/lib/daemon-client.ts +163 -0
  57. package/lib/cf-memory/src/lib/dedup.ts +80 -0
  58. package/lib/cf-memory/src/lib/lazy-install.ts +274 -0
  59. package/lib/cf-memory/src/lib/ollama.ts +76 -0
  60. package/lib/cf-memory/src/lib/temporal-decay.ts +19 -0
  61. package/lib/cf-memory/src/lib/tier.ts +107 -0
  62. package/lib/cf-memory/src/lib/types.ts +109 -0
  63. package/lib/cf-memory/src/resources/index.ts +62 -0
  64. package/lib/cf-memory/src/server.ts +20 -0
  65. package/lib/cf-memory/src/tools/delete.ts +38 -0
  66. package/lib/cf-memory/src/tools/list.ts +38 -0
  67. package/lib/cf-memory/src/tools/retrieve.ts +52 -0
  68. package/lib/cf-memory/src/tools/search.ts +47 -0
  69. package/lib/cf-memory/src/tools/store.ts +70 -0
  70. package/lib/cf-memory/src/tools/update.ts +62 -0
  71. package/lib/cf-memory/tsconfig.json +15 -0
  72. package/lib/cf-memory/vitest.config.ts +7 -0
  73. package/lib/learn-host/CHANGELOG.md +4 -1
  74. package/lib/learn-host/package.json +1 -1
  75. package/package.json +1 -1
@@ -5,14 +5,14 @@ import {
5
5
  import {
6
6
  hasShellCompletion,
7
7
  removeShellCompletion
8
- } from "./chunk-KJUGTLPQ.js";
8
+ } from "./chunk-YO6JKGR3.js";
9
9
  import {
10
10
  resolveScope
11
- } from "./chunk-PYRGNY5P.js";
11
+ } from "./chunk-C5LYVVEI.js";
12
12
  import {
13
13
  commandExists,
14
14
  run
15
- } from "./chunk-X5WEODUD.js";
15
+ } from "./chunk-CYQU33FY.js";
16
16
  import {
17
17
  claudeSettingsPath,
18
18
  devStatePath,
@@ -2,12 +2,12 @@ import {
2
2
  getLatestVersion,
3
3
  semverCompare,
4
4
  updateCommand
5
- } from "./chunk-ITL5TY3B.js";
5
+ } from "./chunk-G6CEEMAR.js";
6
6
  import "./chunk-ORACWEDN.js";
7
7
  import "./chunk-POC2WHU2.js";
8
- import "./chunk-KJUGTLPQ.js";
9
- import "./chunk-PYRGNY5P.js";
10
- import "./chunk-X5WEODUD.js";
8
+ import "./chunk-YO6JKGR3.js";
9
+ import "./chunk-C5LYVVEI.js";
10
+ import "./chunk-CYQU33FY.js";
11
11
  import "./chunk-RWUTFVRB.js";
12
12
  import "./chunk-W5CD7WTX.js";
13
13
  export {
@@ -0,0 +1,15 @@
1
+ # CF Memory Changelog
2
+
3
+ ## v0.0.1 (unpublished)
4
+
5
+ - Add persistent memory system — MCP server with 6 tools (`memory_store`, `memory_search`, `memory_retrieve`, `memory_list`, `memory_update`, `memory_delete`) + 2 resources (`memory://index`, `memory://stats`)
6
+ - Add 3-tier graceful degradation: SQLite + hybrid search (Tier 1) → MiniSearch daemon + BM25/fuzzy (Tier 2) → Markdown file I/O (Tier 3)
7
+ - Add SQLite backend with FTS5 + sqlite-vec + RRF fusion for hybrid keyword/semantic search
8
+ - Add MiniSearch daemon (Hono + Unix Domain Socket) with file watcher and idle timeout
9
+ - Add lazy dependency installer for heavy deps (`better-sqlite3`, `sqlite-vec`, `@huggingface/transformers`)
10
+ - Add Ollama embedding support with automatic fallback to Transformers.js
11
+ - Add `cf memory` CLI commands: `status`, `search`, `list`, `start`, `stop`, `rebuild`, `init`
12
+ - Add PreCompact auto-capture hook and smart capture in skills (`cf-fix`, `cf-sys-debug`, `cf-review`, `cf-ask`)
13
+ - Add deduplication detection and temporal decay scoring
14
+ - Add frontmatter migration script for existing `docs/memory/` files
15
+ - Migrate `/cf-remember` and Frontmatter Recall to use `memory_search` MCP tool
@@ -0,0 +1,284 @@
1
+ # CF Memory
2
+
3
+ Persistent memory system for [Coding Friend](https://cf.dinhanhthi.com/). Provides MCP (Model Context Protocol) tools for storing, searching, and retrieving project knowledge across sessions.
4
+
5
+ ## Architecture
6
+
7
+ CF Memory uses a **3-tier graceful degradation** design — it automatically detects and uses the best available backend:
8
+
9
+ | Tier | Backend | Features | When |
10
+ | --------------------- | -------------------------- | ------------------------------------------------------------------------------ | --------------------------- |
11
+ | **Tier 1** (Full) | SQLite + FTS5 + sqlite-vec | Hybrid search (BM25 keyword + semantic embeddings), RRF fusion, temporal decay | SQLite deps installed |
12
+ | **Tier 2** (Lite) | MiniSearch daemon | In-memory BM25 + fuzzy search, file watcher, Unix Domain Socket | Daemon running |
13
+ | **Tier 3** (Markdown) | Markdown file I/O | Substring matching, no external deps | Always available (fallback) |
14
+
15
+ Detection: Tier 1 → Tier 2 → Tier 3 (first available wins).
16
+
17
+ ## MCP Interface
18
+
19
+ **6 tools:**
20
+
21
+ | Tool | Description |
22
+ | ----------------- | --------------------------------------------------------------- |
23
+ | `memory_store` | Store a new memory with title, description, type, tags, content |
24
+ | `memory_search` | Search memories by query with optional type/tags filter |
25
+ | `memory_retrieve` | Fetch a specific memory by ID |
26
+ | `memory_list` | List memories with optional type/category filter |
27
+ | `memory_update` | Update fields of an existing memory |
28
+ | `memory_delete` | Delete a memory by ID |
29
+
30
+ **2 resources:**
31
+
32
+ | Resource | Description |
33
+ | ---------------- | ------------------------------------------------ |
34
+ | `memory://index` | Browse all stored memories (JSON) |
35
+ | `memory://stats` | Storage statistics (total, by category, by type) |
36
+
37
+ ## Memory Model
38
+
39
+ **Types** map to storage categories:
40
+
41
+ | Type | Category (folder) | Use case |
42
+ | ------------ | ----------------- | ------------------------------- |
43
+ | `fact` | `features/` | Feature descriptions, facts |
44
+ | `preference` | `conventions/` | Conventions, preferences |
45
+ | `context` | `decisions/` | Architecture decisions, context |
46
+ | `episode` | `bugs/` | Bug reports, debugging sessions |
47
+ | `procedure` | `infrastructure/` | Procedures, infra setup |
48
+
49
+ Memories are stored as Markdown files with YAML frontmatter in `docs/memory/<category>/`.
50
+
51
+ ## Embedding Models
52
+
53
+ Tier 1 (SQLite) uses embedding models to generate vectors for semantic search. Two providers are supported:
54
+
55
+ ### Providers
56
+
57
+ | Provider | How it works | Default model | Pros | Cons |
58
+ | ------------------- | ----------------------------------------------- | -------------------------------- | -------------------------------------------- | ------------------------------------------------ |
59
+ | **Transformers.js** | Runs in-process via `@huggingface/transformers` | `Xenova/all-MiniLM-L6-v2` (384d) | Zero config, no external service | Slower first load (~5s), limited model selection |
60
+ | **Ollama** | Calls local Ollama server API | `all-minilm:l6-v2` (384d) | Fast, wide model selection, GPU acceleration | Requires Ollama running separately |
61
+
62
+ ### Recommended Models
63
+
64
+ | Model | Dims | Size | Notes |
65
+ | -------------------------- | ---- | ------- | --------------------------------------------------------------------- |
66
+ | `all-minilm:l6-v2` | 384 | ~23 MB | **Default** — fast, good for small-to-medium collections |
67
+ | `nomic-embed-text` | 768 | ~274 MB | **Recommended upgrade** — significantly better semantic understanding |
68
+ | `mxbai-embed-large` | 1024 | ~670 MB | Best quality, suitable for large collections (100+ memories) |
69
+ | `snowflake-arctic-embed:s` | 384 | ~67 MB | Alternative compact model |
70
+ | `snowflake-arctic-embed:m` | 768 | ~250 MB | Good balance of quality and speed |
71
+ | `bge-base-en-v1.5` | 768 | ~130 MB | Strong English-language model |
72
+ | `bge-large-en-v1.5` | 1024 | ~670 MB | Top-tier English model |
73
+
74
+ ### Using Ollama for Embeddings
75
+
76
+ 1. Install Ollama: https://ollama.com/download
77
+ 2. Pull a model:
78
+ ```bash
79
+ ollama pull nomic-embed-text
80
+ ```
81
+ 3. Configure in `.coding-friend/config.json`:
82
+ ```json
83
+ {
84
+ "memory": {
85
+ "embedding": {
86
+ "provider": "ollama",
87
+ "model": "nomic-embed-text"
88
+ }
89
+ }
90
+ }
91
+ ```
92
+ 4. If you have existing memories, rebuild to re-embed:
93
+ ```bash
94
+ cf memory rebuild
95
+ ```
96
+
97
+ If Ollama is not running or the configured model is missing, the system falls back to Transformers.js automatically.
98
+
99
+ ### Changing Models
100
+
101
+ When you switch to a model with different dimensions (e.g., 384 → 768):
102
+
103
+ 1. The system detects the mismatch on startup
104
+ 2. Vector search is **disabled** with a warning
105
+ 3. Run `cf memory rebuild` to re-embed all memories
106
+ 4. Vector search is re-enabled with the new dimensions
107
+
108
+ Markdown files are unaffected — they remain the source of truth.
109
+
110
+ ### Dynamic Dimensions
111
+
112
+ CF Memory includes a lookup table of known models and their dimensions. For models not in the table, it defaults to 384 dimensions. If you use an exotic model, the system logs a warning suggesting you verify dimensions.
113
+
114
+ Known models include: all-MiniLM-L6-v2 (384d), nomic-embed-text (768d), mxbai-embed-large (1024d), snowflake-arctic-embed variants, and BGE variants.
115
+
116
+ ## Project Structure
117
+
118
+ ```
119
+ src/
120
+ ├── index.ts # MCP server entry (stdio transport)
121
+ ├── server.ts # Tool registration
122
+ ├── bin/
123
+ │ └── cf-memory.ts # CLI entry point
124
+ ├── tools/ # MCP tool handlers
125
+ │ ├── store.ts
126
+ │ ├── search.ts
127
+ │ ├── retrieve.ts
128
+ │ ├── list.ts
129
+ │ ├── update.ts
130
+ │ └── delete.ts
131
+ ├── resources/
132
+ │ └── index.ts # memory://index + memory://stats
133
+ ├── backends/
134
+ │ ├── markdown.ts # Tier 3: file-based backend
135
+ │ ├── minisearch.ts # Tier 2: in-memory search backend
136
+ │ └── sqlite/
137
+ │ ├── index.ts # Tier 1: SQLite backend
138
+ │ ├── schema.ts # DB schema + PRAGMAs
139
+ │ ├── migrations.ts # Version tracking, vec table
140
+ │ ├── search.ts # FTS5 + vector + RRF hybrid search
141
+ │ └── embeddings.ts # Ollama / Transformers.js pipeline
142
+ ├── daemon/
143
+ │ ├── entry.ts # Daemon process entry
144
+ │ ├── process.ts # Start/stop, PID management
145
+ │ ├── server.ts # Hono HTTP app (UDS)
146
+ │ └── watcher.ts # File watcher + index rebuild
147
+ ├── lib/
148
+ │ ├── types.ts # MemoryType, Memory, SearchResult, etc.
149
+ │ ├── backend.ts # MemoryBackend interface (8 methods)
150
+ │ ├── tier.ts # detectTier() + createBackendForTier()
151
+ │ ├── daemon-client.ts # HTTP client over Unix Domain Socket
152
+ │ ├── lazy-install.ts # On-demand dep installer
153
+ │ ├── dedup.ts # Jaccard similarity deduplication
154
+ │ ├── temporal-decay.ts # Recency + access scoring
155
+ │ └── ollama.ts # Ollama detection + embedding provider
156
+ └── __tests__/ # 14 test suites (vitest)
157
+ ```
158
+
159
+ ## Development
160
+
161
+ ### Prerequisites
162
+
163
+ - Node.js 22+
164
+ - npm
165
+
166
+ ### Setup
167
+
168
+ ```bash
169
+ cd cli/lib/cf-memory
170
+ npm install
171
+ ```
172
+
173
+ ### Scripts
174
+
175
+ | Command | Description |
176
+ | -------------------- | ------------------------------------- |
177
+ | `npm run build` | Compile TypeScript → `dist/` |
178
+ | `npm run dev` | Run MCP server directly via tsx |
179
+ | `npm run dev:watch` | Watch mode — recompile on changes |
180
+ | `npm start` | Run compiled server (`dist/index.js`) |
181
+ | `npm test` | Run all tests (vitest) |
182
+ | `npm run test:watch` | Run tests in watch mode |
183
+
184
+ ### Dev mode and `cf dev sync`
185
+
186
+ CF Memory lives in `cli/lib/cf-memory/` (part of the CLI package), **not** in `plugin/`. This means `cf dev sync` is **not needed** — the CLI resolves cf-memory via `getLibPath()` which points directly to `cli/lib/cf-memory/dist/`.
187
+
188
+ | Consumer | Needs `cf dev sync`? | How changes take effect |
189
+ | ----------------------------------- | --------------------------------- | ---------------------------------------------------------------------------- |
190
+ | CLI commands (`cf memory *`) | No | `dev:watch` recompiles `dist/` → picked up on next CLI invocation |
191
+ | MCP server (if configured) | No | Needs MCP server **restart** (long-running process) |
192
+ | Plugin skills (cf-fix, cf-ask, ...) | Yes (for skill file changes only) | Skills reference MCP tools by name — cf-memory code itself doesn't need sync |
193
+
194
+ In short: run `npm run dev:watch` (or `npm run dev` from the monorepo root) and your changes are immediately available to CLI commands. If you're running the MCP server, restart it after changes.
195
+
196
+ ### Running the MCP server locally
197
+
198
+ ```bash
199
+ # Via tsx (no build needed)
200
+ npm run dev
201
+
202
+ # Or build first, then run
203
+ npm run build
204
+ npm start
205
+
206
+ # With custom docs directory
207
+ MEMORY_DOCS_DIR=/path/to/docs/memory npm run dev
208
+
209
+ # Force a specific tier
210
+ MEMORY_TIER=markdown npm run dev # Options: auto | full | lite | markdown
211
+ ```
212
+
213
+ ### Running tests
214
+
215
+ ```bash
216
+ npm test # Run once
217
+ npm run test:watch # Watch mode
218
+ ```
219
+
220
+ ### Working with the daemon (Tier 2)
221
+
222
+ ```bash
223
+ # Start daemon manually (for testing)
224
+ node dist/daemon/entry.js ./docs/memory
225
+
226
+ # With idle timeout (ms) and tier
227
+ node dist/daemon/entry.js ./docs/memory 1800000 --tier=lite
228
+ ```
229
+
230
+ The daemon runs a Hono HTTP server on a Unix Domain Socket at `~/.coding-friend/memory/daemon.sock`, with PID tracking at `~/.coding-friend/memory/daemon.pid`.
231
+
232
+ ### Lazy dependencies (Tier 1)
233
+
234
+ Heavy dependencies for Tier 1 (SQLite + embeddings) are installed on-demand into `~/.coding-friend/memory/node_modules/`, not in this package's `node_modules/`. These include:
235
+
236
+ - `better-sqlite3` — native SQLite driver
237
+ - `sqlite-vec` — vector search extension
238
+ - `@huggingface/transformers` — local embeddings (fallback when Ollama is unavailable)
239
+
240
+ To install them manually: `cf memory init`
241
+
242
+ ### Migration script
243
+
244
+ For migrating existing `docs/memory/` files to the current frontmatter format:
245
+
246
+ ```bash
247
+ npx tsx scripts/migrate-frontmatter.ts [docsDir]
248
+ ```
249
+
250
+ ## Integration with the CLI
251
+
252
+ ### MCP setup for end users
253
+
254
+ Users don't need to manually configure the MCP server. `cf init` includes a "CF Memory MCP" step that asks to add `coding-friend-memory` to the project's `.mcp.json` automatically. If skipped during init, users can run `cf memory mcp` to get the config for manual setup.
255
+
256
+ ### CLI commands
257
+
258
+ The `cf` CLI exposes memory commands that use this package:
259
+
260
+ | Command | Description |
261
+ | -------------------------- | ----------------------------------------------------------------- |
262
+ | `cf memory status` | Show current tier, daemon status, memory count |
263
+ | `cf memory search <query>` | Search memories from the terminal |
264
+ | `cf memory list` | List all stored memories |
265
+ | `cf memory start` | Start the MiniSearch daemon (Tier 2) |
266
+ | `cf memory stop` | Stop the daemon |
267
+ | `cf memory rebuild` | Rebuild search index (Tier 1 direct or via daemon) |
268
+ | `cf memory init` | Install Tier 1 deps + import existing memories into SQLite |
269
+ | `cf memory mcp` | Print MCP server config for use in Claude Desktop / other clients |
270
+
271
+ ## Environment Variables
272
+
273
+ | Variable | Default | Description |
274
+ | ----------------------------- | ------------------------ | ------------------------------------------------- |
275
+ | `MEMORY_DOCS_DIR` | `./docs/memory` | Path to memory storage directory |
276
+ | `MEMORY_TIER` | `auto` | Force a tier: `auto`, `full`, `lite`, `markdown` |
277
+ | `MEMORY_EMBEDDING_PROVIDER` | `transformers` | Embedding provider: `transformers` or `ollama` |
278
+ | `MEMORY_EMBEDDING_MODEL` | (provider default) | Embedding model name (e.g., `nomic-embed-text`) |
279
+ | `MEMORY_EMBEDDING_OLLAMA_URL` | `http://localhost:11434` | Ollama server URL |
280
+ | `OLLAMA_HOST` | `http://localhost:11434` | Ollama server URL (used by Ollama auto-detection) |
281
+
282
+ ## Versioning
283
+
284
+ Part of the [coding-friend](https://github.com/dinhanhthi/coding-friend) monorepo. Tagged independently as `cf-memory-v*`. Changelog: [CHANGELOG.md](./CHANGELOG.md).