learn-anything-cli 0.1.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/LICENSE +21 -0
- package/README.md +96 -0
- package/README.zh-CN.md +96 -0
- package/bin/learn-anything.js +3 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +88 -0
- package/dist/core/command-generation/adapters/claude.d.ts +3 -0
- package/dist/core/command-generation/adapters/claude.js +31 -0
- package/dist/core/command-generation/adapters/codex.d.ts +3 -0
- package/dist/core/command-generation/adapters/codex.js +26 -0
- package/dist/core/command-generation/adapters/cursor.d.ts +3 -0
- package/dist/core/command-generation/adapters/cursor.js +27 -0
- package/dist/core/command-generation/adapters/gemini.d.ts +3 -0
- package/dist/core/command-generation/adapters/gemini.js +23 -0
- package/dist/core/command-generation/adapters/index.d.ts +5 -0
- package/dist/core/command-generation/adapters/index.js +5 -0
- package/dist/core/command-generation/generator.d.ts +4 -0
- package/dist/core/command-generation/generator.js +10 -0
- package/dist/core/command-generation/index.d.ts +4 -0
- package/dist/core/command-generation/index.js +3 -0
- package/dist/core/command-generation/registry.d.ts +8 -0
- package/dist/core/command-generation/registry.js +20 -0
- package/dist/core/command-generation/types.d.ts +18 -0
- package/dist/core/command-generation/types.js +2 -0
- package/dist/core/config.d.ts +11 -0
- package/dist/core/config.js +33 -0
- package/dist/core/init.d.ts +22 -0
- package/dist/core/init.js +133 -0
- package/dist/core/shared/index.d.ts +3 -0
- package/dist/core/shared/index.js +2 -0
- package/dist/core/shared/skill-generation.d.ts +16 -0
- package/dist/core/shared/skill-generation.js +49 -0
- package/dist/core/templates/skill-templates.d.ts +7 -0
- package/dist/core/templates/skill-templates.js +6 -0
- package/dist/core/templates/types.d.ts +16 -0
- package/dist/core/templates/types.js +2 -0
- package/dist/core/templates/workflows/learn-explain.d.ts +4 -0
- package/dist/core/templates/workflows/learn-explain.js +203 -0
- package/dist/core/templates/workflows/learn-practice.d.ts +4 -0
- package/dist/core/templates/workflows/learn-practice.js +247 -0
- package/dist/core/templates/workflows/learn-review.d.ts +4 -0
- package/dist/core/templates/workflows/learn-review.js +167 -0
- package/dist/core/templates/workflows/learn-status.d.ts +4 -0
- package/dist/core/templates/workflows/learn-status.js +114 -0
- package/dist/core/templates/workflows/learn-topic.d.ts +4 -0
- package/dist/core/templates/workflows/learn-topic.js +191 -0
- package/dist/i18n/index.d.ts +6 -0
- package/dist/i18n/index.js +30 -0
- package/dist/i18n/locales/en.d.ts +3 -0
- package/dist/i18n/locales/en.js +28 -0
- package/dist/i18n/locales/zh-CN.d.ts +3 -0
- package/dist/i18n/locales/zh-CN.js +28 -0
- package/dist/i18n/types.d.ts +31 -0
- package/dist/i18n/types.js +2 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +4 -0
- package/dist/utils/file-system.d.ts +8 -0
- package/dist/utils/file-system.js +38 -0
- package/dist/utils/interactive.d.ts +2 -0
- package/dist/utils/interactive.js +4 -0
- package/package.json +69 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ChenChenyaqi
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Learn Anything
|
|
2
|
+
|
|
3
|
+
AI-powered recursive learning system — turns your AI coding assistant into an interactive tutor using the Socratic method and TDD-style exercises.
|
|
4
|
+
|
|
5
|
+
Generate skill and command files for **30+ AI tools** (Claude Code, Cursor, Gemini CLI, Codex, Copilot, Windsurf, etc.), then use slash commands to systematically master any technical topic.
|
|
6
|
+
|
|
7
|
+
## Quick Start
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# Initialize in your project (interactive — select your AI tools)
|
|
11
|
+
npx learn-anything-cli init
|
|
12
|
+
|
|
13
|
+
# Or specify tools directly
|
|
14
|
+
npx learn-anything-cli init --tools claude
|
|
15
|
+
|
|
16
|
+
# Chinese terminal output
|
|
17
|
+
npx learn-anything-cli init --lang zh-CN
|
|
18
|
+
|
|
19
|
+
# Or install globally
|
|
20
|
+
npm install -g learn-anything-cli
|
|
21
|
+
learn-anything init
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
After init, your AI assistant gains five learning commands:
|
|
25
|
+
|
|
26
|
+
| Command | What it does |
|
|
27
|
+
| -------------------------------- | ------------------------------------------------------------ |
|
|
28
|
+
| `/learn:topic <topic-name>` | Initialize a topic, generate a knowledge map, track progress |
|
|
29
|
+
| `/learn:explain <concept-name>` | Recursive Socratic deep-dive into a concept |
|
|
30
|
+
| `/learn:practice <concept-name>` | TDD-style coding exercises with Socratic feedback |
|
|
31
|
+
| `/learn:review [topic-name]` | Review progress, spaced repetition recommendations |
|
|
32
|
+
| `/learn:status [topic-name]` | Visualize learning state as a knowledge map heatmap |
|
|
33
|
+
|
|
34
|
+
## Learning Workflows
|
|
35
|
+
|
|
36
|
+
### `/learn:topic <topic-name>` — Initialize a Topic
|
|
37
|
+
|
|
38
|
+
The AI generates a hierarchical knowledge map (`.learn/topics/<topic>/knowledge-map.md`), creates a learning state tracker (`state.yaml`), and presents the landscape for you to choose your own path.
|
|
39
|
+
|
|
40
|
+
### `/learn:explain <concept-name>` — Recursive Deep Dive
|
|
41
|
+
|
|
42
|
+
The AI assesses your level (beginner → advanced), explains the concept with analogies and code examples, identifies deeper sub-topics, and lets you choose how deep to go. Every session is recorded for spaced repetition.
|
|
43
|
+
|
|
44
|
+
### `/learn:practice <concept-name>` — TDD-Style Exercises
|
|
45
|
+
|
|
46
|
+
The AI generates a test-driven exercise at the right difficulty (beginner / intermediate / challenge), provides structured Socratic feedback, and updates your mastery status. Edge cases, security, and code quality are all covered.
|
|
47
|
+
|
|
48
|
+
### `/learn:review [topic-name]` — Progress Review
|
|
49
|
+
|
|
50
|
+
Analyzes your learning data: mastery heatmap, spaced repetition priority scoring, concept relationship analysis (blocking / orphan concepts). Generates a personalized next-step plan.
|
|
51
|
+
|
|
52
|
+
### `/learn:status [topic-name]` — Visualize State
|
|
53
|
+
|
|
54
|
+
Renders a knowledge map heatmap with status icons, practice counts, and confidence scores for every concept.
|
|
55
|
+
|
|
56
|
+
## Supported AI Tools
|
|
57
|
+
|
|
58
|
+
Manage, Amazon Q Developer, Antigravity, Auggie, Bob Shell, Claude Code, Cline, Codex, ForgeCode, CodeBuddy Code, Continue, CoStrict, Crush, Cursor, Factory Droid, Gemini CLI, GitHub Copilot, iFlow, Junie, Kilo Code, Kiro, OpenCode, Pi, Qoder, Lingma, Qwen Code, RooCode, Trae, Windsurf, and AGENTS.md-compatible assistants.
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
# Update skill files to latest version (detects existing tools automatically)
|
|
62
|
+
npx learn-anything-cli update
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## How It Works
|
|
66
|
+
|
|
67
|
+
```
|
|
68
|
+
Your Project/
|
|
69
|
+
├── .claude/commands/learn/ # Slash commands (learn:topic, learn:explain, ...)
|
|
70
|
+
├── .claude/skills/ # Skill files with full workflow instructions
|
|
71
|
+
├── .cursor/commands/ # Cursor-specific command format
|
|
72
|
+
├── .gemini/commands/learn/ # Gemini TOML-format commands
|
|
73
|
+
├── .learn/ # Your learning data (knowledge maps, progress)
|
|
74
|
+
│ └── topics/
|
|
75
|
+
│ └── javascript/
|
|
76
|
+
│ ├── knowledge-map.md
|
|
77
|
+
│ ├── state.yaml
|
|
78
|
+
│ └── sessions/
|
|
79
|
+
└── ...
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Each AI tool gets tool-appropriate file formats (YAML frontmatter for Claude, TOML for Gemini, etc.) via an adapter pattern.
|
|
83
|
+
|
|
84
|
+
## Development
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
pnpm install
|
|
88
|
+
pnpm build # Compile TypeScript
|
|
89
|
+
pnpm test # Run tests
|
|
90
|
+
pnpm dev # Watch mode
|
|
91
|
+
pnpm dev:cli # Build and run CLI locally
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## License
|
|
95
|
+
|
|
96
|
+
MIT
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Learn Anything
|
|
2
|
+
|
|
3
|
+
AI 驱动的递归学习系统 — 将你的 AI 编程助手变成交互式导师,使用苏格拉底式教学法和 TDD 风格练习。
|
|
4
|
+
|
|
5
|
+
为 **30+ 种 AI 工具**(Claude Code、Cursor、Gemini CLI、Codex、Copilot、Windsurf 等)生成 skill 和 command 文件,通过斜杠命令系统性掌握任何技术主题。
|
|
6
|
+
|
|
7
|
+
## 快速开始
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# 在项目中初始化(交互模式 — 选择你的 AI 工具)
|
|
11
|
+
npx learn-anything-cli init
|
|
12
|
+
|
|
13
|
+
# 直接指定工具
|
|
14
|
+
npx learn-anything-cli init --tools claude
|
|
15
|
+
|
|
16
|
+
# 中文终端输出
|
|
17
|
+
npx learn-anything-cli init --lang zh-CN
|
|
18
|
+
|
|
19
|
+
# 或者全局安装
|
|
20
|
+
npm install -g learn-anything-cli
|
|
21
|
+
learn-anything init
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
初始化后,你的 AI 助手获得五个学习命令:
|
|
25
|
+
|
|
26
|
+
| 命令 | 功能 |
|
|
27
|
+
| -------------------------------- | -------------------------------------- |
|
|
28
|
+
| `/learn:topic <topic-name>` | 初始化主题,生成知识图谱,跟踪学习进度 |
|
|
29
|
+
| `/learn:explain <concept-name>` | 递归式苏格拉底深度学习一个概念 |
|
|
30
|
+
| `/learn:practice <concept-name>` | TDD 风格编码练习,获得苏格拉底式反馈 |
|
|
31
|
+
| `/learn:review [topic-name]` | 回顾学习进度,基于间隔重复推荐下一步 |
|
|
32
|
+
| `/learn:status [topic-name]` | 可视化学习状态,展示知识图谱热力图 |
|
|
33
|
+
|
|
34
|
+
## 学习工作流
|
|
35
|
+
|
|
36
|
+
### `/learn:topic <topic-name>` — 初始化主题
|
|
37
|
+
|
|
38
|
+
AI 生成层次化知识图谱(`.learn/topics/<topic>/knowledge-map.md`),创建学习状态跟踪文件(`state.yaml`),展示知识全景让你自主选择学习路径。
|
|
39
|
+
|
|
40
|
+
### `/learn:explain <concept-name>` — 递归式深度学习
|
|
41
|
+
|
|
42
|
+
AI 评估你的水平(初级 → 高级),用类比和代码示例讲解概念,识别更深层的子话题,让你自主决定深入程度。每次学习会话都会被记录用于间隔重复。
|
|
43
|
+
|
|
44
|
+
### `/learn:practice <concept-name>` — TDD 风格练习
|
|
45
|
+
|
|
46
|
+
AI 生成合适难度的测试驱动练习题(入门 / 进阶 / 挑战),提供结构化的苏格拉底式反馈,并更新你的掌握状态。涵盖边界情况、安全性和代码质量。
|
|
47
|
+
|
|
48
|
+
### `/learn:review [topic-name]` — 进度回顾
|
|
49
|
+
|
|
50
|
+
分析学习数据:掌握度热力图、间隔重复优先级评分、概念关系分析(阻塞概念 / 孤立概念)。生成个性化的下一步学习计划。
|
|
51
|
+
|
|
52
|
+
### `/learn:status [topic-name]` — 可视化状态
|
|
53
|
+
|
|
54
|
+
为每个概念渲染带状态图标、练习次数和信心分数的知识图谱热力图。
|
|
55
|
+
|
|
56
|
+
## 支持的 AI 工具
|
|
57
|
+
|
|
58
|
+
Manage、Amazon Q Developer、Antigravity、Auggie、Bob Shell、Claude Code、Cline、Codex、ForgeCode、CodeBuddy Code、Continue、CoStrict、Crush、Cursor、Factory Droid、Gemini CLI、GitHub Copilot、iFlow、Junie、Kilo Code、Kiro、OpenCode、Pi、Qoder、Lingma、Qwen Code、RooCode、Trae、Windsurf 及兼容 AGENTS.md 的助手。
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
# 更新技能文件到最新版本(自动检测已有工具目录)
|
|
62
|
+
npx learn-anything-cli update
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## 工作原理
|
|
66
|
+
|
|
67
|
+
```
|
|
68
|
+
你的项目/
|
|
69
|
+
├── .claude/commands/learn/ # 斜杠命令(learn:topic、learn:explain...)
|
|
70
|
+
├── .claude/skills/ # 包含完整工作流指令的 skill 文件
|
|
71
|
+
├── .cursor/commands/ # Cursor 专用命令格式
|
|
72
|
+
├── .gemini/commands/learn/ # Gemini TOML 格式命令
|
|
73
|
+
├── .learn/ # 你的学习数据(知识图谱、进度)
|
|
74
|
+
│ └── topics/
|
|
75
|
+
│ └── javascript/
|
|
76
|
+
│ ├── knowledge-map.md
|
|
77
|
+
│ ├── state.yaml
|
|
78
|
+
│ └── sessions/
|
|
79
|
+
└── ...
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
每个 AI 工具通过适配器模式获得对应格式的文件(Claude 用 YAML frontmatter,Gemini 用 TOML 等)。
|
|
83
|
+
|
|
84
|
+
## 开发
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
pnpm install
|
|
88
|
+
pnpm build # 编译 TypeScript
|
|
89
|
+
pnpm test # 运行测试
|
|
90
|
+
pnpm dev # 监听模式
|
|
91
|
+
pnpm dev:cli # 本地构建并运行 CLI
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## 许可证
|
|
95
|
+
|
|
96
|
+
MIT
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { createRequire } from 'module';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { promises as fs } from 'fs';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
import { AI_TOOLS } from '../core/config.js';
|
|
7
|
+
import { resolveLocale } from '../i18n/index.js';
|
|
8
|
+
import { getMessages } from '../i18n/index.js';
|
|
9
|
+
const program = new Command();
|
|
10
|
+
const require = createRequire(import.meta.url);
|
|
11
|
+
const { version } = require('../../package.json');
|
|
12
|
+
// Parse --lang early from process.argv so we can localize static descriptions
|
|
13
|
+
const langIdx = process.argv.indexOf('--lang');
|
|
14
|
+
const earlyLocale = langIdx !== -1 ? resolveLocale(process.argv[langIdx + 1]) : resolveLocale();
|
|
15
|
+
const m = getMessages(earlyLocale);
|
|
16
|
+
program
|
|
17
|
+
.name('learn-anything')
|
|
18
|
+
.description('AI-powered recursive learning system with Socratic method and TDD practice')
|
|
19
|
+
.version(version);
|
|
20
|
+
const availableToolIds = AI_TOOLS.filter((tool) => tool.skillsDir).map((tool) => tool.value);
|
|
21
|
+
program
|
|
22
|
+
.command('init [path]')
|
|
23
|
+
.description(m.cli.initCommandDescription)
|
|
24
|
+
.option('--tools <tools>', m.cli.toolsOptionDescription(availableToolIds.join(', ')))
|
|
25
|
+
.option('--force', m.cli.forceOption)
|
|
26
|
+
.option('--lang <locale>', m.cli.langOption)
|
|
27
|
+
.action(async (targetPath = '.', options) => {
|
|
28
|
+
const cliLocale = resolveLocale(options?.lang);
|
|
29
|
+
const mc = cliLocale !== earlyLocale ? getMessages(cliLocale).cli : m.cli;
|
|
30
|
+
try {
|
|
31
|
+
const resolvedPath = path.resolve(targetPath);
|
|
32
|
+
try {
|
|
33
|
+
const stats = await fs.stat(resolvedPath);
|
|
34
|
+
if (!stats.isDirectory()) {
|
|
35
|
+
throw new Error(mc.notDirectory(targetPath));
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
if (error.code === 'ENOENT') {
|
|
40
|
+
console.log(chalk.yellow(mc.dirNotExist(targetPath)));
|
|
41
|
+
}
|
|
42
|
+
else if (error.message && error.message.includes('not a directory')) {
|
|
43
|
+
throw error;
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
throw new Error(mc.cannotAccess(targetPath, error.message));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
const { InitCommand } = await import('../core/init.js');
|
|
50
|
+
const initCommand = new InitCommand({
|
|
51
|
+
tools: options?.tools,
|
|
52
|
+
force: options?.force,
|
|
53
|
+
locale: cliLocale,
|
|
54
|
+
});
|
|
55
|
+
await initCommand.execute(targetPath);
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
console.log();
|
|
59
|
+
console.error(chalk.red(mc.errorPrefix(error.message)));
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
program
|
|
64
|
+
.command('update [path]')
|
|
65
|
+
.description(m.cli.updateCommandDescription)
|
|
66
|
+
.option('--force', m.cli.forceOption)
|
|
67
|
+
.option('--lang <locale>', m.cli.langOption)
|
|
68
|
+
.action(async (targetPath = '.', options) => {
|
|
69
|
+
const cliLocale = resolveLocale(options?.lang);
|
|
70
|
+
const mc = cliLocale !== earlyLocale ? getMessages(cliLocale).cli : m.cli;
|
|
71
|
+
try {
|
|
72
|
+
const { InitCommand } = await import('../core/init.js');
|
|
73
|
+
const initCommand = new InitCommand({
|
|
74
|
+
update: true,
|
|
75
|
+
force: options?.force ?? true,
|
|
76
|
+
locale: cliLocale,
|
|
77
|
+
});
|
|
78
|
+
await initCommand.execute(targetPath);
|
|
79
|
+
console.log(chalk.green(mc.updateComplete));
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
console.log();
|
|
83
|
+
console.error(chalk.red(mc.errorPrefix(error.message)));
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
program.parse();
|
|
88
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
function escapeYamlValue(value) {
|
|
3
|
+
const needsQuoting = /[:\n\r#{}[\],&*!|>'"%@`]|^\s|\s$/.test(value);
|
|
4
|
+
if (needsQuoting) {
|
|
5
|
+
const escaped = value.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n');
|
|
6
|
+
return `"${escaped}"`;
|
|
7
|
+
}
|
|
8
|
+
return value;
|
|
9
|
+
}
|
|
10
|
+
function formatTagsArray(tags) {
|
|
11
|
+
const escapedTags = tags.map((tag) => escapeYamlValue(tag));
|
|
12
|
+
return `[${escapedTags.join(', ')}]`;
|
|
13
|
+
}
|
|
14
|
+
export const claudeAdapter = {
|
|
15
|
+
toolId: 'claude',
|
|
16
|
+
getFilePath(commandId) {
|
|
17
|
+
return path.join('.claude', 'commands', 'learn', `${commandId}.md`);
|
|
18
|
+
},
|
|
19
|
+
formatFile(content) {
|
|
20
|
+
return `---
|
|
21
|
+
name: ${escapeYamlValue(content.name)}
|
|
22
|
+
description: ${escapeYamlValue(content.description)}
|
|
23
|
+
category: ${escapeYamlValue(content.category)}
|
|
24
|
+
tags: ${formatTagsArray(content.tags)}
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
${content.body}
|
|
28
|
+
`;
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
//# sourceMappingURL=claude.js.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import os from 'os';
|
|
3
|
+
function escapeYamlValue(value) {
|
|
4
|
+
const needsQuoting = /[:\n\r#{}[\],&*!|>'"%@`]|^\s|\s$/.test(value);
|
|
5
|
+
if (needsQuoting) {
|
|
6
|
+
const escaped = value.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n');
|
|
7
|
+
return `"${escaped}"`;
|
|
8
|
+
}
|
|
9
|
+
return value;
|
|
10
|
+
}
|
|
11
|
+
export const codexAdapter = {
|
|
12
|
+
toolId: 'codex',
|
|
13
|
+
getFilePath(commandId) {
|
|
14
|
+
return path.join(os.homedir(), '.codex', 'prompts', `learn-anything-${commandId}.md`);
|
|
15
|
+
},
|
|
16
|
+
formatFile(content) {
|
|
17
|
+
return `---
|
|
18
|
+
description: ${escapeYamlValue(content.description)}
|
|
19
|
+
argument-hint: <概念名>
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
${content.body}
|
|
23
|
+
`;
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=codex.js.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
function escapeYamlValue(value) {
|
|
3
|
+
const needsQuoting = /[:\n\r#{}[\],&*!|>'"%@`]|^\s|\s$/.test(value);
|
|
4
|
+
if (needsQuoting) {
|
|
5
|
+
const escaped = value.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n');
|
|
6
|
+
return `"${escaped}"`;
|
|
7
|
+
}
|
|
8
|
+
return value;
|
|
9
|
+
}
|
|
10
|
+
export const cursorAdapter = {
|
|
11
|
+
toolId: 'cursor',
|
|
12
|
+
getFilePath(commandId) {
|
|
13
|
+
return path.join('.cursor', 'commands', `learn-anything-${commandId}.md`);
|
|
14
|
+
},
|
|
15
|
+
formatFile(content) {
|
|
16
|
+
return `---
|
|
17
|
+
name: /learn-anything-${content.id}
|
|
18
|
+
id: learn-anything-${content.id}
|
|
19
|
+
category: ${escapeYamlValue(content.category)}
|
|
20
|
+
description: ${escapeYamlValue(content.description)}
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
${content.body}
|
|
24
|
+
`;
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=cursor.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
function escapeYamlValue(value) {
|
|
3
|
+
const needsQuoting = /[:\n\r#{}[\],&*!|>'"%@`]|^\s|\s$/.test(value);
|
|
4
|
+
if (needsQuoting) {
|
|
5
|
+
const escaped = value.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n');
|
|
6
|
+
return `"${escaped}"`;
|
|
7
|
+
}
|
|
8
|
+
return value;
|
|
9
|
+
}
|
|
10
|
+
export const geminiAdapter = {
|
|
11
|
+
toolId: 'gemini',
|
|
12
|
+
getFilePath(commandId) {
|
|
13
|
+
return path.join('.gemini', 'commands', 'learn', `${commandId}.toml`);
|
|
14
|
+
},
|
|
15
|
+
formatFile(content) {
|
|
16
|
+
return `description = "${escapeYamlValue(content.description)}"
|
|
17
|
+
prompt = """
|
|
18
|
+
${content.body}
|
|
19
|
+
"""
|
|
20
|
+
`;
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=gemini.js.map
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { CommandContent, GeneratedCommand, ToolCommandAdapter } from './types.js';
|
|
2
|
+
export declare function generateCommand(content: CommandContent, adapter: ToolCommandAdapter): GeneratedCommand;
|
|
3
|
+
export declare function generateCommands(contents: CommandContent[], adapter: ToolCommandAdapter): GeneratedCommand[];
|
|
4
|
+
//# sourceMappingURL=generator.d.ts.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export function generateCommand(content, adapter) {
|
|
2
|
+
return {
|
|
3
|
+
path: adapter.getFilePath(content.id),
|
|
4
|
+
fileContent: adapter.formatFile(content),
|
|
5
|
+
};
|
|
6
|
+
}
|
|
7
|
+
export function generateCommands(contents, adapter) {
|
|
8
|
+
return contents.map((content) => generateCommand(content, adapter));
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=generator.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ToolCommandAdapter } from './types.js';
|
|
2
|
+
export declare class CommandAdapterRegistry {
|
|
3
|
+
private static adapters;
|
|
4
|
+
static get(toolId: string): ToolCommandAdapter | undefined;
|
|
5
|
+
static has(toolId: string): boolean;
|
|
6
|
+
static getAll(): ToolCommandAdapter[];
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { claudeAdapter, cursorAdapter, codexAdapter, geminiAdapter, } from './adapters/index.js';
|
|
2
|
+
export class CommandAdapterRegistry {
|
|
3
|
+
static adapters = new Map();
|
|
4
|
+
static {
|
|
5
|
+
const all = [claudeAdapter, cursorAdapter, codexAdapter, geminiAdapter];
|
|
6
|
+
for (const adapter of all) {
|
|
7
|
+
CommandAdapterRegistry.adapters.set(adapter.toolId, adapter);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
static get(toolId) {
|
|
11
|
+
return CommandAdapterRegistry.adapters.get(toolId);
|
|
12
|
+
}
|
|
13
|
+
static has(toolId) {
|
|
14
|
+
return CommandAdapterRegistry.adapters.has(toolId);
|
|
15
|
+
}
|
|
16
|
+
static getAll() {
|
|
17
|
+
return Array.from(CommandAdapterRegistry.adapters.values());
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface CommandContent {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
description: string;
|
|
5
|
+
category: string;
|
|
6
|
+
tags: string[];
|
|
7
|
+
body: string;
|
|
8
|
+
}
|
|
9
|
+
export interface ToolCommandAdapter {
|
|
10
|
+
toolId: string;
|
|
11
|
+
getFilePath(commandId: string): string;
|
|
12
|
+
formatFile(content: CommandContent): string;
|
|
13
|
+
}
|
|
14
|
+
export interface GeneratedCommand {
|
|
15
|
+
path: string;
|
|
16
|
+
fileContent: string;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const LEARN_DIR = ".learn";
|
|
2
|
+
export interface AIToolOption {
|
|
3
|
+
name: string;
|
|
4
|
+
value: string;
|
|
5
|
+
available: boolean;
|
|
6
|
+
successLabel?: string;
|
|
7
|
+
skillsDir?: string;
|
|
8
|
+
detectionPaths?: string[];
|
|
9
|
+
}
|
|
10
|
+
export declare const AI_TOOLS: AIToolOption[];
|
|
11
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export const LEARN_DIR = '.learn';
|
|
2
|
+
export const AI_TOOLS = [
|
|
3
|
+
{ name: 'Amazon Q Developer', value: 'amazon-q', available: true, successLabel: 'Amazon Q Developer', skillsDir: '.amazonq' },
|
|
4
|
+
{ name: 'Antigravity', value: 'antigravity', available: true, successLabel: 'Antigravity', skillsDir: '.agent' },
|
|
5
|
+
{ name: 'Auggie (Augment CLI)', value: 'auggie', available: true, successLabel: 'Auggie', skillsDir: '.augment' },
|
|
6
|
+
{ name: 'Bob Shell', value: 'bob', available: true, successLabel: 'Bob Shell', skillsDir: '.bob' },
|
|
7
|
+
{ name: 'Claude Code', value: 'claude', available: true, successLabel: 'Claude Code', skillsDir: '.claude' },
|
|
8
|
+
{ name: 'Cline', value: 'cline', available: true, successLabel: 'Cline', skillsDir: '.cline' },
|
|
9
|
+
{ name: 'Codex', value: 'codex', available: true, successLabel: 'Codex', skillsDir: '.codex' },
|
|
10
|
+
{ name: 'ForgeCode', value: 'forgecode', available: true, successLabel: 'ForgeCode', skillsDir: '.forge' },
|
|
11
|
+
{ name: 'CodeBuddy Code (CLI)', value: 'codebuddy', available: true, successLabel: 'CodeBuddy Code', skillsDir: '.codebuddy' },
|
|
12
|
+
{ name: 'Continue', value: 'continue', available: true, successLabel: 'Continue (VS Code / JetBrains / Cli)', skillsDir: '.continue' },
|
|
13
|
+
{ name: 'CoStrict', value: 'costrict', available: true, successLabel: 'CoStrict', skillsDir: '.cospec' },
|
|
14
|
+
{ name: 'Crush', value: 'crush', available: true, successLabel: 'Crush', skillsDir: '.crush' },
|
|
15
|
+
{ name: 'Cursor', value: 'cursor', available: true, successLabel: 'Cursor', skillsDir: '.cursor' },
|
|
16
|
+
{ name: 'Factory Droid', value: 'factory', available: true, successLabel: 'Factory Droid', skillsDir: '.factory' },
|
|
17
|
+
{ name: 'Gemini CLI', value: 'gemini', available: true, successLabel: 'Gemini CLI', skillsDir: '.gemini' },
|
|
18
|
+
{ name: 'GitHub Copilot', value: 'github-copilot', available: true, successLabel: 'GitHub Copilot', skillsDir: '.github', detectionPaths: ['.github/copilot-instructions.md', '.github/instructions', '.github/workflows/copilot-setup-steps.yml', '.github/prompts', '.github/agents', '.github/skills', '.github/.mcp.json'] },
|
|
19
|
+
{ name: 'iFlow', value: 'iflow', available: true, successLabel: 'iFlow', skillsDir: '.iflow' },
|
|
20
|
+
{ name: 'Junie', value: 'junie', available: true, successLabel: 'Junie', skillsDir: '.junie' },
|
|
21
|
+
{ name: 'Kilo Code', value: 'kilocode', available: true, successLabel: 'Kilo Code', skillsDir: '.kilocode' },
|
|
22
|
+
{ name: 'Kiro', value: 'kiro', available: true, successLabel: 'Kiro', skillsDir: '.kiro' },
|
|
23
|
+
{ name: 'OpenCode', value: 'opencode', available: true, successLabel: 'OpenCode', skillsDir: '.opencode' },
|
|
24
|
+
{ name: 'Pi', value: 'pi', available: true, successLabel: 'Pi', skillsDir: '.pi' },
|
|
25
|
+
{ name: 'Qoder', value: 'qoder', available: true, successLabel: 'Qoder', skillsDir: '.qoder' },
|
|
26
|
+
{ name: 'Lingma', value: 'lingma', available: true, successLabel: 'Lingma', skillsDir: '.lingma' },
|
|
27
|
+
{ name: 'Qwen Code', value: 'qwen', available: true, successLabel: 'Qwen Code', skillsDir: '.qwen' },
|
|
28
|
+
{ name: 'RooCode', value: 'roocode', available: true, successLabel: 'RooCode', skillsDir: '.roo' },
|
|
29
|
+
{ name: 'Trae', value: 'trae', available: true, successLabel: 'Trae', skillsDir: '.trae' },
|
|
30
|
+
{ name: 'Windsurf', value: 'windsurf', available: true, successLabel: 'Windsurf', skillsDir: '.windsurf' },
|
|
31
|
+
{ name: 'AGENTS.md (works with Amp, VS Code, …)', value: 'agents', available: false, successLabel: 'your AGENTS.md-compatible assistant' },
|
|
32
|
+
];
|
|
33
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { SupportedLocale } from '../i18n/types.js';
|
|
2
|
+
type InitCommandOptions = {
|
|
3
|
+
tools?: string;
|
|
4
|
+
force?: boolean;
|
|
5
|
+
locale?: SupportedLocale;
|
|
6
|
+
update?: boolean;
|
|
7
|
+
};
|
|
8
|
+
export declare class InitCommand {
|
|
9
|
+
private readonly toolsArg?;
|
|
10
|
+
private readonly force;
|
|
11
|
+
private readonly locale;
|
|
12
|
+
private readonly isUpdate;
|
|
13
|
+
constructor(options?: InitCommandOptions);
|
|
14
|
+
execute(targetPath?: string): Promise<void>;
|
|
15
|
+
private detectTools;
|
|
16
|
+
private hasToolDir;
|
|
17
|
+
private interactiveSelect;
|
|
18
|
+
private generateSkillsForTool;
|
|
19
|
+
private generateCommandsForTool;
|
|
20
|
+
}
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=init.d.ts.map
|