@moon791017/neo-skills 1.0.8 → 1.0.10
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 +19 -8
- package/bin/_utils.js +141 -0
- package/bin/install-claude-skills.js +4 -81
- package/bin/install-copilot-skills.js +7 -0
- package/bin/install-skills.js +55 -0
- package/gemini-extension.json +1 -1
- package/package.json +5 -3
package/README.md
CHANGED
|
@@ -68,19 +68,30 @@
|
|
|
68
68
|
|
|
69
69
|
本套件支援多種 AI Agent 環境。請依據您的 CLI 工具執行對應指令:
|
|
70
70
|
|
|
71
|
-
###
|
|
71
|
+
### Gemini CLI
|
|
72
72
|
|
|
73
73
|
```bash
|
|
74
74
|
gemini extension install https://github.com/Benknightdark/neo-skills --auto-update
|
|
75
75
|
```
|
|
76
76
|
|
|
77
|
-
###
|
|
77
|
+
### Claude Code
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
npx -p @moon791017/neo-skills install-claude-skills
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Copilot CLI
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
npx -p @moon791017/neo-skills install-copilot-skills
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### 安裝全部AI Agent技能
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
npx -p @moon791017/neo-skills install-skills
|
|
93
|
+
```
|
|
78
94
|
|
|
79
|
-
| 說明 | 執行指令 |
|
|
80
|
-
| :--- | :--- |
|
|
81
|
-
| Claude 內建外掛安裝 | `claude plugin add https://github.com/Benknightdark/neo-skills` |
|
|
82
|
-
| 透過 `npx` 執行安裝腳本 | `npx @moon791017/neo-skills install-claude-skills` |
|
|
83
|
-
| `npm` 全域安裝後執行 | `npm i @moon791017/neo-skills -g` <br> `install-claude-skills` |
|
|
84
95
|
|
|
85
96
|
## 💡 常用指令範例
|
|
86
97
|
|
|
@@ -127,4 +138,4 @@ gemini extension install https://github.com/Benknightdark/neo-skills --auto-upda
|
|
|
127
138
|
4. **類型檢查**
|
|
128
139
|
```bash
|
|
129
140
|
bun run typecheck
|
|
130
|
-
```
|
|
141
|
+
```
|
package/bin/_utils.js
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared utilities for agent skill installers.
|
|
3
|
+
*
|
|
4
|
+
* 新增 AI agent 只需兩步:
|
|
5
|
+
* 1. 在 AGENTS 加入設定
|
|
6
|
+
* 2. 建立 bin/install-{key}-skills.js(複製任一現有檔案,改 named export 即可)
|
|
7
|
+
*/
|
|
8
|
+
import { realpathSync } from 'node:fs';
|
|
9
|
+
import { cp, mkdir, access } from 'node:fs/promises';
|
|
10
|
+
import { join, resolve, dirname, basename } from 'node:path';
|
|
11
|
+
import { homedir } from 'node:os';
|
|
12
|
+
import { fileURLToPath } from 'node:url';
|
|
13
|
+
|
|
14
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
15
|
+
const __dirname = dirname(__filename);
|
|
16
|
+
const packageRoot = resolve(__dirname, '..');
|
|
17
|
+
const sourceDir = join(packageRoot, 'skills');
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Agent 設定中心 — 所有 agent 的安裝參數集中管理於此。
|
|
21
|
+
* key 須與檔名 install-{key}-skills.js 一致。
|
|
22
|
+
*/
|
|
23
|
+
export const AGENTS = {
|
|
24
|
+
claude: {
|
|
25
|
+
name: 'Claude',
|
|
26
|
+
targetSubDir: '.claude/skills',
|
|
27
|
+
hint: '請確保您的 Claude Desktop 或相關插件已指向此目錄。',
|
|
28
|
+
},
|
|
29
|
+
copilot: {
|
|
30
|
+
name: 'Copilot',
|
|
31
|
+
targetSubDir: '.copilot/skills',
|
|
32
|
+
hint: '請確保您的 GitHub Copilot CLI 已指向此目錄。',
|
|
33
|
+
},
|
|
34
|
+
// gemini: {
|
|
35
|
+
// name: 'Gemini',
|
|
36
|
+
// targetSubDir: '.gemini/skills',
|
|
37
|
+
// hint: '請確保您的 Gemini CLI 已指向此目錄。',
|
|
38
|
+
// },
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* 從檔名解析 agent key: install-{key}-skills.js → key
|
|
43
|
+
*/
|
|
44
|
+
function extractAgentKey(importMetaUrl) {
|
|
45
|
+
const filename = basename(fileURLToPath(importMetaUrl), '.js');
|
|
46
|
+
const match = filename.match(/^install-(.+)-skills$/);
|
|
47
|
+
if (!match) throw new Error(`無法從檔名 "${filename}" 解析 agent key`);
|
|
48
|
+
return match[1];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* 根據 agent config 建立 installer 函式
|
|
53
|
+
*/
|
|
54
|
+
export function createInstaller({ name: agentName, targetSubDir, hint }) {
|
|
55
|
+
return async function install() {
|
|
56
|
+
console.log(`🚀 [${agentName}] 開始同步 Neo Skills...`);
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
await access(sourceDir);
|
|
60
|
+
} catch {
|
|
61
|
+
const msg = `在 ${sourceDir} 找不到來源技能目錄。`;
|
|
62
|
+
console.error(`❌ 錯誤: ${msg}`);
|
|
63
|
+
return { success: false, message: msg };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const targetSkillsDir = join(homedir(), targetSubDir);
|
|
67
|
+
|
|
68
|
+
console.log(`📁 來源路徑: ${sourceDir}`);
|
|
69
|
+
console.log(`🎯 目標路徑: ${targetSkillsDir}`);
|
|
70
|
+
|
|
71
|
+
await mkdir(targetSkillsDir, { recursive: true });
|
|
72
|
+
|
|
73
|
+
let copyCount = 0;
|
|
74
|
+
await cp(sourceDir, targetSkillsDir, {
|
|
75
|
+
recursive: true,
|
|
76
|
+
force: true,
|
|
77
|
+
filter: (src) => {
|
|
78
|
+
const relativePath = src.replace(sourceDir, '');
|
|
79
|
+
const isIgnored = relativePath.includes('node_modules') || relativePath.includes('.git');
|
|
80
|
+
if (!isIgnored) { copyCount++; return true; }
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
if (copyCount === 0) {
|
|
86
|
+
console.warn('⚠️ 警告: 沒有任何檔案被複製。請檢查來源目錄是否正確。');
|
|
87
|
+
return { success: true, message: '沒有任何檔案被複製' };
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const msg = `已同步 ${copyCount} 個檔案/資料夾至 ${targetSubDir}`;
|
|
91
|
+
console.log(`✅ [${agentName}] 安裝成功!${msg}`);
|
|
92
|
+
if (hint) console.log(`💡 提示: ${hint}`);
|
|
93
|
+
return { success: true, message: msg };
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* 從呼叫端的檔名自動解析 agent,建立對應的 installer。
|
|
99
|
+
* @param {string} importMetaUrl - 呼叫端的 import.meta.url
|
|
100
|
+
*/
|
|
101
|
+
export function createInstallerFromFile(importMetaUrl) {
|
|
102
|
+
const key = extractAgentKey(importMetaUrl);
|
|
103
|
+
const config = AGENTS[key];
|
|
104
|
+
if (!config) throw new Error(`未知的 agent: "${key}"。請在 _utils.js 的 AGENTS 中註冊。`);
|
|
105
|
+
return createInstaller(config);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* 當腳本被直接執行時(非 import),自動呼叫 installer。
|
|
110
|
+
* Agent 名稱從檔名自動推導。
|
|
111
|
+
* @param {() => Promise<{ success: boolean, message: string }>} installFn
|
|
112
|
+
* @param {string} callerUrl - 呼叫端的 import.meta.url
|
|
113
|
+
*/
|
|
114
|
+
export function runAsMain(installFn, callerUrl) {
|
|
115
|
+
const callerPath = fileURLToPath(callerUrl);
|
|
116
|
+
const argvPath = process.argv[1];
|
|
117
|
+
const isMain = Boolean(argvPath) && (
|
|
118
|
+
resolve(argvPath) === resolve(callerPath) ||
|
|
119
|
+
realpathSync.native(resolve(argvPath)) === realpathSync.native(resolve(callerPath))
|
|
120
|
+
);
|
|
121
|
+
if (!isMain) return;
|
|
122
|
+
|
|
123
|
+
const key = extractAgentKey(callerUrl);
|
|
124
|
+
const agentName = AGENTS[key]?.name || key;
|
|
125
|
+
|
|
126
|
+
process.on('uncaughtException', (err) => {
|
|
127
|
+
console.error('💥 [Fatal Error]:', err);
|
|
128
|
+
process.exit(1);
|
|
129
|
+
});
|
|
130
|
+
process.on('unhandledRejection', (reason) => {
|
|
131
|
+
console.error('💥 [Unhandled Rejection]:', reason);
|
|
132
|
+
process.exit(1);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
installFn().then((result) => {
|
|
136
|
+
if (!result.success) process.exit(1);
|
|
137
|
+
}).catch((error) => {
|
|
138
|
+
console.error(`❌ [${agentName}] 安裝失敗:`, error.message || error);
|
|
139
|
+
process.exit(1);
|
|
140
|
+
});
|
|
141
|
+
}
|
|
@@ -1,84 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
import { join, resolve, dirname } from 'node:path';
|
|
4
|
-
import { homedir } from 'node:os';
|
|
5
|
-
import { fileURLToPath } from 'node:url';
|
|
2
|
+
import { createInstallerFromFile, runAsMain } from './_utils.js';
|
|
6
3
|
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
export const install = createInstallerFromFile(import.meta.url);
|
|
5
|
+
export { install as installClaudeSkills };
|
|
9
6
|
|
|
10
|
-
|
|
11
|
-
process.on('uncaughtException', (err) => {
|
|
12
|
-
console.error('💥 [Fatal Error]:', err);
|
|
13
|
-
process.exit(1);
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
process.on('unhandledRejection', (reason, promise) => {
|
|
17
|
-
console.error('💥 [Unhandled Rejection]:', reason);
|
|
18
|
-
process.exit(1);
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
// 取得當前檔案路徑
|
|
22
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
23
|
-
const __dirname = dirname(__filename);
|
|
24
|
-
|
|
25
|
-
async function installClaudeSkills() {
|
|
26
|
-
try {
|
|
27
|
-
// 1. 定義來源目錄: 腳本所在目錄的上一層的 skills 資料夾
|
|
28
|
-
// 當透過 npx 執行時,它會指向臨時下載的 package 內容
|
|
29
|
-
const packageRoot = resolve(__dirname, '..');
|
|
30
|
-
const sourceDir = join(packageRoot, 'skills');
|
|
31
|
-
|
|
32
|
-
// 2. 定義目標目錄: ~/.claude/skills (跨平台自動處理)
|
|
33
|
-
const targetBaseDir = join(homedir(), '.claude');
|
|
34
|
-
const targetSkillsDir = join(targetBaseDir, 'skills');
|
|
35
|
-
|
|
36
|
-
console.log('🚀 [Claude] 開始同步 Neo Skills...');
|
|
37
|
-
|
|
38
|
-
// 檢查來源是否存在
|
|
39
|
-
try {
|
|
40
|
-
await access(sourceDir);
|
|
41
|
-
} catch {
|
|
42
|
-
console.error(`❌ 錯誤: 在 ${sourceDir} 找不到來源技能目錄。`);
|
|
43
|
-
process.exit(1);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
console.log(`📁 來源路徑: ${sourceDir}`);
|
|
47
|
-
console.log(`🎯 目標路徑: ${targetSkillsDir}`);
|
|
48
|
-
|
|
49
|
-
// 3. 確保目標目錄存在 (recursive: true 會自動建立多層目錄)
|
|
50
|
-
await mkdir(targetSkillsDir, { recursive: true });
|
|
51
|
-
|
|
52
|
-
// 4. 執行複製
|
|
53
|
-
let copyCount = 0;
|
|
54
|
-
await cp(sourceDir, targetSkillsDir, {
|
|
55
|
-
recursive: true,
|
|
56
|
-
force: true,
|
|
57
|
-
// 過濾掉不必要的開發檔案
|
|
58
|
-
filter: (src) => {
|
|
59
|
-
// 取得相對於來源目錄的路徑
|
|
60
|
-
const relativePath = src.replace(sourceDir, '');
|
|
61
|
-
const isIgnored = relativePath.includes('node_modules') || relativePath.includes('.git');
|
|
62
|
-
|
|
63
|
-
if (!isIgnored) {
|
|
64
|
-
copyCount++;
|
|
65
|
-
return true;
|
|
66
|
-
}
|
|
67
|
-
return false;
|
|
68
|
-
}
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
if (copyCount === 0) {
|
|
72
|
-
console.warn('⚠️ 警告: 沒有任何檔案被複製。請檢查來源目錄是否正確。');
|
|
73
|
-
} else {
|
|
74
|
-
console.log(`✅ [Claude] 安裝成功!已同步 ${copyCount} 個檔案/資料夾至 .claude/skills`);
|
|
75
|
-
}
|
|
76
|
-
console.log('💡 提示: 請確保您的 Claude Desktop 或相關插件已指向此目錄。');
|
|
77
|
-
|
|
78
|
-
} catch (error) {
|
|
79
|
-
console.error('❌ [Claude] 安裝失敗:', error.message || error);
|
|
80
|
-
process.exit(1);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
installClaudeSkills();
|
|
7
|
+
runAsMain(install, import.meta.url);
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { AGENTS, createInstaller } from './_utils.js';
|
|
3
|
+
|
|
4
|
+
process.on('uncaughtException', (err) => {
|
|
5
|
+
console.error('💥 [Fatal Error]:', err);
|
|
6
|
+
process.exit(1);
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
process.on('unhandledRejection', (reason) => {
|
|
10
|
+
console.error('💥 [Unhandled Rejection]:', reason);
|
|
11
|
+
process.exit(1);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
async function main() {
|
|
15
|
+
console.log('╔══════════════════════════════════════════╗');
|
|
16
|
+
console.log('║ 🧠 Neo Skills — 統一安裝程式 ║');
|
|
17
|
+
console.log('╚══════════════════════════════════════════╝');
|
|
18
|
+
console.log('');
|
|
19
|
+
|
|
20
|
+
const results = [];
|
|
21
|
+
|
|
22
|
+
for (const [key, config] of Object.entries(AGENTS)) {
|
|
23
|
+
console.log(`━━━ 正在安裝: ${config.name} ━━━`);
|
|
24
|
+
try {
|
|
25
|
+
const installFn = createInstaller(config);
|
|
26
|
+
const result = await installFn();
|
|
27
|
+
results.push({ name: config.name, ...result });
|
|
28
|
+
} catch (error) {
|
|
29
|
+
console.error(`❌ [${config.name}] 安裝失敗:`, error.message || error);
|
|
30
|
+
results.push({ name: config.name, success: false, message: error.message || String(error) });
|
|
31
|
+
}
|
|
32
|
+
console.log('');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// 彙總報告
|
|
36
|
+
console.log('══════════════════════════════════════════');
|
|
37
|
+
console.log('📊 安裝結果彙總:');
|
|
38
|
+
const failed = results.filter(r => !r.success);
|
|
39
|
+
|
|
40
|
+
for (const r of results) {
|
|
41
|
+
console.log(` ${r.success ? '✅' : '❌'} ${r.name}: ${r.message}`);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
console.log('');
|
|
45
|
+
console.log(`成功: ${results.length - failed.length} / ${results.length}`);
|
|
46
|
+
|
|
47
|
+
if (failed.length > 0) {
|
|
48
|
+
console.log(`失敗: ${failed.length} — ${failed.map(r => r.name).join(', ')}`);
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
console.log('🎉 全部安裝完成!');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
main();
|
package/gemini-extension.json
CHANGED
package/package.json
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moon791017/neo-skills",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.10",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Neo Skills: A Universal Expert Agent Extension",
|
|
6
6
|
"bin": {
|
|
7
|
-
"neo-skills": "./bin/install-
|
|
8
|
-
"install-
|
|
7
|
+
"neo-skills": "./bin/install-skills.js",
|
|
8
|
+
"install-skills": "./bin/install-skills.js",
|
|
9
|
+
"install-claude-skills": "./bin/install-claude-skills.js",
|
|
10
|
+
"install-copilot-skills": "./bin/install-copilot-skills.js"
|
|
9
11
|
},
|
|
10
12
|
"files": [
|
|
11
13
|
"dist",
|