sp-rag 0.6.11 → 0.6.12

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
@@ -17,7 +17,7 @@ CLI để setup nhanh SP-RAG theo hướng dev-friendly:
17
17
  ## Trạng thái package
18
18
 
19
19
  - package npm public: `sp-rag`
20
- - version đang publish: `0.6.7`
20
+ - version đang publish: `0.6.12`
21
21
  - binary public: `sp-rag`
22
22
 
23
23
  ## Cài từ source trong monorepo
@@ -36,8 +36,10 @@ node dist/index.js doctor
36
36
  npx sp-rag@latest install --client codex --mcp-token <grc_pat_...> --doctor
37
37
  npx sp-rag@latest install --client cursor --scope project --cwd D:/Webs/seo-booster --mcp-token <grc_pat_...>
38
38
  npx sp-rag@latest install --client vscode --scope project --cwd D:/Webs/seo-booster --mcp-token <grc_pat_...>
39
- npx sp-rag@latest add --client claude-code --scope project --cwd D:/Webs/seo-booster
40
- npx sp-rag@latest explain --client vscode --scope project --cwd D:/Webs/seo-booster
39
+ npx sp-rag@latest add --client claude-code --scope project --cwd D:/Webs/seo-booster
40
+ npx sp-rag@latest update --client claude-code --scope project --cwd D:/Webs/seo-booster
41
+ npx sp-rag@latest uninstall --client claude-code --scope project --cwd D:/Webs/seo-booster
42
+ npx sp-rag@latest explain --client vscode --scope project --cwd D:/Webs/seo-booster
41
43
  npx sp-rag@latest token add --token <grc_pat_...>
42
44
  npx sp-rag@latest token verify --token <grc_pat_...>
43
45
  npx sp-rag@latest mcp add antigravity
@@ -50,8 +52,10 @@ Tương đương bằng `npm`:
50
52
 
51
53
  ```bash
52
54
  npm exec --yes sp-rag@latest install -- --client codex --mcp-token <grc_pat_...> --doctor
53
- npm exec --yes sp-rag@latest add -- --client claude-code --scope project --cwd D:/Webs/seo-booster
54
- npm exec --yes sp-rag@latest explain -- --client vscode --scope project --cwd D:/Webs/seo-booster
55
+ npm exec --yes sp-rag@latest add -- --client claude-code --scope project --cwd D:/Webs/seo-booster
56
+ npm exec --yes sp-rag@latest update -- --client claude-code --scope project --cwd D:/Webs/seo-booster
57
+ npm exec --yes sp-rag@latest uninstall -- --client claude-code --scope project --cwd D:/Webs/seo-booster
58
+ npm exec --yes sp-rag@latest explain -- --client vscode --scope project --cwd D:/Webs/seo-booster
55
59
  npm exec --yes sp-rag@latest token add -- --token <grc_pat_...>
56
60
  npm exec --yes sp-rag@latest token verify -- --token <grc_pat_...>
57
61
  ```
@@ -61,24 +65,29 @@ npm exec --yes sp-rag@latest token verify -- --token <grc_pat_...>
61
65
  Flow khuyên dùng sau khi đã có `grc_pat_*`:
62
66
 
63
67
  1. chạy `install` đúng một lần cho client đầu tiên, có kèm `--mcp-token`
64
- 2. từ lần sau, dùng `add --client ...` để cài thêm MCP + skill cho client khác mà không phải nhập lại token
65
- 3. khi chỉ muốn làm một nửa, dùng `mcp add` hoặc `skill install`
66
- 4. khi đổi token, chỉ cần `token add`
67
- 5. khi muốn kiểm tra máy đang được cấu hình ra sao, dùng `explain`
68
+ 2. từ lần sau, dùng `add --client ...` để cài thêm MCP + skill cho client khác mà không phải nhập lại token
69
+ 3. khi muốn cập nhật lại MCP + skill giữ token cũ, dùng `update`
70
+ 4. khi muốn gỡ sạch MCP + skill + config CLI do `sp-rag` tạo, dùng `uninstall`
71
+ 5. khi chỉ muốn làm một nửa, dùng `mcp add` hoặc `skill install`
72
+ 6. khi đổi token, chỉ cần `token add`
73
+ 7. khi muốn kiểm tra máy đang được cấu hình ra sao, dùng `explain`
68
74
 
69
75
  Ghi chú:
70
76
 
71
- - với `cursor` và `vscode` ở `scope project`, nếu Sếpp đang đứng sẵn trong repo thì có thể bỏ `--cwd`
72
- - CLI sẽ tự dùng thư mục hiện tại cho cả MCP lẫn skill
73
- - rule/agent mới đã được tăng độ ưu tiên MCP-first, giảm khả năng model nhảy thẳng sang grep/read file local
77
+ - với `cursor` và `vscode` ở `scope project`, nếu Sếpp đang đứng sẵn trong repo thì có thể bỏ `--cwd`
78
+ - CLI sẽ tự dùng thư mục hiện tại cho cả MCP lẫn skill
79
+ - `update` sẽ tự tính lại target project từ `--cwd` hoặc thư mục hiện tại, không dùng target lệch project nếu user không truyền `--target-dir`
80
+ - rule/agent mới đã được tăng độ ưu tiên MCP-first, giảm khả năng model nhảy thẳng sang grep/read file local
74
81
  - skill mới cũng dặn model tổng hợp từ `matched_passages`, `top_entities`, `top_relations`, `citations`; không bê nguyên `answer_brief`
75
82
 
76
83
  Ví dụ:
77
84
 
78
85
  ```bash
79
- sp-rag install --client vscode --scope project --cwd D:/Webs/seo-booster --mcp-token <grc_pat_...> --doctor
80
- sp-rag add --client cursor --scope project --cwd D:/Webs/seo-booster
81
- sp-rag mcp add antigravity
86
+ sp-rag install --client vscode --scope project --cwd D:/Webs/seo-booster --mcp-token <grc_pat_...> --doctor
87
+ sp-rag add --client cursor --scope project --cwd D:/Webs/seo-booster
88
+ sp-rag update --client vscode --scope project --cwd D:/Webs/seo-booster
89
+ sp-rag uninstall --client claude-code --scope project --cwd D:/Webs/seo-booster
90
+ sp-rag mcp add antigravity
82
91
  sp-rag skill install --client vscode --scope project --cwd D:/Webs/seo-booster
83
92
  sp-rag token add --token <grc_pat_moi>
84
93
  sp-rag explain --client vscode --scope project --cwd D:/Webs/seo-booster
@@ -186,7 +195,8 @@ Ghi chú:
186
195
  ### Skill / rule / custom agent
187
196
 
188
197
  - `codex`: `~/.codex/skills/sp-rag/SKILL.md`
189
- - `claude-code`: `~/.claude/skills/sp-rag/SKILL.md`
198
+ - `claude-code` project: `.claude/skills/sp-rag/SKILL.md`
199
+ - `claude-code` global skill-only override: `~/.claude/skills/sp-rag/SKILL.md`
190
200
  - `antigravity`: `~/.gemini/antigravity/skills/sp-rag/SKILL.md`
191
201
  - `opencode`: `~/.config/opencode/skills/sp-rag/SKILL.md`
192
202
  - `cursor` project: `.cursor/rules/sp-rag.mdc`
@@ -197,8 +207,10 @@ Ghi chú:
197
207
 
198
208
  ```bash
199
209
  sp-rag install --client codex --mcp-token <grc_pat_...> --doctor
200
- sp-rag add --client cursor --scope project --cwd D:/Webs/seo-booster
201
- sp-rag explain --client codex
210
+ sp-rag add --client cursor --scope project --cwd D:/Webs/seo-booster
211
+ sp-rag update --client cursor --scope project --cwd D:/Webs/seo-booster
212
+ sp-rag uninstall --client cursor --scope project --cwd D:/Webs/seo-booster
213
+ sp-rag explain --client codex
202
214
  sp-rag token add --token <grc_pat_...>
203
215
  sp-rag token verify --token <grc_pat_...>
204
216
  sp-rag config show
@@ -212,8 +224,10 @@ sp-rag mcp add vscode --scope project --cwd D:/Webs/seo-booster
212
224
  sp-rag mcp add opencode --scope project --cwd D:/Webs/seo-booster
213
225
  sp-rag skill install --client codex
214
226
  sp-rag skill install --client cursor --scope project --cwd D:/Webs/seo-booster
215
- sp-rag skill install --client vscode --scope project --cwd D:/Webs/seo-booster
216
- sp-rag eval run --file ./examples/eval-suite.sample.json
227
+ sp-rag skill install --client vscode --scope project --cwd D:/Webs/seo-booster
228
+ sp-rag eval run --file ./examples/eval-suite.sample.json
229
+ sp-rag update --client vscode --scope project --cwd D:/Webs/seo-booster
230
+ sp-rag uninstall --client vscode --scope project --cwd D:/Webs/seo-booster
217
231
  ```
218
232
 
219
233
  ## Lệnh chính
@@ -240,8 +254,10 @@ sp-rag mcp add opencode --scope project --cwd D:/Webs/seo-booster
240
254
  sp-rag skill install --client codex
241
255
  sp-rag skill install --client cursor --scope project --cwd D:/Webs/seo-booster
242
256
  sp-rag skill install --client vscode --scope project --cwd D:/Webs/seo-booster
243
- sp-rag eval run --file ./examples/eval-suite.sample.json
244
- sp-rag update setup --client codex
257
+ sp-rag eval run --file ./examples/eval-suite.sample.json
258
+ sp-rag update --client codex
259
+ sp-rag update setup --client codex
260
+ sp-rag uninstall --client codex
245
261
  ```
246
262
 
247
263
  ## `doctor` kiểm gì
package/dist/cli.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import { readFile } from 'node:fs/promises';
2
- import { loadCliConfig, saveCliConfig, } from './lib/config-store.js';
2
+ import { clearCliConfig, loadCliConfig, saveCliConfig, } from './lib/config-store.js';
3
3
  import { runEvaluationSuite } from './lib/eval.js';
4
- import { defaultBaseUrl, defaultMcpServerAlias, defaultMcpUrl, installMcpConfig, resolveMcpConfigPath, } from './lib/mcp-config.js';
4
+ import { defaultBaseUrl, defaultMcpServerAlias, defaultMcpUrl, installMcpConfig, removeMcpConfig, resolveMcpConfigPath, } from './lib/mcp-config.js';
5
5
  import { diagnoseMcpConfig, formatMcpDoctorResult } from './lib/doctor.js';
6
6
  import { fetchJson, fetchText, runDoctor } from './lib/http.js';
7
- import { installSkill, resolveSkillInstallTarget, } from './lib/skill.js';
7
+ import { installSkill, removeSkill, resolveSkillInstallTarget, } from './lib/skill.js';
8
8
  let cliVersionPromise;
9
9
  async function resolveCliVersion() {
10
10
  if (!cliVersionPromise) {
@@ -205,9 +205,11 @@ function helpText() {
205
205
  return `sp-rag - CLI cho setup, MCP, codegraph, eval và skill của SP-RAG
206
206
 
207
207
  Lệnh chính:
208
- sp-rag install --client codex|cursor|claude-code|antigravity|vscode|opencode [--base-url URL] [--mcp-url URL] [--scope global|project] [--mcp-token TOKEN] [--auth-env-var ENV_VAR] [--target-dir PATH] [--doctor]
209
- sp-rag add --client codex|cursor|claude-code|antigravity|vscode|opencode [--scope global|project] [--cwd PATH] [--target-dir PATH]
210
- sp-rag init [--base-url URL] [--mcp-url URL] [--client codex|cursor|claude-code|antigravity|vscode|opencode] [--skill-client codex|cursor|claude-code|antigravity|vscode|opencode] [--scope global|project] [--auth-env-var ENV_VAR] [--target-dir PATH]
208
+ sp-rag install --client codex|cursor|claude-code|antigravity|vscode|opencode [--base-url URL] [--mcp-url URL] [--scope global|project] [--mcp-token TOKEN] [--auth-env-var ENV_VAR] [--target-dir PATH] [--doctor]
209
+ sp-rag add --client codex|cursor|claude-code|antigravity|vscode|opencode [--scope global|project] [--cwd PATH] [--target-dir PATH]
210
+ sp-rag update [--client codex|cursor|claude-code|antigravity|vscode|opencode] [--scope global|project] [--cwd PATH] [--target-dir PATH] [--doctor]
211
+ sp-rag uninstall [--client codex|cursor|claude-code|antigravity|vscode|opencode] [--scope global|project] [--cwd PATH] [--target-dir PATH]
212
+ sp-rag init [--base-url URL] [--mcp-url URL] [--client codex|cursor|claude-code|antigravity|vscode|opencode] [--skill-client codex|cursor|claude-code|antigravity|vscode|opencode] [--scope global|project] [--auth-env-var ENV_VAR] [--target-dir PATH]
211
213
  sp-rag token add --token TOKEN
212
214
  sp-rag token verify [--token TOKEN] [--base-url URL]
213
215
  sp-rag config show
@@ -597,6 +599,50 @@ async function runUpdateSetup(parsed) {
597
599
  await runSkillInstall(parsed, defaults, client);
598
600
  }
599
601
  }
602
+ async function runUpdate(parsed) {
603
+ const defaults = await loadRuntimeDefaults(parsed);
604
+ const client = resolveSelectedClient(parsed, defaults);
605
+ if (!client) {
606
+ throw new Error('Thiếu client. Dùng sp-rag update --client <client>.');
607
+ }
608
+ await runClientSetup(parsed, defaults, client);
609
+ }
610
+ async function runUninstall(parsed) {
611
+ const defaults = await loadRuntimeDefaults(parsed);
612
+ const client = resolveSelectedClient(parsed, defaults);
613
+ if (!client) {
614
+ throw new Error('Thiếu client. Dùng sp-rag uninstall --client <client>.');
615
+ }
616
+ const scope = supportedScope(optionString(parsed, 'scope')) ?? defaults.defaultScope;
617
+ const mcpResult = await removeMcpConfig({
618
+ client,
619
+ url: optionString(parsed, 'url') ?? defaults.mcpUrl,
620
+ scope,
621
+ cwd: optionString(parsed, 'cwd'),
622
+ serverAlias: optionString(parsed, 'server-alias') ?? defaults.serverAlias,
623
+ });
624
+ process.stdout.write(`${mcpResult.removed ? 'Đã gỡ' : 'Không tìm thấy'} cấu hình MCP cho ${mcpResult.client} tại ${mcpResult.path} (${mcpResult.scope}).\n`);
625
+ const skillClient = resolveSelectedSkillClient(parsed, defaults, client);
626
+ if (skillClient) {
627
+ const skillResult = await removeSkill({
628
+ client: skillClient,
629
+ cwd: optionString(parsed, 'cwd'),
630
+ scope,
631
+ targetDir: optionString(parsed, 'target-dir'),
632
+ serverAlias: optionString(parsed, 'server-alias') ?? defaults.serverAlias,
633
+ mcpUrl: optionString(parsed, 'mcp-url') ?? defaults.mcpUrl,
634
+ docsUrl: optionString(parsed, 'docs-url') ?? defaults.docsUrl,
635
+ });
636
+ for (const removedPath of skillResult.removedPaths) {
637
+ process.stdout.write(`Đã gỡ skill cho ${skillResult.client} tại ${removedPath}\n`);
638
+ }
639
+ if (skillResult.removedPaths.length === 0) {
640
+ process.stdout.write(`Không tìm thấy skill cần gỡ cho ${skillResult.client}.\n`);
641
+ }
642
+ }
643
+ const configPath = await clearCliConfig(defaults.homeDir);
644
+ process.stdout.write(`Đã xóa config CLI tại ${configPath}\n`);
645
+ }
600
646
  export async function runCli(argv) {
601
647
  const parsed = parseArgv(argv);
602
648
  const [group, action] = parsed.positionals;
@@ -695,8 +741,17 @@ export async function runCli(argv) {
695
741
  if (group === 'eval' && action === 'run') {
696
742
  return runEval(parsed);
697
743
  }
698
- if (group === 'update' && action === 'setup') {
699
- await runUpdateSetup(parsed);
744
+ if (group === 'update' && (!action || action === 'setup')) {
745
+ if (action === 'setup') {
746
+ await runUpdateSetup(parsed);
747
+ }
748
+ else {
749
+ await runUpdate(parsed);
750
+ }
751
+ return 0;
752
+ }
753
+ if (group === 'uninstall') {
754
+ await runUninstall(parsed);
700
755
  return 0;
701
756
  }
702
757
  if (group === 'version') {
@@ -1,6 +1,6 @@
1
1
  import os from 'node:os';
2
2
  import path from 'node:path';
3
- import { mkdir, readFile, writeFile } from 'node:fs/promises';
3
+ import { mkdir, readFile, rm, writeFile } from 'node:fs/promises';
4
4
  function stripUndefined(value) {
5
5
  return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== undefined));
6
6
  }
@@ -37,3 +37,8 @@ export async function saveCliConfig(config, homeDir) {
37
37
  await writeFile(filePath, `${JSON.stringify(normalized, null, 2)}\n`, 'utf8');
38
38
  return filePath;
39
39
  }
40
+ export async function clearCliConfig(homeDir) {
41
+ const filePath = resolveCliConfigPath(homeDir);
42
+ await rm(filePath, { force: true });
43
+ return filePath;
44
+ }
@@ -85,6 +85,30 @@ function upsertObjectEntryPreservingAliasByEndpoint(base, sectionKey, entryKey,
85
85
  [sectionKey]: section,
86
86
  };
87
87
  }
88
+ function removeObjectEntryByAliasOrEndpoint(base, sectionKey, entryKey, endpointKey, endpointValue) {
89
+ const section = base[sectionKey] && typeof base[sectionKey] === 'object'
90
+ ? { ...base[sectionKey] }
91
+ : {};
92
+ const targetEndpoint = normalizeEndpoint(endpointValue);
93
+ let removed = false;
94
+ for (const [alias, value] of Object.entries(section)) {
95
+ if (!value || typeof value !== 'object') {
96
+ continue;
97
+ }
98
+ const candidateEndpoint = normalizeEndpoint(value[endpointKey]);
99
+ if (alias === entryKey || (targetEndpoint && candidateEndpoint === targetEndpoint)) {
100
+ delete section[alias];
101
+ removed = true;
102
+ }
103
+ }
104
+ return {
105
+ next: {
106
+ ...base,
107
+ [sectionKey]: section,
108
+ },
109
+ removed,
110
+ };
111
+ }
88
112
  function vscodeGlobalConfigPath(home) {
89
113
  if (process.platform === 'win32') {
90
114
  const appData = process.env['APPDATA']?.trim() || path.join(home, 'AppData', 'Roaming');
@@ -122,6 +146,23 @@ export function upsertCodexConfig(existing, options) {
122
146
  }
123
147
  return `${cleaned ? `${cleaned}\n\n` : ''}${lines.join('\n')}\n`;
124
148
  }
149
+ export function removeCodexConfigContent(existing, serverAlias) {
150
+ const alias = serverAlias.trim();
151
+ const aliasPattern = escapeRegex(alias);
152
+ let removed = false;
153
+ const withoutHeaders = existing.replace(new RegExp(`(?:^|\\n)\\[mcp_servers\\.(?:"${aliasPattern}"|${aliasPattern})\\.headers\\][\\s\\S]*?(?=(?:\\n\\[[^\\n]+\\])|$)`, 'g'), () => {
154
+ removed = true;
155
+ return '';
156
+ });
157
+ const cleaned = withoutHeaders.replace(new RegExp(`(?:^|\\n)\\[mcp_servers\\.(?:"${aliasPattern}"|${aliasPattern})\\][\\s\\S]*?(?=(?:\\n\\[[^\\n]+\\])|$)`, 'g'), () => {
158
+ removed = true;
159
+ return '';
160
+ });
161
+ return {
162
+ content: `${cleaned.trimEnd()}${cleaned.trimEnd() ? '\n' : ''}`,
163
+ removed,
164
+ };
165
+ }
125
166
  export function upsertJsonMcpConfig(existing, options) {
126
167
  const base = parseJsonObject(existing);
127
168
  const serverConfig = withHeaders({
@@ -279,3 +320,58 @@ export async function installMcpConfig(options) {
279
320
  await writeFile(resolved.path, content, 'utf8');
280
321
  return resolved;
281
322
  }
323
+ export async function removeMcpConfig(options) {
324
+ const resolved = resolveMcpConfigPath(options);
325
+ const existing = await readFile(resolved.path, 'utf8').catch((error) => {
326
+ if (error.code === 'ENOENT') {
327
+ return '';
328
+ }
329
+ throw error;
330
+ });
331
+ const alias = options.serverAlias?.trim() || defaultMcpServerAlias();
332
+ const url = options.url.trim();
333
+ let content = existing;
334
+ let removed = false;
335
+ if (existing.trim()) {
336
+ switch (resolved.client) {
337
+ case 'codex': {
338
+ const result = removeCodexConfigContent(existing, alias);
339
+ content = result.content;
340
+ removed = result.removed;
341
+ break;
342
+ }
343
+ case 'cursor':
344
+ case 'claude-code': {
345
+ const result = removeObjectEntryByAliasOrEndpoint(parseJsonObject(existing), 'mcpServers', alias, 'url', url);
346
+ content = `${JSON.stringify(result.next, null, 2)}\n`;
347
+ removed = result.removed;
348
+ break;
349
+ }
350
+ case 'antigravity': {
351
+ const result = removeObjectEntryByAliasOrEndpoint(parseJsonObject(existing), 'mcpServers', alias, 'serverUrl', url);
352
+ content = `${JSON.stringify(result.next, null, 2)}\n`;
353
+ removed = result.removed;
354
+ break;
355
+ }
356
+ case 'vscode': {
357
+ const result = removeObjectEntryByAliasOrEndpoint(parseJsonObject(existing), 'servers', alias, 'url', url);
358
+ content = `${JSON.stringify(result.next, null, 2)}\n`;
359
+ removed = result.removed;
360
+ break;
361
+ }
362
+ case 'opencode': {
363
+ const result = removeObjectEntryByAliasOrEndpoint(parseJsonObject(existing), 'mcp', alias, 'url', url);
364
+ content = `${JSON.stringify(result.next, null, 2)}\n`;
365
+ removed = result.removed;
366
+ break;
367
+ }
368
+ }
369
+ }
370
+ if (removed) {
371
+ await writeFile(resolved.path, content, 'utf8');
372
+ }
373
+ return {
374
+ ...resolved,
375
+ removed,
376
+ };
377
+ }
package/dist/lib/skill.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import os from 'node:os';
2
2
  import path from 'node:path';
3
- import { mkdir, writeFile } from 'node:fs/promises';
3
+ import { mkdir, readFile, rm, writeFile } from 'node:fs/promises';
4
4
  const seoBoosterRemoteUrl = 'https://gitlab.com/secomapp/development/seo-booster.git';
5
5
  const seoBoosterProjectGuard = [
6
6
  '- SP-RAG chỉ dành cho repo seo-booster.',
@@ -260,6 +260,41 @@ export async function installSkill(options = {}) {
260
260
  paths,
261
261
  };
262
262
  }
263
+ async function removeIfSpRagArtifact(filePath) {
264
+ const content = await readFile(filePath, 'utf8').catch((error) => {
265
+ if (error.code === 'ENOENT') {
266
+ return null;
267
+ }
268
+ throw error;
269
+ });
270
+ if (content === null) {
271
+ return false;
272
+ }
273
+ if (!content.includes('SP-RAG') && !content.includes('sp-rag')) {
274
+ return false;
275
+ }
276
+ await rm(filePath, { force: true });
277
+ return true;
278
+ }
279
+ export async function removeSkill(options = {}) {
280
+ const resolved = resolveSkillInstallTarget(options);
281
+ const context = createSkillContext(options, resolved.client);
282
+ const paths = [
283
+ resolved.path,
284
+ ...resolveAdditionalSkillArtifacts(options, resolved, context).map((entry) => entry.path),
285
+ ];
286
+ const removedPaths = [];
287
+ for (const filePath of paths) {
288
+ if (await removeIfSpRagArtifact(filePath)) {
289
+ removedPaths.push(filePath);
290
+ }
291
+ }
292
+ return {
293
+ client: resolved.client,
294
+ paths,
295
+ removedPaths,
296
+ };
297
+ }
263
298
  export async function installCodexSkill(options = {}) {
264
299
  return installSkill({
265
300
  ...options,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sp-rag",
3
- "version": "0.6.11",
3
+ "version": "0.6.12",
4
4
  "description": "CLI cho setup MCP, codegraph GitNexus và skill của SP-RAG",
5
5
  "type": "module",
6
6
  "files": [