ai-developer-skill-os 1.7.1 → 1.8.1
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 +10 -0
- package/bin/install.js +133 -32
- package/docs/HUONG_DAN_SU_DUNG.md +10 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -57,6 +57,16 @@ Sau khi thư mục kỹ năng đã xuất hiện trong dự án của bạn, hã
|
|
|
57
57
|
**Không cần cấu hình gì thêm!** Nếu bạn đã cài đặt bằng cờ `--gemini` (thư mục `.agents/skills/`), hệ thống sẽ tự động quét và load toàn bộ 23 kỹ năng này. Bạn có thể sử dụng ngay lập tức!
|
|
58
58
|
|
|
59
59
|
### Cho Claude Code / Kilo Code (CLI Agents)
|
|
60
|
+
#### Cách 1: Cài đặt Native (Khuyên dùng cho Kilo Code)
|
|
61
|
+
Chạy `npx ai-developer-skill-os init` và chọn **(6) Kilo Code**.
|
|
62
|
+
Hệ thống sẽ tự động:
|
|
63
|
+
- Copy toàn bộ skills vào `.kilo/skills/` (Local) hoặc `~/.kilo/skills/` (Global)
|
|
64
|
+
- Cấu hình `kilo.json` hoặc `~/.config/kilo/kilo.json` để Kilo nhận diện
|
|
65
|
+
- Tạo file `CLAUDE.md` như hướng dẫn bổ sung
|
|
66
|
+
|
|
67
|
+
Sau đó mở Kilo Code, dùng `<leader>t` hoặc `/themes` để kiểm tra skills đã được cài.
|
|
68
|
+
|
|
69
|
+
#### Cách 2: Thủ công
|
|
60
70
|
Tạo file `CLAUDE.md` (hoặc `KILO.md`) ở gốc dự án và dán đoạn sau vào:
|
|
61
71
|
```md
|
|
62
72
|
# System Instructions
|
package/bin/install.js
CHANGED
|
@@ -28,19 +28,56 @@ function cleanOldSkills(targetSkillsDir, isGeminiGlobal) {
|
|
|
28
28
|
if (fs.existsSync(targetSkillsDir)) {
|
|
29
29
|
console.log('🧹 Đang dọn dẹp phiên bản cũ để tối ưu hệ thống...');
|
|
30
30
|
if (isGeminiGlobal) {
|
|
31
|
-
// Chỉ xoá các thư mục qk-* để không ảnh hưởng các skill khác của người dùng
|
|
32
31
|
fs.readdirSync(targetSkillsDir).forEach(item => {
|
|
33
32
|
if (item.startsWith('qk-')) {
|
|
34
33
|
fs.rmSync(path.join(targetSkillsDir, item), { recursive: true, force: true });
|
|
35
34
|
}
|
|
36
35
|
});
|
|
37
36
|
} else {
|
|
38
|
-
// Xoá sạch toàn bộ thư mục kỹ năng của bộ công cụ này
|
|
39
37
|
fs.rmSync(targetSkillsDir, { recursive: true, force: true });
|
|
40
38
|
}
|
|
41
39
|
}
|
|
42
40
|
}
|
|
43
41
|
|
|
42
|
+
function ensureKiloConfig(kiloJsonPath, kiloSkillsDir, kiloThemesDir, kiloCommandsDir) {
|
|
43
|
+
if (!fs.existsSync(kiloSkillsDir)) {
|
|
44
|
+
fs.mkdirSync(kiloSkillsDir, { recursive: true });
|
|
45
|
+
}
|
|
46
|
+
if (!fs.existsSync(kiloThemesDir)) {
|
|
47
|
+
fs.mkdirSync(kiloThemesDir, { recursive: true });
|
|
48
|
+
}
|
|
49
|
+
if (!fs.existsSync(kiloCommandsDir)) {
|
|
50
|
+
fs.mkdirSync(kiloCommandsDir, { recursive: true });
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const srcSkills = path.join(sourceDir, 'skills');
|
|
54
|
+
if (fs.existsSync(srcSkills)) {
|
|
55
|
+
copyRecursiveSync(srcSkills, kiloSkillsDir);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
let kiloConfig = {};
|
|
59
|
+
if (fs.existsSync(kiloJsonPath)) {
|
|
60
|
+
try {
|
|
61
|
+
kiloConfig = JSON.parse(fs.readFileSync(kiloJsonPath, 'utf8'));
|
|
62
|
+
} catch (e) {
|
|
63
|
+
kiloConfig = {};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const skillPaths = [kiloSkillsDir];
|
|
68
|
+
if (!Array.isArray(kiloConfig.skills) || typeof kiloConfig.skills !== 'object' || !kiloConfig.skills.paths) {
|
|
69
|
+
kiloConfig.skills = { paths: skillPaths };
|
|
70
|
+
} else {
|
|
71
|
+
const exists = kiloConfig.skills.paths.some(p => path.resolve(p) === path.resolve(kiloSkillsDir));
|
|
72
|
+
if (!exists) {
|
|
73
|
+
kiloConfig.skills.paths = [...kiloConfig.skills.paths, ...skillPaths];
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
fs.writeFileSync(kiloJsonPath, JSON.stringify(kiloConfig, null, 2) + '\n');
|
|
78
|
+
return kiloJsonPath;
|
|
79
|
+
}
|
|
80
|
+
|
|
44
81
|
const rl = readline.createInterface({
|
|
45
82
|
input: process.stdin,
|
|
46
83
|
output: process.stdout
|
|
@@ -55,9 +92,10 @@ const questionIde = `Vui lòng chọn IDE/AI Assistant bạn đang sử dụng:
|
|
|
55
92
|
(4) Antigravity / Gemini
|
|
56
93
|
(5) Codex
|
|
57
94
|
(6) Kilo Code
|
|
95
|
+
(7) Tất cả các IDE (Multi-IDE)
|
|
58
96
|
(0) Bỏ qua (Không tạo config tự động)
|
|
59
97
|
|
|
60
|
-
Nhập số (0-
|
|
98
|
+
Nhập số (0-7): `;
|
|
61
99
|
|
|
62
100
|
const questionScope = `
|
|
63
101
|
Bạn muốn cài đặt bộ kỹ năng ở đâu?
|
|
@@ -68,6 +106,8 @@ Nhập số (1-2): `;
|
|
|
68
106
|
|
|
69
107
|
rl.question(questionIde, (answerIde) => {
|
|
70
108
|
let isGemini = false;
|
|
109
|
+
let isKilo = false;
|
|
110
|
+
let isMultiIde = false;
|
|
71
111
|
let ruleFileName = null;
|
|
72
112
|
const ideCode = answerIde.trim();
|
|
73
113
|
|
|
@@ -77,20 +117,35 @@ rl.question(questionIde, (answerIde) => {
|
|
|
77
117
|
case '3': ruleFileName = '.clinerules'; break;
|
|
78
118
|
case '4': isGemini = true; break;
|
|
79
119
|
case '5': ruleFileName = '.codexrules'; break;
|
|
80
|
-
case '6': ruleFileName = '.kilorules'; break;
|
|
120
|
+
case '6': ruleFileName = '.kilorules'; isKilo = true; break;
|
|
121
|
+
case '7': isMultiIde = true; ruleFileName = null; break;
|
|
81
122
|
case '0': default: break;
|
|
82
123
|
}
|
|
83
124
|
|
|
84
125
|
rl.question(questionScope, (answerScope) => {
|
|
85
126
|
const isGlobal = answerScope.trim() === '2';
|
|
86
127
|
|
|
128
|
+
const homeDir = os.homedir();
|
|
129
|
+
const cwd = process.cwd();
|
|
87
130
|
let targetDir = '';
|
|
88
131
|
let ruleFilePath = null;
|
|
89
132
|
let baseFolderForPrompt = '';
|
|
90
|
-
|
|
91
|
-
|
|
133
|
+
let kiloJsonPath = null;
|
|
134
|
+
let kiloSkillsDir = null;
|
|
135
|
+
let kiloThemesDir = null;
|
|
136
|
+
let kiloCommandsDir = null;
|
|
92
137
|
|
|
93
|
-
if (
|
|
138
|
+
if (isMultiIde) {
|
|
139
|
+
targetDir = path.join(cwd, '.qk-ai-skill-os');
|
|
140
|
+
baseFolderForPrompt = './.qk-ai-skill-os';
|
|
141
|
+
ruleFilePath = path.join(cwd, 'CLAUDE.md');
|
|
142
|
+
if (!isGlobal) {
|
|
143
|
+
kiloSkillsDir = path.join(cwd, '.kilo', 'skills');
|
|
144
|
+
kiloThemesDir = path.join(cwd, '.kilo', 'themes');
|
|
145
|
+
kiloCommandsDir = path.join(cwd, '.kilo', 'command');
|
|
146
|
+
kiloJsonPath = path.join(cwd, 'kilo.json');
|
|
147
|
+
}
|
|
148
|
+
} else if (isGemini) {
|
|
94
149
|
if (isGlobal) {
|
|
95
150
|
targetDir = path.join(homeDir, '.gemini', 'config');
|
|
96
151
|
ruleFilePath = path.join(targetDir, 'AGENTS.md');
|
|
@@ -100,6 +155,23 @@ rl.question(questionIde, (answerIde) => {
|
|
|
100
155
|
ruleFilePath = path.join(cwd, '.agents', 'AGENTS.md');
|
|
101
156
|
baseFolderForPrompt = '.agents/skills';
|
|
102
157
|
}
|
|
158
|
+
} else if (isKilo) {
|
|
159
|
+
if (isGlobal) {
|
|
160
|
+
targetDir = path.join(homeDir, '.qk-ai-skill-os');
|
|
161
|
+
baseFolderForPrompt = targetDir.replace(/\\/g, '/');
|
|
162
|
+
kiloSkillsDir = path.join(homeDir, '.kilo', 'skills');
|
|
163
|
+
kiloThemesDir = path.join(homeDir, '.config', 'kilo', 'themes');
|
|
164
|
+
kiloCommandsDir = path.join(homeDir, '.config', 'kilo', 'command');
|
|
165
|
+
kiloJsonPath = path.join(homeDir, '.config', 'kilo', 'kilo.json');
|
|
166
|
+
} else {
|
|
167
|
+
targetDir = path.join(cwd, '.qk-ai-skill-os');
|
|
168
|
+
baseFolderForPrompt = './.qk-ai-skill-os';
|
|
169
|
+
kiloSkillsDir = path.join(cwd, '.kilo', 'skills');
|
|
170
|
+
kiloThemesDir = path.join(cwd, '.kilo', 'themes');
|
|
171
|
+
kiloCommandsDir = path.join(cwd, '.kilo', 'command');
|
|
172
|
+
kiloJsonPath = path.join(cwd, 'kilo.json');
|
|
173
|
+
}
|
|
174
|
+
ruleFilePath = path.join(cwd, 'CLAUDE.md');
|
|
103
175
|
} else {
|
|
104
176
|
if (isGlobal) {
|
|
105
177
|
targetDir = path.join(homeDir, '.qk-ai-skill-os');
|
|
@@ -136,49 +208,78 @@ Nếu người dùng sử dụng tham số (argument), bạn BẮT BUỘC phải
|
|
|
136
208
|
'skills', '_template', 'docs', 'skills.json', 'README.md', 'CHANGELOG.md', 'LICENSE'
|
|
137
209
|
];
|
|
138
210
|
|
|
139
|
-
// Nếu là Gemini Global, chỉ cần copy skills và skills.json để tránh rác
|
|
140
211
|
if (isGemini && isGlobal) {
|
|
141
212
|
if (fs.existsSync(path.join(sourceDir, 'skills'))) {
|
|
142
|
-
|
|
213
|
+
copyRecursiveSync(path.join(sourceDir, 'skills'), path.join(targetDir, 'skills'));
|
|
143
214
|
}
|
|
144
215
|
if (fs.existsSync(path.join(sourceDir, 'skills.json'))) {
|
|
145
|
-
|
|
216
|
+
fs.copyFileSync(path.join(sourceDir, 'skills.json'), path.join(targetDir, 'skills', 'skills.json'));
|
|
146
217
|
}
|
|
147
218
|
} else {
|
|
148
219
|
filesAndFolders.forEach(item => {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
220
|
+
const src = path.join(sourceDir, item);
|
|
221
|
+
let dest = path.join(targetDir, item);
|
|
222
|
+
if (fs.existsSync(src)) {
|
|
223
|
+
copyRecursiveSync(src, dest);
|
|
224
|
+
}
|
|
154
225
|
});
|
|
155
226
|
}
|
|
156
227
|
|
|
157
228
|
if (ruleFilePath) {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
let writeContent = systemPrompt;
|
|
164
|
-
if (isGemini) {
|
|
165
|
-
writeContent = `\n<RULE[ai_skill_os]>\n---\ntrigger: always_on\n---\n${systemPrompt}\n</RULE[ai_skill_os]>\n`;
|
|
166
|
-
}
|
|
229
|
+
const ruleDir = path.dirname(ruleFilePath);
|
|
230
|
+
if (ruleDir !== cwd && !fs.existsSync(ruleDir)) {
|
|
231
|
+
fs.mkdirSync(ruleDir, { recursive: true });
|
|
232
|
+
}
|
|
167
233
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
234
|
+
let writeContent = systemPrompt;
|
|
235
|
+
if (isGemini) {
|
|
236
|
+
writeContent = `\n<RULE[ai_skill_os]>\n---\ntrigger: always_on\n---\n${systemPrompt}\n</RULE[ai_skill_os]>\n`;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (fs.existsSync(ruleFilePath)) {
|
|
240
|
+
fs.appendFileSync(ruleFilePath, "\n\n" + writeContent);
|
|
241
|
+
console.log(`✅ Đã GHI THÊM cấu hình tự động vào file: ${ruleFilePath}`);
|
|
242
|
+
} else {
|
|
243
|
+
fs.writeFileSync(ruleFilePath, writeContent);
|
|
244
|
+
console.log(`✅ Đã TẠO MỚI file cấu hình: ${ruleFilePath}`);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if (isKilo) {
|
|
249
|
+
ensureKiloConfig(kiloJsonPath, kiloSkillsDir, kiloThemesDir, kiloCommandsDir);
|
|
250
|
+
console.log(`✅ Đã cấu hình Kilo Code tại: ${kiloJsonPath}`);
|
|
251
|
+
console.log(` → Skills: ${kiloSkillsDir}`);
|
|
252
|
+
console.log(` → Themes: ${kiloThemesDir}`);
|
|
253
|
+
console.log(` → Commands: ${kiloCommandsDir}`);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
if (isMultiIde) {
|
|
257
|
+
if (kiloJsonPath && kiloSkillsDir) {
|
|
258
|
+
ensureKiloConfig(kiloJsonPath, kiloSkillsDir, kiloThemesDir, kiloCommandsDir);
|
|
259
|
+
console.log(`✅ Đã cấu hình Kilo Code (Multi-IDE) tại: ${kiloJsonPath}`);
|
|
260
|
+
console.log(` → Skills: ${kiloSkillsDir}`);
|
|
261
|
+
console.log(` → Themes: ${kiloThemesDir}`);
|
|
262
|
+
console.log(` → Commands: ${kiloCommandsDir}`);
|
|
263
|
+
} else if (ruleFilePath) {
|
|
264
|
+
console.log(`✅ Đã tạo file cấu hình Multi-IDE: ${ruleFilePath}`);
|
|
265
|
+
}
|
|
175
266
|
}
|
|
176
267
|
|
|
177
268
|
console.log(`\n🎉 HOÀN TẤT! Dữ liệu kỹ năng đã được lưu tại: ${targetDir}`);
|
|
178
269
|
if (isGlobal && !isGemini) {
|
|
179
|
-
|
|
270
|
+
const name = ruleFilePath ? path.basename(ruleFilePath) : 'CLAUDE.md';
|
|
271
|
+
console.log(`💡 Lưu ý: Kỹ năng đã được cài ở cấp độ máy tính (Global). File cấu hình cục bộ (${name}) ở dự án này đang trỏ thẳng về thư mục Global đó.`);
|
|
180
272
|
} else if (isGlobal && isGemini) {
|
|
181
273
|
console.log(`💡 Lưu ý: Antigravity đã được cài Global. Từ nay bạn mở BẤT KỲ DỰ ÁN NÀO trên máy tính này, Antigravity cũng sẽ tự động có đủ 23 kỹ năng mà không cần cài lại!`);
|
|
274
|
+
} else if (isKilo) {
|
|
275
|
+
console.log(`💡 Lưu ý: Kilo Code đã sẵn sàng. Dùng \`<leader>t\` hoặc \`/themes\` để xem, và \`/skills\` để xem danh sách skill đã cài.`);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
if (!isGemini && !isKilo && !isMultiIde) {
|
|
279
|
+
if (fs.existsSync(path.join(cwd, '.kilorules'))) {
|
|
280
|
+
fs.unlinkSync(path.join(cwd, '.kilorules'));
|
|
281
|
+
console.log(`🧹 Đã xoá file .kilorules cũ (không còn cần thiết).`);
|
|
282
|
+
}
|
|
182
283
|
}
|
|
183
284
|
|
|
184
285
|
} catch (error) {
|
|
@@ -59,6 +59,16 @@ Speak to me in Vietnamese, but write all code in English.
|
|
|
59
59
|
```
|
|
60
60
|
|
|
61
61
|
### Cho Claude Code / Kilo Code (CLI Agents)
|
|
62
|
+
#### Cách 1: Cài đặt Native (Khuyên dùng cho Kilo Code)
|
|
63
|
+
Chạy `npx ai-developer-skill-os init` và chọn **(6) Kilo Code**.
|
|
64
|
+
Hệ thống sẽ tự động:
|
|
65
|
+
- Copy toàn bộ skills vào `.kilo/skills/` (Local) hoặc `~/.kilo/skills/` (Global)
|
|
66
|
+
- Cấu hình `kilo.json` hoặc `~/.config/kilo/kilo.json` để Kilo nhận diện
|
|
67
|
+
- Tạo file `CLAUDE.md` như hướng dẫn bổ sung
|
|
68
|
+
|
|
69
|
+
Sau đó mở Kilo Code, dùng `<leader>t` hoặc `/themes` để kiểm tra skills đã được cài.
|
|
70
|
+
|
|
71
|
+
#### Cách 2: Thủ công
|
|
62
72
|
Tạo file `CLAUDE.md` (hoặc `KILO.md`) ở gốc dự án và dán đoạn sau vào:
|
|
63
73
|
```md
|
|
64
74
|
# System Instructions
|
package/package.json
CHANGED