coding-friend-cli 1.2.0 → 1.3.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.
- package/README.md +29 -6
- package/dist/{chunk-R6ZYK4UX.js → chunk-CSF4FAHL.js} +2 -1
- package/dist/{chunk-5HZJX47M.js → chunk-Q4DKU5IG.js} +3 -5
- package/dist/{dev-LZASFXZZ.js → dev-VMN2JHA6.js} +89 -18
- package/dist/{host-BK6DYFWF.js → host-2WINWEW7.js} +1 -1
- package/dist/index.js +30 -13
- package/dist/{init-2UKYE2KV.js → init-CTCDQKIQ.js} +23 -12
- package/dist/{mcp-CH4SKZSX.js → mcp-43HCE2KD.js} +1 -1
- package/dist/postinstall.js +1 -1
- package/dist/{update-5A2OP6EY.js → update-GGCBM7U4.js} +45 -15
- package/lib/learn-host/.prettierignore +1 -0
- package/lib/learn-host/CHANGELOG.md +5 -0
- package/lib/learn-host/README.md +114 -0
- package/lib/learn-host/next-env.d.ts +1 -1
- package/lib/learn-host/next.config.ts +3 -0
- package/lib/learn-host/package.json +1 -1
- package/lib/learn-host/public/logo.svg +1 -1
- package/lib/learn-host/src/app/apple-icon.svg +1 -1
- package/lib/learn-host/src/app/icon.svg +1 -1
- package/lib/learn-host/src/components/Sidebar.tsx +1 -1
- package/lib/learn-host/src/lib/docs.ts +2 -2
- package/lib/learn-mcp/CHANGELOG.md +5 -0
- package/lib/learn-mcp/README.md +169 -0
- package/lib/learn-mcp/package.json +2 -1
- package/lib/learn-mcp/src/index.ts +1 -1
- package/lib/learn-mcp/src/lib/docs.ts +1 -3
- package/lib/learn-mcp/src/lib/knowledge.ts +2 -1
- package/lib/learn-mcp/src/tools/get-review-list.ts +1 -4
- package/lib/learn-mcp/src/tools/search-docs.ts +1 -4
- package/package.json +2 -2
- package/lib/learn-host/public/_pagefind/fragment/en_1172b3c.pf_fragment +0 -0
- package/lib/learn-host/public/_pagefind/fragment/en_118ad1c.pf_fragment +0 -0
- package/lib/learn-host/public/_pagefind/fragment/en_32ab3d8.pf_fragment +0 -0
- package/lib/learn-host/public/_pagefind/fragment/en_441f1e1.pf_fragment +0 -0
- package/lib/learn-host/public/_pagefind/fragment/en_4452de4.pf_fragment +0 -0
- package/lib/learn-host/public/_pagefind/fragment/en_4ae396d.pf_fragment +0 -0
- package/lib/learn-host/public/_pagefind/fragment/en_58ee89d.pf_fragment +0 -0
- package/lib/learn-host/public/_pagefind/fragment/en_6dd2225.pf_fragment +0 -0
- package/lib/learn-host/public/_pagefind/fragment/en_765a297.pf_fragment +0 -0
- package/lib/learn-host/public/_pagefind/fragment/en_7a4cc4a.pf_fragment +0 -0
- package/lib/learn-host/public/_pagefind/fragment/en_8050261.pf_fragment +0 -0
- package/lib/learn-host/public/_pagefind/fragment/en_83eaedf.pf_fragment +0 -0
- package/lib/learn-host/public/_pagefind/fragment/en_925bc5f.pf_fragment +0 -0
- package/lib/learn-host/public/_pagefind/fragment/en_95f3dd5.pf_fragment +0 -0
- package/lib/learn-host/public/_pagefind/fragment/en_96d7a02.pf_fragment +0 -0
- package/lib/learn-host/public/_pagefind/fragment/en_971f951.pf_fragment +0 -0
- package/lib/learn-host/public/_pagefind/fragment/en_a446c32.pf_fragment +0 -0
- package/lib/learn-host/public/_pagefind/fragment/en_a5ee367.pf_fragment +0 -0
- package/lib/learn-host/public/_pagefind/fragment/en_b11c248.pf_fragment +0 -0
- package/lib/learn-host/public/_pagefind/fragment/en_b13c52e.pf_fragment +0 -0
- package/lib/learn-host/public/_pagefind/fragment/en_b5bd69b.pf_fragment +0 -0
- package/lib/learn-host/public/_pagefind/fragment/en_b625d7d.pf_fragment +0 -0
- package/lib/learn-host/public/_pagefind/fragment/en_bf63915.pf_fragment +0 -0
- package/lib/learn-host/public/_pagefind/fragment/en_c52b25b.pf_fragment +0 -0
- package/lib/learn-host/public/_pagefind/fragment/en_c9db556.pf_fragment +0 -0
- package/lib/learn-host/public/_pagefind/fragment/en_d1537ee.pf_fragment +0 -0
- package/lib/learn-host/public/_pagefind/fragment/en_d2e6412.pf_fragment +0 -0
- package/lib/learn-host/public/_pagefind/fragment/en_d2f47a4.pf_fragment +0 -0
- package/lib/learn-host/public/_pagefind/fragment/en_d361292.pf_fragment +0 -0
- package/lib/learn-host/public/_pagefind/fragment/en_d727ec8.pf_fragment +0 -0
- package/lib/learn-host/public/_pagefind/fragment/en_e11cd8f.pf_fragment +0 -0
- package/lib/learn-host/public/_pagefind/fragment/en_e481f19.pf_fragment +0 -0
- package/lib/learn-host/public/_pagefind/fragment/en_eee2805.pf_fragment +0 -0
- package/lib/learn-host/public/_pagefind/fragment/en_f4de6c4.pf_fragment +0 -0
- package/lib/learn-host/public/_pagefind/index/en_1ecb9d5.pf_index +0 -0
- package/lib/learn-host/public/_pagefind/index/en_37e362b.pf_index +0 -0
- package/lib/learn-host/public/_pagefind/index/en_538eee7.pf_index +0 -0
- package/lib/learn-host/public/_pagefind/index/en_5751dc8.pf_index +0 -0
- package/lib/learn-host/public/_pagefind/index/en_67f794d.pf_index +0 -0
- package/lib/learn-host/public/_pagefind/index/en_7458f81.pf_index +0 -0
- package/lib/learn-host/public/_pagefind/index/en_e21f7e1.pf_index +0 -0
- package/lib/learn-host/public/_pagefind/pagefind-entry.json +0 -1
- package/lib/learn-host/public/_pagefind/pagefind-highlight.js +0 -1064
- package/lib/learn-host/public/_pagefind/pagefind-modular-ui.css +0 -214
- package/lib/learn-host/public/_pagefind/pagefind-modular-ui.js +0 -8
- package/lib/learn-host/public/_pagefind/pagefind-ui.css +0 -1
- package/lib/learn-host/public/_pagefind/pagefind-ui.js +0 -2
- package/lib/learn-host/public/_pagefind/pagefind.en_104569cceb.pf_meta +0 -0
- package/lib/learn-host/public/_pagefind/pagefind.en_1075df6f16.pf_meta +0 -0
- package/lib/learn-host/public/_pagefind/pagefind.en_139f35f6e5.pf_meta +0 -0
- package/lib/learn-host/public/_pagefind/pagefind.en_46bfc9f7e1.pf_meta +0 -0
- package/lib/learn-host/public/_pagefind/pagefind.en_76b8937bbc.pf_meta +0 -0
- package/lib/learn-host/public/_pagefind/pagefind.en_83cbfb0fd5.pf_meta +0 -0
- package/lib/learn-host/public/_pagefind/pagefind.en_b1d168d536.pf_meta +0 -0
- package/lib/learn-host/public/_pagefind/pagefind.js +0 -6
- package/lib/learn-host/public/_pagefind/wasm.en.pagefind +0 -0
- package/lib/learn-host/public/_pagefind/wasm.unknown.pagefind +0 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# coding-friend-learn-host
|
|
2
|
+
|
|
3
|
+
Next.js app that renders your `/cf-learn` docs as a browsable website with search, categories, and dark mode.
|
|
4
|
+
|
|
5
|
+
## Usage (via CLI)
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
cf host # serves docs/learn/ on port 3333
|
|
9
|
+
cf host ./my-docs # serves a custom directory
|
|
10
|
+
cf host -p 4000 # custom port
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
The CLI handles deps install, build, and serving automatically.
|
|
14
|
+
|
|
15
|
+
## Local Development
|
|
16
|
+
|
|
17
|
+
Run the app directly without the CLI — useful when working on the UI itself.
|
|
18
|
+
|
|
19
|
+
### 1. Install dependencies
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
cd cli/lib/learn-host
|
|
23
|
+
npm install
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### 2. Point to a docs directory
|
|
27
|
+
|
|
28
|
+
The app resolves docs via (in order):
|
|
29
|
+
|
|
30
|
+
1. `DOCS_DIR` env var
|
|
31
|
+
2. Local `.coding-friend/config.json` → `learn.outputDir`
|
|
32
|
+
3. Global `~/.coding-friend/config.json` → `learn.outputDir`
|
|
33
|
+
4. Default: `docs/learn/` relative to project root
|
|
34
|
+
|
|
35
|
+
For local dev, set `DOCS_DIR` to any directory with the expected structure:
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
docs/
|
|
39
|
+
└── learn/
|
|
40
|
+
├── category-one/
|
|
41
|
+
│ ├── my-doc.md
|
|
42
|
+
│ └── another-doc.md
|
|
43
|
+
└── category-two/
|
|
44
|
+
└── some-doc.md
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Each `.md` file should have frontmatter:
|
|
48
|
+
|
|
49
|
+
```md
|
|
50
|
+
---
|
|
51
|
+
title: My Doc Title
|
|
52
|
+
category: category-one
|
|
53
|
+
tags: [typescript, patterns]
|
|
54
|
+
created: 2025-01-01
|
|
55
|
+
updated: 2025-01-15
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
Content here...
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### 3. Run dev server
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# Point to this repo's own learn docs (if they exist)
|
|
65
|
+
DOCS_DIR=../../../docs/learn npm run dev
|
|
66
|
+
|
|
67
|
+
# Or point to any other project's docs
|
|
68
|
+
DOCS_DIR=/path/to/your/project/docs/learn npm run dev
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
App runs at `http://localhost:3333`.
|
|
72
|
+
|
|
73
|
+
> **Note:** `npm run dev` does not rebuild the Pagefind search index. If you've previously run `npm run build`, search will still work but uses the old index — new or edited docs won't appear in search results until you build again.
|
|
74
|
+
|
|
75
|
+
### 4. Full build (with search)
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
DOCS_DIR=/path/to/docs npm run build
|
|
79
|
+
npx next start -p 3333
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
`postbuild` runs `pagefind` to index docs for full-text search.
|
|
83
|
+
|
|
84
|
+
## Structure
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
src/
|
|
88
|
+
├── app/
|
|
89
|
+
│ ├── page.tsx # Homepage: recent docs, categories, tags
|
|
90
|
+
│ ├── [category]/page.tsx # Category listing
|
|
91
|
+
│ ├── [category]/[slug]/page.tsx # Individual doc
|
|
92
|
+
│ └── layout.tsx
|
|
93
|
+
├── components/
|
|
94
|
+
│ ├── MarkdownRenderer.tsx # Renders .md with syntax highlighting
|
|
95
|
+
│ ├── TableOfContents.tsx # Auto-generated from headings
|
|
96
|
+
│ ├── Sidebar.tsx # Category navigation
|
|
97
|
+
│ ├── PagefindSearch.tsx # Full-text search (build-time index)
|
|
98
|
+
│ └── ThemeToggle.tsx
|
|
99
|
+
└── lib/
|
|
100
|
+
├── docs.ts # getAllDocs, getDocBySlug, etc.
|
|
101
|
+
└── types.ts
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## How It Fits Together
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
cf host [path]
|
|
108
|
+
└─ resolves docs dir
|
|
109
|
+
└─ npm install (one-time)
|
|
110
|
+
└─ npm run build (with DOCS_DIR env)
|
|
111
|
+
└─ npx next start -p 3333 (with DOCS_DIR env)
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
ISR (Incremental Static Regeneration) is enabled, so new or edited docs appear on the next page refresh without a rebuild.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="next" />
|
|
2
2
|
/// <reference types="next/image-types/global" />
|
|
3
|
-
import "./.next/types/routes.d.ts";
|
|
3
|
+
import "./.next/dev/types/routes.d.ts";
|
|
4
4
|
|
|
5
5
|
// NOTE: This file should not be edited
|
|
6
6
|
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="512" height="512" x="0" y="0" viewBox="0 0 64 64" style="enable-background:new 0 0 512 512" xml:space="preserve" class=""><g><linearGradient id="a" x1="78.644" x2="25.425" y1="74.123" y2="11.863" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="512" height="512" x="0" y="0" viewBox="0 0 64 64" style="enable-background:new 0 0 512 512" xml:space="preserve" class=""><g><linearGradient id="a" x1="78.644" x2="25.425" y1="74.123" y2="11.863" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#b45309"></stop><stop offset="1" stop-color="#f59e0b"></stop></linearGradient><path fill="url(#a)" fill-rule="evenodd" d="M2 14C2 7.373 7.373 2 14 2h36c6.627 0 12 5.373 12 12v28c0 6.627-5.373 12-12 12H39.908l-6.403 7.317a2 2 0 0 1-3.01 0L24.093 54H14C7.373 54 2 48.627 2 42z" clip-rule="evenodd" opacity="1" data-original="url(#a)" class=""></path><path fill="#ffffff" d="M32 14a2 2 0 0 1 1.95 1.556l1.107 4.867a6 6 0 0 0 4.52 4.52l4.867 1.107a2 2 0 0 1 0 3.9l-4.867 1.107a6 6 0 0 0-4.52 4.52l-1.107 4.866a2 2 0 0 1-3.9 0l-1.107-4.866a6 6 0 0 0-4.52-4.52l-4.866-1.107a2 2 0 0 1 0-3.9l4.866-1.107a6 6 0 0 0 4.52-4.52l1.107-4.866A2 2 0 0 1 32 14z"></path></g></svg>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="512" height="512" x="0" y="0" viewBox="0 0 64 64" style="enable-background:new 0 0 512 512" xml:space="preserve" class=""><g><linearGradient id="a" x1="78.644" x2="25.425" y1="74.123" y2="11.863" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="512" height="512" x="0" y="0" viewBox="0 0 64 64" style="enable-background:new 0 0 512 512" xml:space="preserve" class=""><g><linearGradient id="a" x1="78.644" x2="25.425" y1="74.123" y2="11.863" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#b45309"></stop><stop offset="1" stop-color="#f59e0b"></stop></linearGradient><path fill="url(#a)" fill-rule="evenodd" d="M2 14C2 7.373 7.373 2 14 2h36c6.627 0 12 5.373 12 12v28c0 6.627-5.373 12-12 12H39.908l-6.403 7.317a2 2 0 0 1-3.01 0L24.093 54H14C7.373 54 2 48.627 2 42z" clip-rule="evenodd" opacity="1" data-original="url(#a)" class=""></path><path fill="#ffffff" d="M32 14a2 2 0 0 1 1.95 1.556l1.107 4.867a6 6 0 0 0 4.52 4.52l4.867 1.107a2 2 0 0 1 0 3.9l-4.867 1.107a6 6 0 0 0-4.52 4.52l-1.107 4.866a2 2 0 0 1-3.9 0l-1.107-4.866a6 6 0 0 0-4.52-4.52l-4.866-1.107a2 2 0 0 1 0-3.9l4.866-1.107a6 6 0 0 0 4.52-4.52l1.107-4.866A2 2 0 0 1 32 14z"></path></g></svg>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="512" height="512" x="0" y="0" viewBox="0 0 64 64" style="enable-background:new 0 0 512 512" xml:space="preserve" class=""><g><linearGradient id="a" x1="78.644" x2="25.425" y1="74.123" y2="11.863" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="512" height="512" x="0" y="0" viewBox="0 0 64 64" style="enable-background:new 0 0 512 512" xml:space="preserve" class=""><g><linearGradient id="a" x1="78.644" x2="25.425" y1="74.123" y2="11.863" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#b45309"></stop><stop offset="1" stop-color="#f59e0b"></stop></linearGradient><path fill="url(#a)" fill-rule="evenodd" d="M2 14C2 7.373 7.373 2 14 2h36c6.627 0 12 5.373 12 12v28c0 6.627-5.373 12-12 12H39.908l-6.403 7.317a2 2 0 0 1-3.01 0L24.093 54H14C7.373 54 2 48.627 2 42z" clip-rule="evenodd" opacity="1" data-original="url(#a)" class=""></path><path fill="#ffffff" d="M32 14a2 2 0 0 1 1.95 1.556l1.107 4.867a6 6 0 0 0 4.52 4.52l4.867 1.107a2 2 0 0 1 0 3.9l-4.867 1.107a6 6 0 0 0-4.52 4.52l-1.107 4.866a2 2 0 0 1-3.9 0l-1.107-4.866a6 6 0 0 0-4.52-4.52l-4.866-1.107a2 2 0 0 1 0-3.9l4.866-1.107a6 6 0 0 0 4.52-4.52l1.107-4.866A2 2 0 0 1 32 14z"></path></g></svg>
|
|
@@ -30,7 +30,7 @@ export default function Sidebar({
|
|
|
30
30
|
}`}
|
|
31
31
|
>
|
|
32
32
|
<span>{cat.name.replace(/[_-]/g, " ")}</span>
|
|
33
|
-
<span className="dark:bg-navy-800 rounded-full bg-slate-200 px-1.5 py-0.5 text-xs text-slate-500 dark:
|
|
33
|
+
<span className="dark:bg-navy-800 rounded-full border border-slate-200 bg-slate-200 px-1.5 py-0.5 text-xs text-slate-500 dark:border-[#a0a0a01c] dark:text-slate-400">
|
|
34
34
|
{cat.docCount}
|
|
35
35
|
</span>
|
|
36
36
|
</Link>
|
|
@@ -53,8 +53,8 @@ function findProjectRoot(from: string): string {
|
|
|
53
53
|
}
|
|
54
54
|
dir = path.dirname(dir);
|
|
55
55
|
}
|
|
56
|
-
// Fallback: assume learn-host is at <root>/lib/learn-host
|
|
57
|
-
return path.resolve(from, "
|
|
56
|
+
// Fallback: assume learn-host is at <root>/cli/lib/learn-host
|
|
57
|
+
return path.resolve(from, "../../..");
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
function resolvePath(p: string, base: string): string {
|
|
@@ -0,0 +1,169 @@
|
|
|
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
|
+
## Docs Directory Structure
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
docs/
|
|
100
|
+
└── learn/
|
|
101
|
+
├── category-one/
|
|
102
|
+
│ ├── my-doc.md
|
|
103
|
+
│ └── another-doc.md
|
|
104
|
+
└── category-two/
|
|
105
|
+
└── some-doc.md
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Each `.md` file needs frontmatter:
|
|
109
|
+
|
|
110
|
+
```md
|
|
111
|
+
---
|
|
112
|
+
title: My Doc Title
|
|
113
|
+
category: category-one
|
|
114
|
+
tags: [typescript, patterns]
|
|
115
|
+
created: 2025-01-01
|
|
116
|
+
updated: 2025-01-15
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
Content here...
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Available Tools
|
|
123
|
+
|
|
124
|
+
| Tool | Type | Description |
|
|
125
|
+
| ----------------- | ----- | ------------------------------------------------ |
|
|
126
|
+
| `list-categories` | Read | List all doc categories |
|
|
127
|
+
| `list-docs` | Read | List docs (optionally filter by category or tag) |
|
|
128
|
+
| `read-doc` | Read | Read a specific doc by category + slug |
|
|
129
|
+
| `search-docs` | Read | Full-text search across all docs |
|
|
130
|
+
| `get-review-list` | Read | Get docs needing review |
|
|
131
|
+
| `create-doc` | Write | Create a new doc with frontmatter |
|
|
132
|
+
| `update-doc` | Write | Append content or update tags on an existing doc |
|
|
133
|
+
| `improve-doc` | Write | Replace doc content while preserving frontmatter |
|
|
134
|
+
| `track-knowledge` | Write | Mark a doc as remembered / needs-review / new |
|
|
135
|
+
|
|
136
|
+
## Structure
|
|
137
|
+
|
|
138
|
+
```
|
|
139
|
+
src/
|
|
140
|
+
├── index.ts # Entry: parses docs dir, starts MCP server
|
|
141
|
+
├── server.ts # Registers all tools
|
|
142
|
+
├── bin/
|
|
143
|
+
│ └── learn-mcp.ts # CLI binary entry
|
|
144
|
+
├── tools/ # One file per MCP tool
|
|
145
|
+
│ ├── list-categories.ts
|
|
146
|
+
│ ├── list-docs.ts
|
|
147
|
+
│ ├── read-doc.ts
|
|
148
|
+
│ ├── search-docs.ts
|
|
149
|
+
│ ├── create-doc.ts
|
|
150
|
+
│ ├── update-doc.ts
|
|
151
|
+
│ ├── improve-doc.ts
|
|
152
|
+
│ ├── track-knowledge.ts
|
|
153
|
+
│ └── get-review-list.ts
|
|
154
|
+
└── lib/
|
|
155
|
+
├── docs.ts # Shared doc utilities (read, write, search)
|
|
156
|
+
├── types.ts # TypeScript interfaces
|
|
157
|
+
└── knowledge.ts # Knowledge tracking state
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## How It Fits Together
|
|
161
|
+
|
|
162
|
+
```
|
|
163
|
+
cf mcp [path]
|
|
164
|
+
└─ resolves docs dir
|
|
165
|
+
└─ npm install + build (one-time)
|
|
166
|
+
└─ prints MCP config to add to Claude
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Once configured, Claude can call these tools directly to read and write your learning notes without leaving the conversation.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "coding-friend-learn-mcp",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"private": true,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
"scripts": {
|
|
10
10
|
"build": "tsc",
|
|
11
11
|
"dev": "tsx src/index.ts",
|
|
12
|
+
"dev:watch": "tsc --watch --preserveWatchOutput",
|
|
12
13
|
"start": "node dist/index.js"
|
|
13
14
|
},
|
|
14
15
|
"dependencies": {
|
|
@@ -181,9 +181,7 @@ export function updateDoc(
|
|
|
181
181
|
const today = new Date().toISOString().split("T")[0];
|
|
182
182
|
|
|
183
183
|
if (updates.tags) {
|
|
184
|
-
raw.data.tags = [
|
|
185
|
-
...new Set([...(raw.data.tags || []), ...updates.tags]),
|
|
186
|
-
];
|
|
184
|
+
raw.data.tags = [...new Set([...(raw.data.tags || []), ...updates.tags])];
|
|
187
185
|
}
|
|
188
186
|
if (updates.title) {
|
|
189
187
|
raw.data.title = updates.title;
|
|
@@ -71,7 +71,8 @@ export function getReviewList(
|
|
|
71
71
|
lastReviewed: null,
|
|
72
72
|
reviewCount: 0,
|
|
73
73
|
notes: "",
|
|
74
|
-
firstSeen:
|
|
74
|
+
firstSeen:
|
|
75
|
+
doc.frontmatter.created || new Date().toISOString().split("T")[0]!,
|
|
75
76
|
};
|
|
76
77
|
|
|
77
78
|
if (statusFilter && entry.status !== statusFilter) continue;
|
|
@@ -14,10 +14,7 @@ export function registerGetReviewList(
|
|
|
14
14
|
.enum(["needs-review", "new"])
|
|
15
15
|
.optional()
|
|
16
16
|
.describe("Filter by specific status"),
|
|
17
|
-
limit: z
|
|
18
|
-
.number()
|
|
19
|
-
.optional()
|
|
20
|
-
.describe("Max number of results to return"),
|
|
17
|
+
limit: z.number().optional().describe("Max number of results to return"),
|
|
21
18
|
},
|
|
22
19
|
async ({ status, limit }) => {
|
|
23
20
|
const results = getReviewList(docsDir, status, limit);
|
|
@@ -8,10 +8,7 @@ export function registerSearchDocs(server: McpServer, docsDir: string): void {
|
|
|
8
8
|
"Full-text search across all learning docs. Searches titles, tags, and content. Optionally filter by category.",
|
|
9
9
|
{
|
|
10
10
|
query: z.string().describe("Search query text"),
|
|
11
|
-
category: z
|
|
12
|
-
.string()
|
|
13
|
-
.optional()
|
|
14
|
-
.describe("Limit search to this category"),
|
|
11
|
+
category: z.string().optional().describe("Limit search to this category"),
|
|
15
12
|
},
|
|
16
13
|
async ({ query, category }) => {
|
|
17
14
|
const results = searchDocs(docsDir, query, category);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "coding-friend-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "CLI for coding-friend — host learning docs, setup MCP server, initialize projects",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"scripts": {
|
|
10
10
|
"build": "tsup src/index.ts src/postinstall.ts --format esm --dts --clean",
|
|
11
11
|
"postinstall": "test -f dist/postinstall.js && node dist/postinstall.js || true",
|
|
12
|
-
"prepublishOnly": "npm run build
|
|
12
|
+
"prepublishOnly": "npm run build",
|
|
13
13
|
"dev": "tsx src/index.ts",
|
|
14
14
|
"watch": "tsup src/index.ts src/postinstall.ts --format esm --dts --watch",
|
|
15
15
|
"test": "vitest run",
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":"1.4.0","languages":{"en":{"hash":"en_46bfc9f7e1","wasm":"en","page_count":14}},"include_characters":["_","‿","⁀","⁔","︳","︴","﹍","﹎","﹏","_"]}
|