ai-developer-skill-os 1.6.0 → 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 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
@@ -133,10 +143,15 @@ Trước khi đổi một cấu trúc lớn, hãy bắt AI dò mìn:
133
143
 
134
144
  ---
135
145
 
136
- ## 💎 Danh sách 23+ Kỹ Năng Độc Quyền
146
+ ## 💎 **Danh sách đầy đủ các Kỹ năng đang có trong Skill OS:**
147
+ *(Bạn có thể gọi trực tiếp trên Terminal hoặc Chat)*
148
+
149
+ > 💡 **Mẹo (Pro-Tip):** Bất cứ khi nào bạn quên mất danh sách kỹ năng hoặc cách dùng, chỉ cần gõ lệnh `./qk-help` (hoặc `@qk-help`), hệ thống sẽ xuất ra toàn bộ cẩm nang sử dụng và bí kíp kết hợp Kỹ năng (Skill Chaining) ngay lập tức!
137
150
 
138
- | Phân hệ | Kỹ năng tiêu biểu | Chức năng chính |
139
- |---------|-------------------|-----------------|
151
+ | Kỹ năng (Skill) | Nhiệm vụ chuyên môn |
152
+ |-----------------|---------------------|
153
+ | 🧠 **`qk-help`** | **[MỚI] Sách hướng dẫn tra cứu nhanh danh sách Skill và Bí kíp kết hợp** |
154
+ | 🧑‍💻 **`qk-ui-builder`** | Xây dựng UI, vẽ Màn hình, chia Layout, tạo Modal cực đẹp |
140
155
  | 🏗️ **Engineering** | `qk-project-audit`, `qk-agent-orchestrator` | Kiểm toán dự án, lập kế hoạch, quản lý Git, Refactor code. |
141
156
  | 🎨 **Frontend** | `qk-ui-builder`, `qk-frontend-performance` | Dựng UI, tối ưu tốc độ, test component, quản lý State. |
142
157
  | ⚙️ **Backend** | `qk-database-engineer`, `qk-auth-security` | Thiết kế DB Schema, bảo mật JWT/OAuth, cấu hình CI/CD. |
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-6): `;
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
- const homeDir = os.homedir();
91
- const cwd = process.cwd();
133
+ let kiloJsonPath = null;
134
+ let kiloSkillsDir = null;
135
+ let kiloThemesDir = null;
136
+ let kiloCommandsDir = null;
92
137
 
93
- if (isGemini) {
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
- copyRecursiveSync(path.join(sourceDir, 'skills'), path.join(targetDir, 'skills'));
213
+ copyRecursiveSync(path.join(sourceDir, 'skills'), path.join(targetDir, 'skills'));
143
214
  }
144
215
  if (fs.existsSync(path.join(sourceDir, 'skills.json'))) {
145
- fs.copyFileSync(path.join(sourceDir, 'skills.json'), path.join(targetDir, 'skills', 'skills.json'));
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
- const src = path.join(sourceDir, item);
150
- let dest = path.join(targetDir, item);
151
- if (fs.existsSync(src)) {
152
- copyRecursiveSync(src, dest);
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
- const ruleDir = path.dirname(ruleFilePath);
159
- if (ruleDir !== cwd && !fs.existsSync(ruleDir)) {
160
- fs.mkdirSync(ruleDir, { recursive: true });
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
- if (fs.existsSync(ruleFilePath)) {
169
- fs.appendFileSync(ruleFilePath, "\n\n" + writeContent);
170
- console.log(`✅ Đã GHI THÊM cấu hình tự động vào file: ${ruleFilePath}`);
171
- } else {
172
- fs.writeFileSync(ruleFilePath, writeContent);
173
- console.log(`✅ Đã TẠO MỚI file cấu hình: ${ruleFilePath}`);
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
- 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ộ (${ruleFileName}) dự án này đang trỏ thẳng về thư mục Global đó.`);
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-developer-skill-os",
3
- "version": "1.6.0",
3
+ "version": "1.8.1",
4
4
  "description": "Multi-agent skill package cho AI coding agents (Claude, Cursor, Windsurf, Antigravity) với 23 skills chuyên nghiệp.",
5
5
  "main": "bin/install.js",
6
6
  "bin": {
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: qk-api-integration
2
+ name: qk-api-integration
3
3
  description: >-
4
4
  Chuyển đổi tài liệu API (curl, swagger...) thành code tích hợp frontend chuẩn xác, có type an toàn và xử lý lỗi.
5
5
  version: 2.0.0
@@ -37,6 +37,248 @@ Activate this skill when the user provides any of:
37
37
  - ✅ Generate typed service/client, hooks/queries, and TypeScript types
38
38
  - ✅ Follow and extend existing architecture — never duplicate it
39
39
  - ✅ Handle special cases: file upload, file download, pagination, auth, WebSocket
40
+
41
+ ---
42
+
43
+ ## Non-goals
44
+
45
+ - ❌ Do NOT create a new HTTP client if one already exists
46
+ - ❌ Do NOT introduce a new state system if one is already in use
47
+ - ❌ Do NOT hardcode URLs, tokens, or secrets
48
+ - ❌ Do NOT use `any` when types can be inferred
49
+ - ❌ Do NOT overwrite existing files without explicit user approval
50
+
51
+ ---
52
+
53
+ ## Severity Levels
54
+
55
+ | Level | Meaning |
56
+ |-------|---------|
57
+ | P0 | Conflict with existing endpoint or type — must resolve before generating |
58
+ | P1 | Missing critical info (auth, response schema) — ask before proceeding |
59
+ | P2 | Naming or structure inconsistency — warn and apply best guess |
60
+ | P3 | Missing optional fields — document assumption and proceed |
61
+
62
+ ---
63
+
64
+ ## Workflow
65
+
66
+ ### Phase 1 — Input Validation
67
+
68
+ Before parsing, verify:
69
+ - URL is valid and method is correct (GET/POST/PUT/PATCH/DELETE)
70
+ - Auth format is identifiable (Bearer, API Key, OAuth2, Basic, Cookie)
71
+ - Request info is present (path params, query params, body)
72
+ - Response structure is clear (JSON, binary, stream, paginated)
73
+ - Error cases are documented
74
+
75
+ If critical info is missing → **stop and ask**. Do not guess.
76
+
77
+ ```json
78
+ {
79
+ "validation": {
80
+ "status": "VALID | INVALID | INCOMPLETE",
81
+ "confidence": 0.95,
82
+ "errors": [],
83
+ "warnings": [],
84
+ "input_type": "curl | openapi | postman | docs | code"
85
+ }
86
+ }
87
+ ```
88
+
89
+ ---
90
+
91
+ ### Phase 2 — API Contract Extraction
92
+
93
+ Extract the full contract:
94
+
95
+ ```
96
+ metadata:
97
+ name, domain, endpoint, method, version, description
98
+
99
+ request:
100
+ pathParams: { name, type, required }
101
+ queryParams: { name, type, required, default }
102
+ headers: { name, value, required }
103
+ body: { contentType, schema { field, type, required, nullable } }
104
+ auth: { type, location, name }
105
+
106
+ response:
107
+ success: { statusCode, contentType, schema, pagination? }
108
+ errors: [ { statusCode, message, businessCode? } ]
109
+
110
+ special:
111
+ rateLimit, timeout, retryable, streaming
112
+ ```
113
+
114
+ Map each field: `type`, `required`, `nullable`, `enum`, `example`.
115
+
116
+ ---
117
+
118
+ ### Phase 3 — Project Profile Detection
119
+
120
+ 1. Check for `.api-config.json` at project root → use if present
121
+ 2. Otherwise infer from:
122
+ - Framework: `package.json`, config files, imports
123
+ - HTTP client: existing axios instance, fetch wrapper, custom client
124
+ - State management: React Query, Redux, Zustand, Pinia, Apollo, Vuex
125
+ - Type system: `tsconfig.json`, JSDoc, plain JS
126
+ - Folder conventions: `services/`, `hooks/`, `api/`, `types/`, `adapters/`
127
+ - Naming: camelCase, PascalCase, snake_case, file patterns
128
+ 3. Read 1-2 existing API files to capture exact patterns for imports, typing, error handling, naming
129
+
130
+ If project context is ambiguous → use conservative defaults and document all assumptions.
131
+
132
+ ---
133
+
134
+ ### Phase 4 — Conflict Detection
135
+
136
+ Before generating code, check for:
137
+
138
+ | Conflict | Action |
139
+ |----------|--------|
140
+ | `ENDPOINT_DUPLICATE` — endpoint already exists | Reuse if same, warn if different |
141
+ | `FUNCTION_DUPLICATE` — function name conflicts | Warn, propose new name |
142
+ | `TYPE_DUPLICATE` — type already defined | Extend or reuse existing |
143
+ | `LOGIC_OVERLAP` — logic exists in another service | Consolidate, don't duplicate |
144
+ | `IMPORT_CONFLICT` — import path conflicts | Resolve before generating |
145
+
146
+ **P0 conflict → stop, report, wait for user decision before proceeding.**
147
+
148
+ ---
149
+
150
+ ### Phase 5 — Code Generation
151
+
152
+ Generate the minimum necessary set for the task:
153
+
154
+ #### TypeScript Types
155
+ ```typescript
156
+ // Request types
157
+ export interface CreateUserRequest {
158
+ name: string;
159
+ email: string;
160
+ role?: UserRole;
161
+ }
162
+
163
+ // Response types
164
+ export interface CreateUserResponse {
165
+ id: string;
166
+ name: string;
167
+ email: string;
168
+ createdAt: string;
169
+ }
170
+
171
+ // Error types
172
+ export interface ApiError {
173
+ code: string;
174
+ message: string;
175
+ details?: Record<string, unknown>;
176
+ }
177
+ ```
178
+
179
+ #### Service / API Layer
180
+ ```typescript
181
+ // Thin layer: HTTP + mapping only. No UI, no business logic.
182
+ export const createUser = async (
183
+ data: CreateUserRequest
184
+ ): Promise<CreateUserResponse> => {
185
+ const response = await apiClient.post<CreateUserResponse>('/users', data);
186
+ return response.data;
187
+ };
188
+ ```
189
+
190
+ #### Hook / Query (if project uses React Query)
191
+ ```typescript
192
+ export const useCreateUser = () => {
193
+ return useMutation<CreateUserResponse, ApiError, CreateUserRequest>({
194
+ mutationFn: createUser,
195
+ onSuccess: () => {
196
+ queryClient.invalidateQueries({ queryKey: ['users'] });
197
+ },
198
+ });
199
+ };
200
+ ```
201
+
202
+ **If project uses Redux** → follow existing slice/thunk pattern.
203
+ **If project uses Zustand** → follow existing store pattern.
204
+ **If project uses Pinia/Vuex** → follow existing composable/action pattern.
205
+
206
+ Do NOT mix patterns.
207
+
208
+ ---
209
+
210
+ ### Phase 6 — Special Case Handling
211
+
212
+ #### File Upload (`multipart/form-data`)
213
+ ```typescript
214
+ // Always use FormData — never send File object in JSON
215
+ const formData = new FormData();
216
+ formData.append('file', file);
217
+ formData.append('name', name);
218
+ await apiClient.post('/upload', formData, {
219
+ headers: { 'Content-Type': 'multipart/form-data' },
220
+ });
221
+ ```
222
+
223
+ #### File Download (binary response)
224
+ ```typescript
225
+ const response = await apiClient.get('/export', { responseType: 'blob' });
226
+ const url = URL.createObjectURL(response.data);
227
+ const a = document.createElement('a');
228
+ a.href = url;
229
+ a.download = filename;
230
+ a.click();
231
+ URL.revokeObjectURL(url);
232
+ ```
233
+
234
+ #### Pagination
235
+ ```typescript
236
+ interface PaginatedResponse<T> {
237
+ items: T[];
238
+ total: number;
239
+ page: number;
240
+ limit: number;
241
+ }
242
+ // Implement consistently with existing project pagination pattern
243
+ ```
244
+
245
+ #### Authentication
246
+ - Follow existing auth mechanism (interceptor, header injection, cookie)
247
+ - Never hardcode tokens or credentials
248
+ - Refresh token logic belongs in the existing interceptor
249
+
250
+ ---
251
+
252
+ ### Phase 7 — Quality Validation
253
+
254
+ Before marking as ready:
255
+
256
+ - [ ] TypeScript strict — compiles clean, no `any` without justification
257
+ - [ ] All functions/params have explicit types and return types
258
+ - [ ] No unused imports, no debug code
259
+ - [ ] Error handling complete (try/catch, `.catch`, fallback)
260
+ - [ ] No hardcoded URLs, tokens, or secrets — use env vars
261
+ - [ ] Naming matches project conventions
262
+ - [ ] Reuses existing HTTP client, interceptors, and query client
263
+ - [ ] JSDoc added for public API if project convention requires it
264
+ - [ ] React: dependency arrays correct, cleanup present, no race conditions
265
+
266
+ ---
267
+
268
+ ### Phase 8 — End-to-End UI Integration (Optional / On-Demand)
269
+
270
+ If the user explicitly requests to integrate the API directly into the UI (End-to-End):
271
+ 1. **Find Target Component:** Identify the UI component where the API should be called.
272
+ 2. **Wire State:** Inject the generated Hook/Query/Service into the component.
273
+ 3. **Handle States:** Implement Loading (spinners, skeletons), Error (toast, alert), and Success (redirect, form reset, table refetch) states in the UI.
274
+ 4. **Data Binding:** Bind the API response data to the UI elements (Table rows, Dropdowns, etc.) and bind UI inputs to the API request payload.
275
+
276
+ ---
277
+
278
+ ## Decision Tree
279
+
280
+ ```
281
+ Is required info complete?
40
282
  ├── No → Ask for missing info (auth, response schema, base URL)
41
283
  └── Yes → Check for conflicts
42
284
  ├── P0 conflict → Stop, report, wait for user decision
@@ -0,0 +1,67 @@
1
+ ---
2
+ name: qk-help
3
+ description: >-
4
+ Tra cứu danh sách toàn bộ kỹ năng (skills) hiện có và đọc các mẹo (pro-tips) kết hợp kỹ năng để tăng tốc độ code.
5
+ version: 1.0.0
6
+ category: engineering
7
+ tags: [help, list, tips, guide, manual]
8
+ platforms: [antigravity, claude-code, kilo-code, cursor, windsurf]
9
+ ---
10
+
11
+ # 📚 Cẩm nang AI Developer Skill OS
12
+
13
+ > **Nhiệm vụ của bạn (AI):** Khi người dùng gọi lệnh `./qk-help`, hãy xuất ra màn hình (bằng tiếng Việt) danh sách các kỹ năng phân theo nhóm và các Mẹo sử dụng (Pro-tips) dưới đây một cách sinh động, dễ đọc (dùng markdown, in đậm, emoji). Không cần phân tích code, chỉ đóng vai trò là "Sách hướng dẫn sử dụng".
14
+
15
+ ---
16
+
17
+ ## 🎯 1. Danh sách Kỹ năng (Skills Directory)
18
+
19
+ Dưới đây là các kỹ năng chính bạn có thể gọi bằng cách gõ `./qk-[tên-kỹ-năng]`:
20
+
21
+ ### 🎨 Frontend (Giao diện)
22
+ - **`qk-ui-builder`**: Xây dựng UI, Layout, Component, Modal phức tạp.
23
+ - **`qk-table-crud-generator`**: Chuyên vẽ bảng danh sách (Table), phân trang, lọc và form Thêm/Sửa/Xóa.
24
+ - **`qk-form-builder`**: Chuyên làm Form nhập liệu, validate (Zod/Yup).
25
+ - **`qk-component-generator`**: Tạo Component độc lập, tái sử dụng (Button, Input, Card).
26
+ - **`qk-state-management`**: Xử lý Redux, Zustand, React Query.
27
+ - **`qk-frontend-debug`**: Bắt bệnh vỡ layout, infinite re-render, lỗi Hydration.
28
+ - **`qk-frontend-performance`**: Tối ưu tốc độ, chống re-render thừa.
29
+ - **`qk-frontend-architecture`**: Tư vấn kiến trúc thư mục Frontend.
30
+ - **`qk-frontend-testing`**: Viết Unit Test / E2E Test cho Frontend.
31
+ - **`qk-accessibility-audit`**: Sửa lỗi a11y, hỗ trợ Screen reader.
32
+
33
+ ### ⚙️ Engineering & Integration (Tích hợp)
34
+ - **`qk-api-integration`**: [Cực mạnh] Bóc tách tài liệu API (Curl, Postman) -> Gen Type, Service, Hook -> (Tùy chọn) Ốp thẳng vào UI.
35
+ - **`qk-refactor`**: Tối ưu, dọn dẹp mã nguồn sạch sẽ.
36
+ - **`qk-bug-fix`**: Chẩn đoán lỗi sâu và sửa an toàn.
37
+ - **`qk-project-audit`**: Quét toàn bộ dự án tìm nợ kỹ thuật.
38
+ - **`qk-git-engineer`**: Viết Commit / PR chuẩn Conventional.
39
+ - **`qk-migration`**: Nâng cấp version framework / thư viện.
40
+ - **`qk-agent-orchestrator`**: Kiến trúc sư, lên plan phân rã task lớn.
41
+ - **`qk-context-manager`**: Tóm tắt kiến trúc dự án.
42
+
43
+ ### 🗄️ Backend (Máy chủ)
44
+ - **`qk-database-engineer`**: Thiết kế Schema, ORM (Prisma/Drizzle), Migration.
45
+ - **`qk-backend-architecture`**: Setup kiến trúc Backend (Node/Nest/Python).
46
+ - **`qk-auth-security`**: Phân quyền RBAC, JWT, OAuth.
47
+ - **`qk-deployment`**: Viết Dockerfile, CI/CD Pipeline.
48
+
49
+ ---
50
+
51
+ ## 💡 2. Mẹo sử dụng Nâng cao (Pro-Tips)
52
+
53
+ ### Mẹo 1: Kết hợp Kỹ năng (Skill Chaining) 🔗
54
+ Đừng bắt AI làm từ A-Z bằng 1 câu prompt. Hãy gọi liên hoàn:
55
+ > *"Hãy dùng `./qk-api-integration` để bóc tách API này thành hook React Query. Sau đó dùng `./qk-table-crud-generator` vẽ cái Bảng hiển thị danh sách tích hợp hook đó."*
56
+
57
+ ### Mẹo 2: Chế độ "Một phát ăn ngay" (End-to-End) 🚀
58
+ Nếu bạn đã có sẵn 1 màn hình UI (chỉ thiếu data), hãy ép `qk-api-integration` làm End-to-End:
59
+ > *"./qk-api-integration Dưới đây là API Get Profile. Hãy khai báo Type, viết Hook và TÍCH HỢP THẲNG LUÔN vào file \`Profile.tsx\` đang mở."*
60
+
61
+ ### Mẹo 3: Truyền tham số ép buộc (Arguments) 🎯
62
+ Bạn có thể ép AI dùng công nghệ bạn muốn bằng cách thêm \`--tham_số\`:
63
+ > *"./qk-ui-builder --fw=react --css=tailwind Hãy vẽ màn hình Đăng nhập."*
64
+
65
+ ### Mẹo 4: Nhờ "Kiến trúc sư" phân việc 🧠
66
+ Nếu bạn có một tính năng quá lớn (ví dụ: Làm tính năng Giỏ Hàng), đừng tự chia việc, hãy gọi:
67
+ > *"./qk-agent-orchestrator Tôi muốn làm tính năng Giỏ hàng. Hãy phân tích và lên kế hoạch gọi các skill \`qk-\` nào cho phù hợp."*
package/skills.json CHANGED
@@ -6,6 +6,30 @@
6
6
  "author": "Quang Khánh",
7
7
  "homepage": "https://github.com/phamquangkhanh2999/ai-developer-skill-os.git",
8
8
  "skills": [
9
+ {
10
+ "name": "qk-help",
11
+ "path": "skills/qk-help/SKILL.md",
12
+ "version": "1.0.0",
13
+ "category": "engineering",
14
+ "priority": "P0",
15
+ "trigger": [
16
+ "help",
17
+ "list skills",
18
+ "show tips",
19
+ "danh sách skill"
20
+ ],
21
+ "dependencies": [],
22
+ "conflicts": [],
23
+ "platforms": [
24
+ "antigravity",
25
+ "claude-code",
26
+ "kilo-code",
27
+ "cursor",
28
+ "windsurf"
29
+ ],
30
+ "status": "planned",
31
+ "description": "Tra cứu danh sách toàn bộ kỹ năng (skills) hiện có và đọc các mẹo kết hợp để code hiệu quả."
32
+ },
9
33
  {
10
34
  "name": "qk-agent-orchestrator",
11
35
  "path": "skills/qk-agent-orchestrator/SKILL.md",