@catcuts-skills/commit 1.0.1 → 1.0.4
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 +32 -3
- package/package.json +3 -3
- package/scripts/install-skill.js +121 -5
- package/scripts/uninstall-skill.js +128 -20
- package/scripts/usage-guide.js +75 -0
package/README.md
CHANGED
|
@@ -61,15 +61,44 @@ npm test
|
|
|
61
61
|
|
|
62
62
|
### 卸载
|
|
63
63
|
|
|
64
|
+
**重要**:由于 npm 的限制,全局卸载时 preuninstall hook 可能不会执行。请按照以下步骤正确卸载:
|
|
65
|
+
|
|
66
|
+
#### 方式 1:使用 npm scripts(推荐)
|
|
67
|
+
|
|
64
68
|
```bash
|
|
65
69
|
# 全局卸载
|
|
66
|
-
npm uninstall
|
|
70
|
+
npm run uninstall:global
|
|
71
|
+
npm uninstall -g @catcuts-skills/commit
|
|
67
72
|
|
|
68
73
|
# 项目级卸载
|
|
69
|
-
npm uninstall
|
|
74
|
+
npm run uninstall:local
|
|
75
|
+
npm uninstall @catcuts-skills/commit
|
|
70
76
|
```
|
|
71
77
|
|
|
72
|
-
|
|
78
|
+
#### 方式 2:手动清理(如果方式 1 失败)
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
# 1. 清理技能文件
|
|
82
|
+
rm -rf ~/.claude/skills/commit
|
|
83
|
+
rm -rf ~/.agents/skills/commit
|
|
84
|
+
|
|
85
|
+
# 2. 卸载 npm 包
|
|
86
|
+
npm uninstall -g @catcuts-skills/commit
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**Windows PowerShell**:
|
|
90
|
+
```powershell
|
|
91
|
+
# 1. 清理技能文件
|
|
92
|
+
Remove-Item -Recurse -Force "$env:USERPROFILE\.claude\skills\commit"
|
|
93
|
+
Remove-Item -Recurse -Force "$env:USERPROFILE\.agents\skills\commit"
|
|
94
|
+
|
|
95
|
+
# 2. 卸载 npm 包
|
|
96
|
+
npm uninstall -g @catcuts-skills/commit
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
#### 为什么需要两步?
|
|
100
|
+
|
|
101
|
+
npm 的 `preuninstall` hook 在全局卸载时**不保证被执行**,这是 npm 的已知限制。因此需要先手动清理技能文件,再卸载 npm 包。
|
|
73
102
|
|
|
74
103
|
## 使用示例
|
|
75
104
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@catcuts-skills/commit",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "读取 staged 代码差异,自动生成符合 Conventional Commits 规范的提交文本",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"scripts/"
|
|
16
16
|
],
|
|
17
17
|
"optionalDependencies": {
|
|
18
|
-
"
|
|
18
|
+
"skills": "^1.1.2"
|
|
19
19
|
},
|
|
20
20
|
"keywords": [
|
|
21
21
|
"claude-code",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"bugs": {
|
|
35
35
|
"url": "https://github.com/catcuts/agent-skills/issues"
|
|
36
36
|
},
|
|
37
|
-
"homepage": "https://github.com/catcuts/agent-skills#readme",
|
|
37
|
+
"homepage": "https://github.com/catcuts/agent-skills/tree/main/skills/commit#readme",
|
|
38
38
|
"engines": {
|
|
39
39
|
"node": ">=18.0.0"
|
|
40
40
|
}
|
package/scripts/install-skill.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Commit Skill Installation Script
|
|
5
|
-
* Install skill to Claude Code using
|
|
5
|
+
* Install skill to Claude Code using skills
|
|
6
6
|
*
|
|
7
7
|
* Command Line Arguments (Recommended):
|
|
8
8
|
* --dry-run: Test mode, show command without executing
|
|
@@ -15,14 +15,32 @@
|
|
|
15
15
|
|
|
16
16
|
const { execSync } = require('child_process');
|
|
17
17
|
const path = require('path');
|
|
18
|
+
const fs = require('fs');
|
|
19
|
+
const os = require('os');
|
|
20
|
+
const { printUsageGuide } = require('./usage-guide');
|
|
18
21
|
|
|
19
22
|
// Get package root directory
|
|
20
23
|
const packageRoot = path.resolve(__dirname, '..');
|
|
21
24
|
|
|
25
|
+
// Get user home directory
|
|
26
|
+
const homeDir = os.homedir();
|
|
27
|
+
|
|
22
28
|
// Read package.json to get skill name
|
|
23
29
|
const packageJson = require(path.join(packageRoot, 'package.json'));
|
|
24
30
|
const skillName = packageJson.name.split('/')[1] || packageJson.name;
|
|
25
31
|
|
|
32
|
+
// Paths to clean
|
|
33
|
+
const pathsToClean = {
|
|
34
|
+
// skills CLI canonical copy directory (root cause of the issue)
|
|
35
|
+
canonical: path.join(homeDir, '.agents', 'skills', skillName),
|
|
36
|
+
|
|
37
|
+
// Claude Code global skill directory (symlink)
|
|
38
|
+
claudeGlobal: path.join(homeDir, '.claude', 'skills', skillName),
|
|
39
|
+
|
|
40
|
+
// Claude Code project-level skill directory (if exists)
|
|
41
|
+
claudeLocal: path.join(process.cwd(), '.claude', 'skills', skillName),
|
|
42
|
+
};
|
|
43
|
+
|
|
26
44
|
// Parse command line arguments
|
|
27
45
|
const args = process.argv.slice(2);
|
|
28
46
|
const dryRun = args.includes('--dry-run');
|
|
@@ -53,11 +71,102 @@ function log(message, type = 'info') {
|
|
|
53
71
|
console.log(`${prefix} ${message}`);
|
|
54
72
|
}
|
|
55
73
|
|
|
74
|
+
// Safely remove a path (supports symlinks, files, directories)
|
|
75
|
+
function safeRemovePath(filePath, description) {
|
|
76
|
+
try {
|
|
77
|
+
if (!fs.existsSync(filePath)) {
|
|
78
|
+
return { success: true, removed: false, message: 'Not found' };
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const stats = fs.lstatSync(filePath);
|
|
82
|
+
const isLink = stats.isSymbolicLink();
|
|
83
|
+
const isDir = stats.isDirectory();
|
|
84
|
+
|
|
85
|
+
if (isLink) {
|
|
86
|
+
fs.unlinkSync(filePath);
|
|
87
|
+
return {
|
|
88
|
+
success: true,
|
|
89
|
+
removed: true,
|
|
90
|
+
message: `Removed symlink: ${description}`
|
|
91
|
+
};
|
|
92
|
+
} else if (isDir) {
|
|
93
|
+
fs.rmSync(filePath, { recursive: true, force: true });
|
|
94
|
+
return {
|
|
95
|
+
success: true,
|
|
96
|
+
removed: true,
|
|
97
|
+
message: `Removed directory: ${description}`
|
|
98
|
+
};
|
|
99
|
+
} else {
|
|
100
|
+
fs.unlinkSync(filePath);
|
|
101
|
+
return {
|
|
102
|
+
success: true,
|
|
103
|
+
removed: true,
|
|
104
|
+
message: `Removed file: ${description}`
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
} catch (error) {
|
|
108
|
+
return {
|
|
109
|
+
success: false,
|
|
110
|
+
removed: false,
|
|
111
|
+
message: `Failed to remove: ${error.message}`
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Clean old installation files
|
|
117
|
+
function cleanOldInstallations() {
|
|
118
|
+
log('\nCleaning up old installation files...', 'info');
|
|
119
|
+
|
|
120
|
+
const results = [];
|
|
121
|
+
|
|
122
|
+
// 1. Clean canonical copy directory (.agents/skills/<skill>)
|
|
123
|
+
const canonicalResult = safeRemovePath(
|
|
124
|
+
pathsToClean.canonical,
|
|
125
|
+
'canonical copy'
|
|
126
|
+
);
|
|
127
|
+
results.push({ path: pathsToClean.canonical, ...canonicalResult });
|
|
128
|
+
|
|
129
|
+
// 2. Clean Claude Code global symlink
|
|
130
|
+
const globalResult = safeRemovePath(
|
|
131
|
+
pathsToClean.claudeGlobal,
|
|
132
|
+
'global skill link'
|
|
133
|
+
);
|
|
134
|
+
results.push({ path: pathsToClean.claudeGlobal, ...globalResult });
|
|
135
|
+
|
|
136
|
+
// 3. Clean Claude Code project-level installation (if exists)
|
|
137
|
+
const localResult = safeRemovePath(
|
|
138
|
+
pathsToClean.claudeLocal,
|
|
139
|
+
'project-level skill'
|
|
140
|
+
);
|
|
141
|
+
results.push({ path: pathsToClean.claudeLocal, ...localResult });
|
|
142
|
+
|
|
143
|
+
// Output cleanup results
|
|
144
|
+
let removedCount = 0;
|
|
145
|
+
results.forEach((result) => {
|
|
146
|
+
if (result.removed) {
|
|
147
|
+
log(` ✓ ${result.message}`, 'success');
|
|
148
|
+
removedCount++;
|
|
149
|
+
} else if (result.success) {
|
|
150
|
+
log(` ⊗ ${result.message} (skipped)`, 'info');
|
|
151
|
+
} else {
|
|
152
|
+
log(` ✗ ${result.message}`, 'warning');
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
if (removedCount > 0) {
|
|
157
|
+
log(`\nCleaned up ${removedCount} old installation(s)`, 'success');
|
|
158
|
+
} else {
|
|
159
|
+
log('No old installations found to clean', 'info');
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return removedCount > 0;
|
|
163
|
+
}
|
|
164
|
+
|
|
56
165
|
// Error handler
|
|
57
166
|
function handleError(error) {
|
|
58
167
|
log(`Installation failed: ${error.message}`, 'error');
|
|
59
168
|
log('\nYou can try manual installation:', 'warning');
|
|
60
|
-
log(` npx add
|
|
169
|
+
log(` npx skills add "${packageRoot}" ${isGlobal ? '-g' : ''} -y`);
|
|
61
170
|
process.exit(1);
|
|
62
171
|
}
|
|
63
172
|
|
|
@@ -65,10 +174,14 @@ try {
|
|
|
65
174
|
log(`Starting installation of ${skillName}...`, 'info');
|
|
66
175
|
log(`Installation scope: ${isGlobal ? 'Global (GLOBAL)' : 'Project-level (LOCAL)'}`, 'info');
|
|
67
176
|
|
|
68
|
-
//
|
|
177
|
+
// Clean old installation files (solves incremental update file residue issue)
|
|
178
|
+
cleanOldInstallations();
|
|
179
|
+
|
|
180
|
+
// Build skills command
|
|
69
181
|
const commandParts = [
|
|
70
182
|
'npx',
|
|
71
|
-
'
|
|
183
|
+
'skills',
|
|
184
|
+
'add',
|
|
72
185
|
`"${packageRoot}"`,
|
|
73
186
|
];
|
|
74
187
|
|
|
@@ -88,7 +201,7 @@ try {
|
|
|
88
201
|
}
|
|
89
202
|
|
|
90
203
|
// Execute installation
|
|
91
|
-
log('\nExecuting add
|
|
204
|
+
log('\nExecuting skills add...', 'info');
|
|
92
205
|
execSync(command, {
|
|
93
206
|
stdio: 'inherit',
|
|
94
207
|
cwd: packageRoot
|
|
@@ -97,6 +210,9 @@ try {
|
|
|
97
210
|
log('\nInstallation successful!', 'success');
|
|
98
211
|
log(`Skill installed to: ${isGlobal ? `~/.claude/skills/${skillName}` : `.claude/skills/${skillName}`}`, 'info');
|
|
99
212
|
|
|
213
|
+
// 显示使用指南
|
|
214
|
+
printUsageGuide();
|
|
215
|
+
|
|
100
216
|
} catch (error) {
|
|
101
217
|
handleError(error);
|
|
102
218
|
}
|
|
@@ -2,7 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Commit Skill Uninstallation Script
|
|
5
|
-
* Remove installed skill files
|
|
5
|
+
* Remove installed skill files from Claude Code
|
|
6
|
+
*
|
|
7
|
+
* Command Line Arguments:
|
|
8
|
+
* --global: Force global uninstallation
|
|
9
|
+
* --local: Force project-level uninstallation
|
|
10
|
+
*
|
|
11
|
+
* Environment Variables:
|
|
12
|
+
* - SKILL_SCOPE: Installation scope, GLOBAL or LOCAL, default: GLOBAL
|
|
6
13
|
*/
|
|
7
14
|
|
|
8
15
|
const fs = require('fs');
|
|
@@ -16,6 +23,23 @@ const packageRoot = path.resolve(__dirname, '..');
|
|
|
16
23
|
const packageName = require(path.join(packageRoot, 'package.json')).name;
|
|
17
24
|
const skillName = packageName.split('/')[1] || packageName;
|
|
18
25
|
|
|
26
|
+
// Parse command line arguments
|
|
27
|
+
const args = process.argv.slice(2);
|
|
28
|
+
const forceGlobal = args.includes('--global');
|
|
29
|
+
const forceLocal = args.includes('--local');
|
|
30
|
+
|
|
31
|
+
// Determine uninstallation scope
|
|
32
|
+
let scope;
|
|
33
|
+
if (forceGlobal) {
|
|
34
|
+
scope = 'GLOBAL';
|
|
35
|
+
} else if (forceLocal) {
|
|
36
|
+
scope = 'LOCAL';
|
|
37
|
+
} else {
|
|
38
|
+
scope = (process.env.SKILL_SCOPE || 'GLOBAL').toUpperCase();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const isGlobal = scope === 'GLOBAL';
|
|
42
|
+
|
|
19
43
|
// Logging function
|
|
20
44
|
function log(message, type = 'info') {
|
|
21
45
|
const prefix = {
|
|
@@ -28,39 +52,123 @@ function log(message, type = 'info') {
|
|
|
28
52
|
console.log(`${prefix} ${message}`);
|
|
29
53
|
}
|
|
30
54
|
|
|
31
|
-
//
|
|
32
|
-
function
|
|
55
|
+
// Safely remove a path (supports symlinks, files, directories)
|
|
56
|
+
function safeRemovePath(filePath, description) {
|
|
33
57
|
try {
|
|
34
|
-
if (fs.existsSync(
|
|
35
|
-
|
|
36
|
-
|
|
58
|
+
if (!fs.existsSync(filePath)) {
|
|
59
|
+
return { success: true, removed: false, message: 'Not found' };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const stats = fs.lstatSync(filePath);
|
|
63
|
+
const isLink = stats.isSymbolicLink();
|
|
64
|
+
const isDir = stats.isDirectory();
|
|
65
|
+
|
|
66
|
+
if (isLink) {
|
|
67
|
+
fs.unlinkSync(filePath);
|
|
68
|
+
return {
|
|
69
|
+
success: true,
|
|
70
|
+
removed: true,
|
|
71
|
+
message: `Removed symlink: ${description}`
|
|
72
|
+
};
|
|
73
|
+
} else if (isDir) {
|
|
74
|
+
fs.rmSync(filePath, { recursive: true, force: true });
|
|
75
|
+
return {
|
|
76
|
+
success: true,
|
|
77
|
+
removed: true,
|
|
78
|
+
message: `Removed directory: ${description}`
|
|
79
|
+
};
|
|
37
80
|
} else {
|
|
38
|
-
|
|
81
|
+
fs.unlinkSync(filePath);
|
|
82
|
+
return {
|
|
83
|
+
success: true,
|
|
84
|
+
removed: true,
|
|
85
|
+
message: `Removed file: ${description}`
|
|
86
|
+
};
|
|
39
87
|
}
|
|
40
88
|
} catch (error) {
|
|
41
|
-
|
|
89
|
+
// Ignore "file not found" errors, may have been deleted concurrently
|
|
90
|
+
if (error.code === 'ENOENT') {
|
|
91
|
+
return { success: true, removed: false, message: 'Already removed' };
|
|
92
|
+
}
|
|
93
|
+
return {
|
|
94
|
+
success: false,
|
|
95
|
+
removed: false,
|
|
96
|
+
message: `Failed: ${error.message}`
|
|
97
|
+
};
|
|
42
98
|
}
|
|
43
99
|
}
|
|
44
100
|
|
|
45
101
|
try {
|
|
46
102
|
log(`Starting uninstallation of ${skillName}...`, 'info');
|
|
103
|
+
log(`Uninstallation scope: ${isGlobal ? 'Global (GLOBAL)' : 'Project-level (LOCAL)'}`, 'info');
|
|
104
|
+
|
|
105
|
+
log('\nCleaning up skill files...', 'info');
|
|
106
|
+
|
|
107
|
+
const results = [];
|
|
47
108
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
109
|
+
if (isGlobal) {
|
|
110
|
+
// Global uninstallation
|
|
111
|
+
const homeDir = os.homedir();
|
|
51
112
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
113
|
+
// 1. Clean canonical copy directory (.agents/skills/<skill>)
|
|
114
|
+
const canonicalResult = safeRemovePath(
|
|
115
|
+
path.join(homeDir, '.agents', 'skills', skillName),
|
|
116
|
+
'canonical copy'
|
|
117
|
+
);
|
|
118
|
+
results.push(canonicalResult);
|
|
55
119
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
120
|
+
// 2. Clean Claude Code global symlink
|
|
121
|
+
const globalResult = safeRemovePath(
|
|
122
|
+
path.join(homeDir, '.claude', 'skills', skillName),
|
|
123
|
+
'global skill link'
|
|
124
|
+
);
|
|
125
|
+
results.push(globalResult);
|
|
126
|
+
} else {
|
|
127
|
+
// Project-level uninstallation
|
|
128
|
+
const cwd = process.cwd();
|
|
59
129
|
|
|
60
|
-
|
|
61
|
-
|
|
130
|
+
// 1. Clean project-level canonical copy (if exists)
|
|
131
|
+
const canonicalResult = safeRemovePath(
|
|
132
|
+
path.join(cwd, '.agents', 'skills', skillName),
|
|
133
|
+
'project-level canonical copy'
|
|
134
|
+
);
|
|
135
|
+
results.push(canonicalResult);
|
|
62
136
|
|
|
63
|
-
|
|
137
|
+
// 2. Clean Claude Code project-level skill
|
|
138
|
+
const localResult = safeRemovePath(
|
|
139
|
+
path.join(cwd, '.claude', 'skills', skillName),
|
|
140
|
+
'project-level skill'
|
|
141
|
+
);
|
|
142
|
+
results.push(localResult);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Output cleanup results
|
|
146
|
+
let removedCount = 0;
|
|
147
|
+
let errorCount = 0;
|
|
148
|
+
|
|
149
|
+
results.forEach((result) => {
|
|
150
|
+
if (result.removed) {
|
|
151
|
+
log(` ✓ ${result.message}`, 'success');
|
|
152
|
+
removedCount++;
|
|
153
|
+
} else if (result.success) {
|
|
154
|
+
log(` ⊗ ${result.message} (skipped)`, 'info');
|
|
155
|
+
} else {
|
|
156
|
+
log(` ✗ ${result.message}`, 'error');
|
|
157
|
+
errorCount++;
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
// Summary
|
|
162
|
+
if (removedCount > 0) {
|
|
163
|
+
log(`\n✓ Uninstallation successful! Removed ${removedCount} file(s)/director(y)(ies)`, 'success');
|
|
164
|
+
} else if (errorCount === 0) {
|
|
165
|
+
log('\n⊗ No files found to uninstall', 'warning');
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (errorCount > 0) {
|
|
169
|
+
log(`\n⚠ ${errorCount} item(s) failed to remove, please clean up manually`, 'warning');
|
|
170
|
+
process.exit(1);
|
|
171
|
+
}
|
|
64
172
|
|
|
65
173
|
} catch (error) {
|
|
66
174
|
log(`Uninstallation failed: ${error.message}`, 'error');
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 技能使用指南生成器
|
|
5
|
+
* 在安装成功后显示友好的使用指南
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* 读取 package.json 中的信息
|
|
13
|
+
*/
|
|
14
|
+
function getPackageInfo() {
|
|
15
|
+
const packageRoot = path.resolve(__dirname, '..');
|
|
16
|
+
const packageJsonPath = path.join(packageRoot, 'package.json');
|
|
17
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
name: packageJson.name.split('/')[1] || packageJson.name,
|
|
21
|
+
description: packageJson.description,
|
|
22
|
+
homepage: packageJson.homepage || '',
|
|
23
|
+
repository: packageJson.repository?.url || '',
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* 读取 SKILL.md 中的触发指令
|
|
29
|
+
*/
|
|
30
|
+
function getSkillInstructions() {
|
|
31
|
+
const packageRoot = path.resolve(__dirname, '..');
|
|
32
|
+
const skillMdPath = path.join(packageRoot, 'SKILL.md');
|
|
33
|
+
|
|
34
|
+
if (!fs.existsSync(skillMdPath)) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const content = fs.readFileSync(skillMdPath, 'utf-8');
|
|
39
|
+
// 匹配 description 行中的指令说明
|
|
40
|
+
const match = content.match(/^description:\s*(.+)$/m);
|
|
41
|
+
return match ? match[1].trim() : null;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* 打印使用指南
|
|
46
|
+
*/
|
|
47
|
+
function printUsageGuide() {
|
|
48
|
+
const pkg = getPackageInfo();
|
|
49
|
+
const instructions = getSkillInstructions();
|
|
50
|
+
|
|
51
|
+
// 如果 SKILL.md 中有指令说明,使用它;否则使用 package.json 的 description
|
|
52
|
+
const usageInfo = instructions || pkg.description;
|
|
53
|
+
|
|
54
|
+
const guide = `
|
|
55
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
56
|
+
🎉 技能安装成功!
|
|
57
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
58
|
+
|
|
59
|
+
📦 技能名称: ${pkg.name}
|
|
60
|
+
📝 功能描述: ${pkg.description}
|
|
61
|
+
|
|
62
|
+
🚀 如何使用:
|
|
63
|
+
${usageInfo}
|
|
64
|
+
|
|
65
|
+
📖 更多信息:
|
|
66
|
+
${pkg.homepage ? ` 文档: ${pkg.homepage}` : ''}
|
|
67
|
+
${pkg.repository ? ` 仓库: ${pkg.repository}` : ''}
|
|
68
|
+
|
|
69
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
70
|
+
`;
|
|
71
|
+
|
|
72
|
+
console.log(guide);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
module.exports = { printUsageGuide };
|