knowy-cli 0.1.2
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 +138 -0
- package/README.zh-TW.md +138 -0
- package/bin/knowy-mcp.js +3 -0
- package/bin/knowy.js +3 -0
- package/package.json +35 -0
- package/skills/knowy-init/SKILL.md +134 -0
- package/skills/knowy-judge/SKILL.md +272 -0
- package/skills/knowy-next/SKILL.md +128 -0
- package/skills/knowy-update/SKILL.md +142 -0
- package/src/adapters/detect.js +38 -0
- package/src/adapters/handshake.js +93 -0
- package/src/adapters/registry.js +276 -0
- package/src/cli.js +58 -0
- package/src/commands/init.js +130 -0
- package/src/commands/setup-mcp.js +87 -0
- package/src/commands/update.js +90 -0
- package/src/constants.js +23 -0
- package/src/i18n.js +172 -0
- package/src/mcp-server.js +471 -0
- package/src/scaffold.js +53 -0
- package/src/skills.js +23 -0
- package/src/templates.js +29 -0
- package/src/ui.js +87 -0
- package/templates/en/experience.md.tmpl +47 -0
- package/templates/en/principles.md.tmpl +42 -0
- package/templates/en/vision.md.tmpl +76 -0
- package/templates/zh-TW/experience.md.tmpl +45 -0
- package/templates/zh-TW/principles.md.tmpl +41 -0
- package/templates/zh-TW/vision.md.tmpl +75 -0
package/src/skills.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { readdir, copyFile, mkdir } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { SKILLS_SOURCE, SKILLS_TARGET, SKILL_NAMES } from './constants.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Install Claude Code skills into the project.
|
|
7
|
+
* Always overwrites (managed files).
|
|
8
|
+
*/
|
|
9
|
+
export async function installSkills(projectRoot) {
|
|
10
|
+
const installed = [];
|
|
11
|
+
|
|
12
|
+
for (const name of SKILL_NAMES) {
|
|
13
|
+
const srcDir = join(SKILLS_SOURCE, name);
|
|
14
|
+
const destDir = join(projectRoot, SKILLS_TARGET, name);
|
|
15
|
+
await mkdir(destDir, { recursive: true });
|
|
16
|
+
|
|
17
|
+
const skillFile = 'SKILL.md';
|
|
18
|
+
await copyFile(join(srcDir, skillFile), join(destDir, skillFile));
|
|
19
|
+
installed.push(name);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return installed;
|
|
23
|
+
}
|
package/src/templates.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { readdir, copyFile, mkdir, access } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { KNOWLEDGE_DIR, TEMPLATES_DIR, PACKAGE_ROOT } from './constants.js';
|
|
4
|
+
|
|
5
|
+
async function exists(p) {
|
|
6
|
+
try { await access(p); return true; } catch { return false; }
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export async function installTemplates(projectRoot, language = 'en') {
|
|
10
|
+
const destDir = join(projectRoot, KNOWLEDGE_DIR, TEMPLATES_DIR);
|
|
11
|
+
await mkdir(destDir, { recursive: true });
|
|
12
|
+
|
|
13
|
+
const installed = [];
|
|
14
|
+
|
|
15
|
+
// Install language-specific templates, fallback to English
|
|
16
|
+
let srcDir = join(PACKAGE_ROOT, 'templates', language);
|
|
17
|
+
if (!await exists(srcDir)) {
|
|
18
|
+
srcDir = join(PACKAGE_ROOT, 'templates', 'en');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const files = await readdir(srcDir);
|
|
22
|
+
for (const file of files) {
|
|
23
|
+
if (!file.endsWith('.tmpl')) continue;
|
|
24
|
+
await copyFile(join(srcDir, file), join(destDir, file));
|
|
25
|
+
installed.push(file);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return installed;
|
|
29
|
+
}
|
package/src/ui.js
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { createInterface } from 'node:readline';
|
|
2
|
+
import { t } from './i18n.js';
|
|
3
|
+
|
|
4
|
+
function createRL() {
|
|
5
|
+
return createInterface({
|
|
6
|
+
input: process.stdin,
|
|
7
|
+
output: process.stdout,
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function question(rl, prompt) {
|
|
12
|
+
return new Promise(resolve => rl.question(prompt, resolve));
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Ask a yes/no question. Returns true for yes.
|
|
17
|
+
*/
|
|
18
|
+
export async function confirm(message, defaultYes = true) {
|
|
19
|
+
const rl = createRL();
|
|
20
|
+
const hint = defaultYes ? '(Y/n)' : '(y/N)';
|
|
21
|
+
const answer = await question(rl, `${message} ${hint} `);
|
|
22
|
+
rl.close();
|
|
23
|
+
const a = answer.trim().toLowerCase();
|
|
24
|
+
if (a === '') return defaultYes;
|
|
25
|
+
return a === 'y' || a === 'yes';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Multi-select from a list of choices.
|
|
30
|
+
* choices: [{ id, name, checked }]
|
|
31
|
+
* Returns array of selected ids.
|
|
32
|
+
*/
|
|
33
|
+
export async function multiSelect(message, choices, lang = 'en') {
|
|
34
|
+
const rl = createRL();
|
|
35
|
+
const selected = new Set(choices.filter(c => c.checked).map(c => c.id));
|
|
36
|
+
|
|
37
|
+
console.log(`\n${message}`);
|
|
38
|
+
|
|
39
|
+
for (let i = 0; i < choices.length; i++) {
|
|
40
|
+
const mark = selected.has(choices[i].id) ? '◉' : '◯';
|
|
41
|
+
console.log(` ${mark} ${i + 1}. ${choices[i].name}`);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const togglePrompt = t(lang, 'ui.toggle');
|
|
45
|
+
const answer = await question(rl, `\n${togglePrompt}`);
|
|
46
|
+
rl.close();
|
|
47
|
+
|
|
48
|
+
const input = answer.trim();
|
|
49
|
+
if (input === '') return [...selected];
|
|
50
|
+
|
|
51
|
+
const nums = input.split(/[,\s]+/).map(Number).filter(n => !isNaN(n));
|
|
52
|
+
for (const n of nums) {
|
|
53
|
+
const idx = n - 1;
|
|
54
|
+
if (idx >= 0 && idx < choices.length) {
|
|
55
|
+
const id = choices[idx].id;
|
|
56
|
+
if (selected.has(id)) selected.delete(id);
|
|
57
|
+
else selected.add(id);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return [...selected];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Single-select from a list of choices. Returns selected id.
|
|
66
|
+
*/
|
|
67
|
+
export async function select(message, choices) {
|
|
68
|
+
const rl = createRL();
|
|
69
|
+
|
|
70
|
+
console.log(`\n${message}`);
|
|
71
|
+
for (let i = 0; i < choices.length; i++) {
|
|
72
|
+
const marker = choices[i].checked ? '→' : ' ';
|
|
73
|
+
console.log(` ${marker} ${i + 1}. ${choices[i].name}`);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const answer = await question(rl, `\n> `);
|
|
77
|
+
rl.close();
|
|
78
|
+
|
|
79
|
+
const num = parseInt(answer.trim(), 10);
|
|
80
|
+
if (num >= 1 && num <= choices.length) {
|
|
81
|
+
return choices[num - 1].id;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Default to checked item or first item
|
|
85
|
+
const defaultChoice = choices.find(c => c.checked) || choices[0];
|
|
86
|
+
return defaultChoice.id;
|
|
87
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Experience
|
|
2
|
+
|
|
3
|
+
<!--
|
|
4
|
+
This file captures distilled lessons from development — not a changelog,
|
|
5
|
+
but patterns that should influence future decisions.
|
|
6
|
+
|
|
7
|
+
Each lesson records the gap between theory and reality.
|
|
8
|
+
Keep entries short and actionable. Detailed event records belong in
|
|
9
|
+
.knowledge/history/.
|
|
10
|
+
-->
|
|
11
|
+
|
|
12
|
+
## Lessons
|
|
13
|
+
|
|
14
|
+
<!--
|
|
15
|
+
Add a new section for each significant lesson. Use the four-part format:
|
|
16
|
+
1. What theory/expectation said
|
|
17
|
+
2. What actually happened
|
|
18
|
+
3. How you resolved it
|
|
19
|
+
4. The distilled lesson
|
|
20
|
+
|
|
21
|
+
This format forces you to articulate *why* something was surprising,
|
|
22
|
+
not just *what* happened.
|
|
23
|
+
-->
|
|
24
|
+
|
|
25
|
+
### [Lesson Title]
|
|
26
|
+
|
|
27
|
+
- **Theory said**: [What you expected based on design, principles, or assumptions]
|
|
28
|
+
- **Actually happened**: [What really occurred — be specific]
|
|
29
|
+
- **Resolved by**: [How the gap was bridged — the fix, workaround, or insight]
|
|
30
|
+
- **Lesson**: [One-sentence reusable pattern for next time]
|
|
31
|
+
- **Source**: [Link to history/ entry or PR/commit, if available]
|
|
32
|
+
|
|
33
|
+
<!--
|
|
34
|
+
Example:
|
|
35
|
+
|
|
36
|
+
### Verify before reimplementing
|
|
37
|
+
|
|
38
|
+
- **Theory said**: The core module only handles evaluation, so we need
|
|
39
|
+
to build a type checker from scratch.
|
|
40
|
+
- **Actually happened**: After two days of building, discovered the core
|
|
41
|
+
module already included full type checking — it just wasn't documented.
|
|
42
|
+
- **Resolved by**: Deleted the duplicate implementation and documented
|
|
43
|
+
the existing one.
|
|
44
|
+
- **Lesson**: Always search existing code before building. The answer
|
|
45
|
+
may already be there, undocumented.
|
|
46
|
+
- **Source**: history/010-duplicate-checker.md
|
|
47
|
+
-->
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Principles
|
|
2
|
+
|
|
3
|
+
<!--
|
|
4
|
+
This file captures the core beliefs and rules that guide your project.
|
|
5
|
+
Start with a root axiom — the single non-negotiable truth — then derive
|
|
6
|
+
specific principles from it.
|
|
7
|
+
|
|
8
|
+
Principles should rarely change. If you find yourself editing this file
|
|
9
|
+
often, the entries might be decisions (which belong in design/) rather
|
|
10
|
+
than principles.
|
|
11
|
+
-->
|
|
12
|
+
|
|
13
|
+
## Root Axiom
|
|
14
|
+
|
|
15
|
+
<!--
|
|
16
|
+
What is the one fundamental belief behind this project?
|
|
17
|
+
Example: "User data belongs to the user, not the platform."
|
|
18
|
+
Example: "Programs are semantic structures — code is just one projection."
|
|
19
|
+
-->
|
|
20
|
+
|
|
21
|
+
## Derived Principles
|
|
22
|
+
|
|
23
|
+
<!--
|
|
24
|
+
Each principle should trace back to the root axiom or another principle.
|
|
25
|
+
Explain what it means in practice so your team (and your AI) can apply it.
|
|
26
|
+
-->
|
|
27
|
+
|
|
28
|
+
### 1. [Principle Name]
|
|
29
|
+
|
|
30
|
+
<!--
|
|
31
|
+
Derived from: [Root Axiom / another principle]
|
|
32
|
+
What it means: ...
|
|
33
|
+
How to apply: ...
|
|
34
|
+
-->
|
|
35
|
+
|
|
36
|
+
### 2. [Principle Name]
|
|
37
|
+
|
|
38
|
+
<!--
|
|
39
|
+
Derived from: ...
|
|
40
|
+
What it means: ...
|
|
41
|
+
How to apply: ...
|
|
42
|
+
-->
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Vision
|
|
2
|
+
|
|
3
|
+
<!--
|
|
4
|
+
This file describes where your project is going. It evolves as your
|
|
5
|
+
understanding deepens. Update it after each milestone or when priorities
|
|
6
|
+
shift.
|
|
7
|
+
-->
|
|
8
|
+
|
|
9
|
+
## Problem Statement
|
|
10
|
+
|
|
11
|
+
<!--
|
|
12
|
+
What problem does this project solve? Who has this problem?
|
|
13
|
+
Why do existing solutions fall short?
|
|
14
|
+
-->
|
|
15
|
+
|
|
16
|
+
## Core Idea
|
|
17
|
+
|
|
18
|
+
<!--
|
|
19
|
+
Your solution in one or two sentences.
|
|
20
|
+
Example: "A single semantic tree that projects into code, blocks, and
|
|
21
|
+
flowcharts — edit any view, all stay in sync."
|
|
22
|
+
-->
|
|
23
|
+
|
|
24
|
+
## Current State
|
|
25
|
+
|
|
26
|
+
<!--
|
|
27
|
+
Where is the project right now? What works and what doesn't?
|
|
28
|
+
Be honest — this helps your AI give realistic suggestions.
|
|
29
|
+
-->
|
|
30
|
+
|
|
31
|
+
## Architecture
|
|
32
|
+
|
|
33
|
+
<!--
|
|
34
|
+
Key technical decisions and why they were made.
|
|
35
|
+
Link to .knowledge/design/ for detailed design documents.
|
|
36
|
+
-->
|
|
37
|
+
|
|
38
|
+
## Roadmap
|
|
39
|
+
|
|
40
|
+
<!--
|
|
41
|
+
Milestones in order. Use checkboxes to track completion status.
|
|
42
|
+
For each milestone:
|
|
43
|
+
- Name + checkbox ([ ] pending, [x] complete)
|
|
44
|
+
- What it delivers
|
|
45
|
+
- Prerequisites (which milestones must be done first)
|
|
46
|
+
- Success criteria (concrete, verifiable)
|
|
47
|
+
|
|
48
|
+
Update checkboxes as milestones are completed. /knowy judge will
|
|
49
|
+
verify that checked items match the actual project state.
|
|
50
|
+
-->
|
|
51
|
+
|
|
52
|
+
### Phase 1: [Name]
|
|
53
|
+
|
|
54
|
+
- [ ] Complete
|
|
55
|
+
|
|
56
|
+
<!--
|
|
57
|
+
Delivers: ...
|
|
58
|
+
Prerequisites: none
|
|
59
|
+
-->
|
|
60
|
+
|
|
61
|
+
**Success criteria:**
|
|
62
|
+
- [ ] [Concrete criterion 1]
|
|
63
|
+
- [ ] [Concrete criterion 2]
|
|
64
|
+
|
|
65
|
+
### Phase 2: [Name]
|
|
66
|
+
|
|
67
|
+
- [ ] Complete
|
|
68
|
+
|
|
69
|
+
<!--
|
|
70
|
+
Delivers: ...
|
|
71
|
+
Prerequisites: Phase 1
|
|
72
|
+
-->
|
|
73
|
+
|
|
74
|
+
**Success criteria:**
|
|
75
|
+
- [ ] [Concrete criterion 1]
|
|
76
|
+
- [ ] [Concrete criterion 2]
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# 經驗
|
|
2
|
+
|
|
3
|
+
<!--
|
|
4
|
+
這份文件記錄從開發過程中蒸餾出的教訓——不是 changelog,
|
|
5
|
+
而是應該影響未來決策的模式。
|
|
6
|
+
|
|
7
|
+
每個教訓記錄「理論」和「現實」之間的落差。
|
|
8
|
+
保持簡短、可操作。詳細的事件記錄放在 .knowledge/history/。
|
|
9
|
+
-->
|
|
10
|
+
|
|
11
|
+
## 教訓
|
|
12
|
+
|
|
13
|
+
<!--
|
|
14
|
+
每個重要的教訓加一個小節,使用四段式格式:
|
|
15
|
+
1. 理論/預期怎麼說
|
|
16
|
+
2. 實際發生了什麼
|
|
17
|
+
3. 如何解決
|
|
18
|
+
4. 蒸餾出的教訓
|
|
19
|
+
|
|
20
|
+
這個格式迫使你清楚說明「為什麼」令人意外,
|
|
21
|
+
而不只是「發生了什麼」。
|
|
22
|
+
-->
|
|
23
|
+
|
|
24
|
+
### [教訓標題]
|
|
25
|
+
|
|
26
|
+
- **理論說**:[基於設計、原則或假設,你預期會發生什麼]
|
|
27
|
+
- **實際發生**:[真正發生了什麼——要具體]
|
|
28
|
+
- **解決方式**:[如何彌合落差——修復、替代方案或洞察]
|
|
29
|
+
- **教訓**:[一句話的可複用模式]
|
|
30
|
+
- **來源**:[history/ 中的記錄或 PR/commit 連結]
|
|
31
|
+
|
|
32
|
+
<!--
|
|
33
|
+
範例:
|
|
34
|
+
|
|
35
|
+
### 實作前先確認功能是否已存在
|
|
36
|
+
|
|
37
|
+
- **理論說**:核心模組只處理求值,所以我們需要從頭建一個
|
|
38
|
+
type checker。
|
|
39
|
+
- **實際發生**:花了兩天在建,結果發現核心模組已經有完整的
|
|
40
|
+
型別檢查功能——只是沒有文件記錄。
|
|
41
|
+
- **解決方式**:刪除重複的實作,為既有功能補上文件。
|
|
42
|
+
- **教訓**:動手之前先搜尋既有程式碼。答案可能已經在那裡,
|
|
43
|
+
只是沒被記錄。
|
|
44
|
+
- **來源**:history/010-duplicate-checker.md
|
|
45
|
+
-->
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# 原則
|
|
2
|
+
|
|
3
|
+
<!--
|
|
4
|
+
這份文件記錄驅動你專案的核心信念和規則。
|
|
5
|
+
從一個根公理開始——那個唯一不可妥協的真理——
|
|
6
|
+
然後從中推導出具體的原則。
|
|
7
|
+
|
|
8
|
+
原則應該很少修改。如果你經常編輯這份文件,
|
|
9
|
+
那些內容可能是設計決策(應該放在 design/),而不是原則。
|
|
10
|
+
-->
|
|
11
|
+
|
|
12
|
+
## 根公理
|
|
13
|
+
|
|
14
|
+
<!--
|
|
15
|
+
這個專案背後最根本的信念是什麼?
|
|
16
|
+
範例:「使用者的資料屬於使用者,不屬於平台。」
|
|
17
|
+
範例:「程式是語義結構——程式碼只是其中一種投影。」
|
|
18
|
+
-->
|
|
19
|
+
|
|
20
|
+
## 衍生原則
|
|
21
|
+
|
|
22
|
+
<!--
|
|
23
|
+
每個原則都應該能追溯到根公理或另一個原則。
|
|
24
|
+
說明它在實務上代表什麼,讓團隊(和你的 AI)能夠應用它。
|
|
25
|
+
-->
|
|
26
|
+
|
|
27
|
+
### 1. [原則名稱]
|
|
28
|
+
|
|
29
|
+
<!--
|
|
30
|
+
推導自:[根公理 / 另一個原則]
|
|
31
|
+
意義:...
|
|
32
|
+
如何應用:...
|
|
33
|
+
-->
|
|
34
|
+
|
|
35
|
+
### 2. [原則名稱]
|
|
36
|
+
|
|
37
|
+
<!--
|
|
38
|
+
推導自:...
|
|
39
|
+
意義:...
|
|
40
|
+
如何應用:...
|
|
41
|
+
-->
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# 願景
|
|
2
|
+
|
|
3
|
+
<!--
|
|
4
|
+
這份文件描述你的專案要往哪裡走。它會隨著理解的加深而演進。
|
|
5
|
+
在每個里程碑完成後,或是優先順序改變時更新它。
|
|
6
|
+
-->
|
|
7
|
+
|
|
8
|
+
## 問題陳述
|
|
9
|
+
|
|
10
|
+
<!--
|
|
11
|
+
這個專案要解決什麼問題?誰有這個問題?
|
|
12
|
+
為什麼現有的方案不夠好?
|
|
13
|
+
-->
|
|
14
|
+
|
|
15
|
+
## 核心想法
|
|
16
|
+
|
|
17
|
+
<!--
|
|
18
|
+
用一兩句話描述你的解決方案。
|
|
19
|
+
範例:「一棵語義樹,可以投影成程式碼、積木和流程圖
|
|
20
|
+
——編輯任何視圖,全部保持同步。」
|
|
21
|
+
-->
|
|
22
|
+
|
|
23
|
+
## 現狀
|
|
24
|
+
|
|
25
|
+
<!--
|
|
26
|
+
專案目前在什麼狀態?什麼能用、什麼不能用?
|
|
27
|
+
誠實描述——這能幫助你的 AI 給出務實的建議。
|
|
28
|
+
-->
|
|
29
|
+
|
|
30
|
+
## 架構
|
|
31
|
+
|
|
32
|
+
<!--
|
|
33
|
+
關鍵的技術決策,以及為什麼這樣決定。
|
|
34
|
+
詳細的設計文件連結到 .knowledge/design/。
|
|
35
|
+
-->
|
|
36
|
+
|
|
37
|
+
## 路線圖
|
|
38
|
+
|
|
39
|
+
<!--
|
|
40
|
+
按順序列出里程碑。用勾選框追蹤完成狀態。
|
|
41
|
+
每個里程碑包含:
|
|
42
|
+
- 名稱 + 勾選框([ ] 待完成、[x] 已完成)
|
|
43
|
+
- 交付什麼
|
|
44
|
+
- 前置條件(哪些里程碑必須先完成)
|
|
45
|
+
- 成功標準(具體、可驗證)
|
|
46
|
+
|
|
47
|
+
完成里程碑時更新勾選框。/knowy judge 會驗證打勾的項目
|
|
48
|
+
是否與專案實際狀態一致。
|
|
49
|
+
-->
|
|
50
|
+
|
|
51
|
+
### 階段 1:[名稱]
|
|
52
|
+
|
|
53
|
+
- [ ] 完成
|
|
54
|
+
|
|
55
|
+
<!--
|
|
56
|
+
交付:...
|
|
57
|
+
前置條件:無
|
|
58
|
+
-->
|
|
59
|
+
|
|
60
|
+
**成功標準:**
|
|
61
|
+
- [ ] [具體標準 1]
|
|
62
|
+
- [ ] [具體標準 2]
|
|
63
|
+
|
|
64
|
+
### 階段 2:[名稱]
|
|
65
|
+
|
|
66
|
+
- [ ] 完成
|
|
67
|
+
|
|
68
|
+
<!--
|
|
69
|
+
交付:...
|
|
70
|
+
前置條件:階段 1
|
|
71
|
+
-->
|
|
72
|
+
|
|
73
|
+
**成功標準:**
|
|
74
|
+
- [ ] [具體標準 1]
|
|
75
|
+
- [ ] [具體標準 2]
|