coding-friend-cli 1.37.0 → 1.38.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 (71) hide show
  1. package/README.md +7 -2
  2. package/dist/{chunk-GZT3YPAP.js → chunk-32UAW3NX.js} +1 -1
  3. package/dist/chunk-5QCGEPQO.js +238 -0
  4. package/dist/{chunk-YIXAQ4R2.js → chunk-6NXZKAOV.js} +1 -1
  5. package/dist/{chunk-676YCW6T.js → chunk-776ZY62N.js} +99 -7
  6. package/dist/{chunk-DP6DFQ4G.js → chunk-BXSCYGWE.js} +2 -2
  7. package/dist/{chunk-W6D3J5DX.js → chunk-CGEMETKQ.js} +8 -6
  8. package/dist/{chunk-XEKQW4RN.js → chunk-ETTZRJ55.js} +1 -1
  9. package/dist/{chunk-IKLMHJH6.js → chunk-GIH6E7GJ.js} +62 -1
  10. package/dist/{chunk-6S7352JG.js → chunk-ONG4KRYP.js} +1 -1
  11. package/dist/{chunk-X2H7JJMR.js → chunk-PLSJW7QJ.js} +29 -1
  12. package/dist/{chunk-O5ZKLFSL.js → chunk-RCE4OWNX.js} +1 -1
  13. package/dist/{chunk-PI4P34KF.js → chunk-RFNKPAJW.js} +3 -1
  14. package/dist/{clean-WEYQZB34.js → clean-YWEMYDE5.js} +2 -2
  15. package/dist/{config-ZMR2AOBB.js → config-NG7SICM4.js} +12 -24
  16. package/dist/{dev-IGHMMEP4.js → dev-PTBNMKZT.js} +3 -3
  17. package/dist/{disable-HL5OEURT.js → disable-MO7AXYYF.js} +20 -3
  18. package/dist/{enable-CZIOCKKJ.js → enable-4GXLQEHD.js} +20 -3
  19. package/dist/{guide-CO2V4ZLZ.js → guide-HCR43LJN.js} +1 -1
  20. package/dist/{host-SSRI4JZV.js → host-EV6QIVTI.js} +2 -2
  21. package/dist/index.js +59 -47
  22. package/dist/{init-6MFQWPOP.js → init-KYE5CJMW.js} +115 -12
  23. package/dist/{install-37NN4CQH.js → install-XAFQY5YF.js} +79 -6
  24. package/dist/{learn-OPH3CI67.js → learn-MC4VDHZH.js} +2 -2
  25. package/dist/{mcp-DWKVMNC7.js → mcp-FV6YX3ZT.js} +7 -7
  26. package/dist/{mcp-serve-5GODJ4DJ.js → mcp-serve-PXREYQRZ.js} +2 -2
  27. package/dist/{mcp-serve-learn-OF3ZJUJC.js → mcp-serve-learn-UVXIDOEZ.js} +1 -1
  28. package/dist/{memory-TRDLADUM.js → memory-DF7OUOTV.js} +6 -6
  29. package/dist/{permission-I3OFJUYA.js → permission-VISPGMUK.js} +38 -4
  30. package/dist/{permissions-J46VP6US.js → permissions-2SBACQHV.js} +2 -2
  31. package/dist/{session-S4WKA4P5.js → session-QK6OZO3X.js} +2 -2
  32. package/dist/{status-YZEOUX46.js → status-FVFTJ6GS.js} +11 -10
  33. package/dist/{statusline-KKFJPTI7.js → statusline-AOZHEQSV.js} +2 -2
  34. package/dist/{uninstall-AVA3J554.js → uninstall-MF6FRUBO.js} +51 -4
  35. package/dist/{update-Q3ACCK4Z.js → update-QNUCSDSA.js} +6 -5
  36. package/dist/{update-check-25SCLHZO.js → update-check-7LKJLJPM.js} +1 -1
  37. package/lib/cf-memory/src/lib/claude-md.ts +82 -70
  38. package/lib/cf-memory/src/lib/status-frame.ts +2 -2
  39. package/lib/cf-memory/src/tools/delete.ts +1 -1
  40. package/lib/cf-memory/src/tools/store.ts +6 -6
  41. package/lib/cf-memory/src/tools/update.ts +5 -11
  42. package/package.json +32 -4
  43. package/lib/cf-memory/README.md +0 -317
  44. package/lib/cf-memory/src/__tests__/claude-md.test.ts +0 -343
  45. package/lib/cf-memory/src/__tests__/daemon-client.test.ts +0 -146
  46. package/lib/cf-memory/src/__tests__/daemon-e2e.test.ts +0 -223
  47. package/lib/cf-memory/src/__tests__/daemon.test.ts +0 -407
  48. package/lib/cf-memory/src/__tests__/dedup.test.ts +0 -103
  49. package/lib/cf-memory/src/__tests__/embeddings.test.ts +0 -292
  50. package/lib/cf-memory/src/__tests__/lazy-install.test.ts +0 -210
  51. package/lib/cf-memory/src/__tests__/markdown-backend.test.ts +0 -450
  52. package/lib/cf-memory/src/__tests__/migration.test.ts +0 -255
  53. package/lib/cf-memory/src/__tests__/migrations.test.ts +0 -288
  54. package/lib/cf-memory/src/__tests__/minisearch-backend.test.ts +0 -262
  55. package/lib/cf-memory/src/__tests__/ollama.test.ts +0 -48
  56. package/lib/cf-memory/src/__tests__/project-id.test.ts +0 -43
  57. package/lib/cf-memory/src/__tests__/schema.test.ts +0 -128
  58. package/lib/cf-memory/src/__tests__/search.test.ts +0 -115
  59. package/lib/cf-memory/src/__tests__/sqlite-lazy-db.test.ts +0 -213
  60. package/lib/cf-memory/src/__tests__/status-frame.test.ts +0 -136
  61. package/lib/cf-memory/src/__tests__/temporal-decay.test.ts +0 -54
  62. package/lib/cf-memory/src/__tests__/tier.test.ts +0 -388
  63. package/lib/cf-memory/src/__tests__/tools.test.ts +0 -83
  64. package/lib/cf-memory/vitest.config.ts +0 -7
  65. package/lib/learn-host/.prettierignore +0 -4
  66. package/lib/learn-host/.prettierrc +0 -8
  67. package/lib/learn-host/README.md +0 -113
  68. package/lib/learn-host/eslint.config.mjs +0 -6
  69. package/lib/learn-mcp/README.md +0 -187
  70. package/lib/learn-mcp/src/__tests__/docs.test.ts +0 -117
  71. package/lib/learn-mcp/vitest.config.ts +0 -8
@@ -1,187 +0,0 @@
1
- # coding-friend-learn-mcp
2
-
3
- MCP (Model Context Protocol) server that exposes your `/cf-learn` docs as tools for Claude — letting Claude read, search, write, and improve your learning notes directly.
4
-
5
- ## Usage (via CLI)
6
-
7
- ```bash
8
- cf mcp # setup MCP for docs/learn/
9
- cf mcp ./my-docs # setup MCP for a custom directory
10
- ```
11
-
12
- The CLI builds the server and prints the config to add to Claude Desktop / Claude Code.
13
-
14
- ## Local Development
15
-
16
- Run the server directly without the CLI — useful when working on tools or docs logic.
17
-
18
- ### 1. Install dependencies
19
-
20
- ```bash
21
- cd cli/lib/learn-mcp
22
- npm install
23
- ```
24
-
25
- ### 2. Run with tsx (no build needed)
26
-
27
- The server accepts the docs directory as the first CLI argument, or via `LEARN_DOCS_DIR` env var.
28
-
29
- ```bash
30
- # Using argument
31
- npx tsx src/index.ts /path/to/your/docs/learn
32
-
33
- # Using env var
34
- LEARN_DOCS_DIR=/path/to/your/docs/learn npx tsx src/index.ts
35
-
36
- # Point to this repo's own learn docs
37
- npx tsx src/index.ts ../../../docs/learn
38
- ```
39
-
40
- The server communicates over stdio (MCP protocol), so you won't see output when running manually — it's meant to be connected to Claude.
41
-
42
- ### 3. Connect to Claude Code (dev mode)
43
-
44
- Add to your project's `.mcp.json`:
45
-
46
- ```json
47
- {
48
- "mcpServers": {
49
- "coding-friend-learn": {
50
- "type": "stdio",
51
- "command": "npx",
52
- "args": [
53
- "tsx",
54
- "/path/to/coding-friend/cli/lib/learn-mcp/src/index.ts",
55
- "/path/to/your/docs/learn"
56
- ]
57
- }
58
- }
59
- }
60
- ```
61
-
62
- Or for Claude Desktop, add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
63
-
64
- ```json
65
- {
66
- "mcpServers": {
67
- "coding-friend-learn": {
68
- "command": "npx",
69
- "args": [
70
- "tsx",
71
- "/path/to/coding-friend/cli/lib/learn-mcp/src/index.ts",
72
- "/path/to/your/docs/learn"
73
- ]
74
- }
75
- }
76
- }
77
- ```
78
-
79
- ### 4. Watch mode (auto-rebuild)
80
-
81
- Keep a terminal running to auto-rebuild on every file change:
82
-
83
- ```bash
84
- npm run dev:watch
85
- ```
86
-
87
- Then restart the MCP server in Claude Code (`/mcp` → restart) to pick up the latest changes.
88
-
89
- ### 5. Build and run compiled
90
-
91
- ```bash
92
- npm run build
93
- node dist/index.js /path/to/docs/learn
94
- ```
95
-
96
- For Claude Desktop with the compiled version:
97
-
98
- ```json
99
- {
100
- "mcpServers": {
101
- "coding-friend-learn": {
102
- "command": "node",
103
- "args": [
104
- "/path/to/coding-friend/cli/lib/learn-mcp/dist/index.js",
105
- "/path/to/your/docs/learn"
106
- ]
107
- }
108
- }
109
- }
110
- ```
111
-
112
- > **Note:** The path must include `/cli/lib/learn-mcp/`, not `/lib/learn-mcp/`. Run `npm run build` first to generate `dist/`.
113
-
114
- ## Docs Directory Structure
115
-
116
- ```
117
- docs/
118
- └── learn/
119
- ├── category-one/
120
- │ ├── my-doc.md
121
- │ └── another-doc.md
122
- └── category-two/
123
- └── some-doc.md
124
- ```
125
-
126
- Each `.md` file needs frontmatter:
127
-
128
- ```md
129
- ---
130
- title: My Doc Title
131
- category: category-one
132
- tags: [typescript, patterns]
133
- created: 2025-01-01
134
- updated: 2025-01-15
135
- ---
136
-
137
- Content here...
138
- ```
139
-
140
- ## Available Tools
141
-
142
- | Tool | Type | Description |
143
- | ----------------- | ----- | ------------------------------------------------ |
144
- | `list-categories` | Read | List all doc categories |
145
- | `list-docs` | Read | List docs (optionally filter by category or tag) |
146
- | `read-doc` | Read | Read a specific doc by category + slug |
147
- | `search-docs` | Read | Full-text search across all docs |
148
- | `get-review-list` | Read | Get docs needing review |
149
- | `create-doc` | Write | Create a new doc with frontmatter |
150
- | `update-doc` | Write | Append content or update tags on an existing doc |
151
- | `improve-doc` | Write | Replace doc content while preserving frontmatter |
152
- | `track-knowledge` | Write | Mark a doc as remembered / needs-review / new |
153
-
154
- ## Structure
155
-
156
- ```
157
- src/
158
- ├── index.ts # Entry: parses docs dir, starts MCP server
159
- ├── server.ts # Registers all tools
160
- ├── bin/
161
- │ └── learn-mcp.ts # CLI binary entry
162
- ├── tools/ # One file per MCP tool
163
- │ ├── list-categories.ts
164
- │ ├── list-docs.ts
165
- │ ├── read-doc.ts
166
- │ ├── search-docs.ts
167
- │ ├── create-doc.ts
168
- │ ├── update-doc.ts
169
- │ ├── improve-doc.ts
170
- │ ├── track-knowledge.ts
171
- │ └── get-review-list.ts
172
- └── lib/
173
- ├── docs.ts # Shared doc utilities (read, write, search)
174
- ├── types.ts # TypeScript interfaces
175
- └── knowledge.ts # Knowledge tracking state
176
- ```
177
-
178
- ## How It Fits Together
179
-
180
- ```
181
- cf mcp [path]
182
- └─ resolves docs dir
183
- └─ npm install + build (one-time)
184
- └─ prints MCP config to add to Claude
185
- ```
186
-
187
- Once configured, Claude can call these tools directly to read and write your learning notes without leaving the conversation.
@@ -1,117 +0,0 @@
1
- import fs from "node:fs";
2
- import matter from "gray-matter";
3
- import os from "node:os";
4
- import path from "node:path";
5
- import { afterEach, beforeEach, describe, expect, it } from "vitest";
6
- import { createDoc, readDoc, updateDoc } from "../lib/docs.js";
7
-
8
- /**
9
- * Place a valid .md file outside docsDir so traversal attempts
10
- * actually find a file — this proves the guard blocks the read,
11
- * not just "file not found".
12
- */
13
- function placeTrapFile(dir: string, name: string): string {
14
- fs.mkdirSync(dir, { recursive: true });
15
- const filePath = path.join(dir, name);
16
- const content = matter.stringify("SECRET CONTENT", {
17
- title: "Trap",
18
- category: "trap",
19
- tags: [],
20
- created: "2026-01-01",
21
- updated: "2026-01-01",
22
- });
23
- fs.writeFileSync(filePath, content, "utf-8");
24
- return filePath;
25
- }
26
-
27
- describe("docs path traversal protection", () => {
28
- let tmpDir: string;
29
- let docsDir: string;
30
-
31
- beforeEach(() => {
32
- tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "learn-mcp-test-"));
33
- docsDir = path.join(tmpDir, "docs");
34
- fs.mkdirSync(docsDir, { recursive: true });
35
-
36
- // Create a legitimate doc for testing
37
- createDoc(docsDir, "javascript", "test-doc", ["test"], "Hello world");
38
- });
39
-
40
- afterEach(() => {
41
- fs.rmSync(tmpDir, { recursive: true, force: true });
42
- });
43
-
44
- describe("readDoc", () => {
45
- it("reads legitimate docs normally", () => {
46
- const doc = readDoc(docsDir, "javascript", "test-doc");
47
- expect(doc).not.toBeNull();
48
- expect(doc!.content).toContain("Hello world");
49
- });
50
-
51
- it("rejects path traversal in category", () => {
52
- // Place a trap file at tmpDir/secret.md (one level above docsDir)
53
- placeTrapFile(tmpDir, "secret.md");
54
- const doc = readDoc(docsDir, "..", "secret");
55
- expect(doc).toBeNull();
56
- });
57
-
58
- it("rejects path traversal in slug", () => {
59
- placeTrapFile(tmpDir, "secret.md");
60
- const doc = readDoc(docsDir, "javascript", "../../secret");
61
- expect(doc).toBeNull();
62
- });
63
-
64
- it("rejects path traversal with nested sequences", () => {
65
- placeTrapFile(tmpDir, "secret.md");
66
- const doc = readDoc(docsDir, "javascript/../../..", "secret");
67
- expect(doc).toBeNull();
68
- });
69
- });
70
-
71
- describe("createDoc", () => {
72
- it("creates legitimate docs normally", () => {
73
- const filePath = createDoc(
74
- docsDir,
75
- "python",
76
- "New Doc",
77
- ["tag1"],
78
- "Content",
79
- );
80
- expect(filePath).toContain(docsDir);
81
- expect(fs.existsSync(filePath)).toBe(true);
82
- });
83
-
84
- it("rejects path traversal in category", () => {
85
- expect(() =>
86
- createDoc(docsDir, "../escape", "title", [], "content"),
87
- ).toThrow();
88
- // Verify no file was created outside docsDir
89
- expect(fs.existsSync(path.join(tmpDir, "escape"))).toBe(false);
90
- });
91
- });
92
-
93
- describe("updateDoc", () => {
94
- it("updates legitimate docs normally", () => {
95
- const result = updateDoc(docsDir, "javascript", "test-doc", {
96
- title: "Updated",
97
- });
98
- expect(result).not.toBeNull();
99
- });
100
-
101
- it("rejects path traversal in category", () => {
102
- placeTrapFile(tmpDir, "secret.md");
103
- const result = updateDoc(docsDir, "..", "secret", {
104
- title: "hack",
105
- });
106
- expect(result).toBeNull();
107
- });
108
-
109
- it("rejects path traversal in slug", () => {
110
- placeTrapFile(tmpDir, "secret.md");
111
- const result = updateDoc(docsDir, "javascript", "../../secret", {
112
- title: "hack",
113
- });
114
- expect(result).toBeNull();
115
- });
116
- });
117
- });
@@ -1,8 +0,0 @@
1
- import { defineConfig } from "vitest/config";
2
-
3
- export default defineConfig({
4
- test: {
5
- environment: "node",
6
- exclude: ["dist/**", "node_modules/**"],
7
- },
8
- });