@catcuts-skills/handover 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 +30 -1
- package/package.json +3 -3
- package/scripts/install-skill.js +132 -6
- package/scripts/uninstall-skill.js +100 -36
- package/scripts/usage-guide.js +75 -0
package/README.md
CHANGED
|
@@ -48,15 +48,44 @@ npm test
|
|
|
48
48
|
|
|
49
49
|
### 卸载
|
|
50
50
|
|
|
51
|
+
**重要**:由于 npm 的限制,全局卸载时 preuninstall hook 可能不会执行。请按照以下步骤正确卸载:
|
|
52
|
+
|
|
53
|
+
#### 方式 1:使用 npm scripts(推荐)
|
|
54
|
+
|
|
51
55
|
```bash
|
|
52
56
|
# 全局卸载
|
|
57
|
+
npm run uninstall:global
|
|
53
58
|
npm uninstall -g @catcuts-skills/handover
|
|
54
59
|
|
|
55
60
|
# 项目级卸载
|
|
61
|
+
npm run uninstall:local
|
|
56
62
|
npm uninstall @catcuts-skills/handover
|
|
57
63
|
```
|
|
58
64
|
|
|
59
|
-
|
|
65
|
+
#### 方式 2:手动清理(如果方式 1 失败)
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
# 1. 清理技能文件
|
|
69
|
+
rm -rf ~/.claude/skills/handover
|
|
70
|
+
rm -rf ~/.agents/skills/handover
|
|
71
|
+
|
|
72
|
+
# 2. 卸载 npm 包
|
|
73
|
+
npm uninstall -g @catcuts-skills/handover
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**Windows PowerShell**:
|
|
77
|
+
```powershell
|
|
78
|
+
# 1. 清理技能文件
|
|
79
|
+
Remove-Item -Recurse -Force "$env:USERPROFILE\.claude\skills\handover"
|
|
80
|
+
Remove-Item -Recurse -Force "$env:USERPROFILE\.agents\skills\handover"
|
|
81
|
+
|
|
82
|
+
# 2. 卸载 npm 包
|
|
83
|
+
npm uninstall -g @catcuts-skills/handover
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
#### 为什么需要两步?
|
|
87
|
+
|
|
88
|
+
npm 的 `preuninstall` hook 在全局卸载时**不保证被执行**,这是 npm 的已知限制。因此需要先手动清理技能文件,再卸载 npm 包。
|
|
60
89
|
|
|
61
90
|
## 使用
|
|
62
91
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@catcuts-skills/handover",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "跨会话工作交接工具。支持归档当前进度和恢复历史进度两个模式。",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"scripts/"
|
|
17
17
|
],
|
|
18
18
|
"optionalDependencies": {
|
|
19
|
-
"
|
|
19
|
+
"skills": "^1.1.2"
|
|
20
20
|
},
|
|
21
21
|
"keywords": [
|
|
22
22
|
"claude-code",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"bugs": {
|
|
36
36
|
"url": "https://github.com/catcuts/agent-skills/issues"
|
|
37
37
|
},
|
|
38
|
-
"homepage": "https://github.com/catcuts/agent-skills#readme",
|
|
38
|
+
"homepage": "https://github.com/catcuts/agent-skills/tree/main/skills/handover#readme",
|
|
39
39
|
"engines": {
|
|
40
40
|
"node": ">=18.0.0"
|
|
41
41
|
}
|
package/scripts/install-skill.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Handover Skill 安装脚本
|
|
5
|
-
* 使用
|
|
5
|
+
* 使用 skills 将 skill 安装到 Claude Code
|
|
6
6
|
*
|
|
7
7
|
* 命令行参数 (推荐):
|
|
8
8
|
* --dry-run: 测试模式,只显示将要执行的命令,不实际安装
|
|
@@ -16,10 +16,30 @@
|
|
|
16
16
|
const { execSync } = require('child_process');
|
|
17
17
|
const path = require('path');
|
|
18
18
|
const fs = require('fs');
|
|
19
|
+
const os = require('os');
|
|
20
|
+
const { printUsageGuide } = require('./usage-guide');
|
|
19
21
|
|
|
20
22
|
// 获取包根目录
|
|
21
23
|
const packageRoot = path.resolve(__dirname, '..');
|
|
22
24
|
|
|
25
|
+
// 获取用户主目录
|
|
26
|
+
const homeDir = os.homedir();
|
|
27
|
+
|
|
28
|
+
// 技能名称
|
|
29
|
+
const skillName = 'handover';
|
|
30
|
+
|
|
31
|
+
// 需要清理的路径列表
|
|
32
|
+
const pathsToClean = {
|
|
33
|
+
// skills CLI 的规范副本目录(这是问题的根源)
|
|
34
|
+
canonical: path.join(homeDir, '.agents', 'skills', skillName),
|
|
35
|
+
|
|
36
|
+
// Claude Code 全局技能目录(符号链接)
|
|
37
|
+
claudeGlobal: path.join(homeDir, '.claude', 'skills', skillName),
|
|
38
|
+
|
|
39
|
+
// Claude Code 项目级技能目录(如果存在)
|
|
40
|
+
claudeLocal: path.join(process.cwd(), '.claude', 'skills', skillName),
|
|
41
|
+
};
|
|
42
|
+
|
|
23
43
|
// 解析命令行参数
|
|
24
44
|
const args = process.argv.slice(2);
|
|
25
45
|
const dryRun = args.includes('--dry-run');
|
|
@@ -51,11 +71,111 @@ function log(message, type = 'info') {
|
|
|
51
71
|
console.log(`${prefix} ${message}`);
|
|
52
72
|
}
|
|
53
73
|
|
|
74
|
+
// 检查路径是否为符号链接
|
|
75
|
+
function isSymlink(filePath) {
|
|
76
|
+
try {
|
|
77
|
+
return fs.lstatSync(filePath).isSymbolicLink();
|
|
78
|
+
} catch (e) {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// 安全删除路径(支持符号链接、文件、目录)
|
|
84
|
+
function safeRemovePath(filePath, description) {
|
|
85
|
+
try {
|
|
86
|
+
if (!fs.existsSync(filePath)) {
|
|
87
|
+
return { success: true, removed: false, message: `不存在:${description}(${filePath})` };
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const stats = fs.lstatSync(filePath);
|
|
91
|
+
const isLink = stats.isSymbolicLink();
|
|
92
|
+
const isDir = stats.isDirectory();
|
|
93
|
+
|
|
94
|
+
if (isLink) {
|
|
95
|
+
fs.unlinkSync(filePath);
|
|
96
|
+
return {
|
|
97
|
+
success: true,
|
|
98
|
+
removed: true,
|
|
99
|
+
message: `已删除符号链接: ${description}(${filePath})`
|
|
100
|
+
};
|
|
101
|
+
} else if (isDir) {
|
|
102
|
+
fs.rmSync(filePath, { recursive: true, force: true });
|
|
103
|
+
return {
|
|
104
|
+
success: true,
|
|
105
|
+
removed: true,
|
|
106
|
+
message: `已删除目录: ${description}(${filePath})`
|
|
107
|
+
};
|
|
108
|
+
} else {
|
|
109
|
+
fs.unlinkSync(filePath);
|
|
110
|
+
return {
|
|
111
|
+
success: true,
|
|
112
|
+
removed: true,
|
|
113
|
+
message: `已删除文件: ${description}(${filePath})`
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
} catch (error) {
|
|
117
|
+
return {
|
|
118
|
+
success: false,
|
|
119
|
+
removed: false,
|
|
120
|
+
message: `删除失败: ${description}(${filePath}) - ${error.message}`
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// 清理旧的安装文件
|
|
126
|
+
function cleanOldInstallations() {
|
|
127
|
+
log('\n正在清理旧的安装文件...', 'info');
|
|
128
|
+
|
|
129
|
+
const results = [];
|
|
130
|
+
|
|
131
|
+
// 1. 清理规范副本目录(.agents/skills/handover)
|
|
132
|
+
const canonicalResult = safeRemovePath(
|
|
133
|
+
pathsToClean.canonical,
|
|
134
|
+
'规范副本'
|
|
135
|
+
);
|
|
136
|
+
results.push({ path: pathsToClean.canonical, ...canonicalResult });
|
|
137
|
+
|
|
138
|
+
// 2. 清理 Claude Code 全局符号链接
|
|
139
|
+
const globalResult = safeRemovePath(
|
|
140
|
+
pathsToClean.claudeGlobal,
|
|
141
|
+
'全局技能链接'
|
|
142
|
+
);
|
|
143
|
+
results.push({ path: pathsToClean.claudeGlobal, ...globalResult });
|
|
144
|
+
|
|
145
|
+
// 3. 清理 Claude Code 项目级安装(如果存在)
|
|
146
|
+
const localResult = safeRemovePath(
|
|
147
|
+
pathsToClean.claudeLocal,
|
|
148
|
+
'项目级技能'
|
|
149
|
+
);
|
|
150
|
+
results.push({ path: pathsToClean.claudeLocal, ...localResult });
|
|
151
|
+
|
|
152
|
+
// 输出清理结果
|
|
153
|
+
let removedCount = 0;
|
|
154
|
+
results.forEach((result) => {
|
|
155
|
+
if (result.removed) {
|
|
156
|
+
log(` ✓ ${result.message}`, 'success');
|
|
157
|
+
removedCount++;
|
|
158
|
+
} else if (result.success) {
|
|
159
|
+
log(` ⊗ ${result.message} (跳过)`, 'info');
|
|
160
|
+
} else {
|
|
161
|
+
log(` ✗ ${result.message}`, 'warning');
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
if (removedCount > 0) {
|
|
166
|
+
log(`\n已清理 ${removedCount} 个旧安装文件`, 'success');
|
|
167
|
+
} else {
|
|
168
|
+
log('未发现需要清理的文件', 'info');
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return removedCount > 0;
|
|
172
|
+
}
|
|
173
|
+
|
|
54
174
|
// 错误处理
|
|
55
175
|
function handleError(error) {
|
|
56
176
|
log(`安装失败: ${error.message}`, 'error');
|
|
57
177
|
log('\n您可以尝试手动安装:', 'warning');
|
|
58
|
-
log(` npx add
|
|
178
|
+
log(` npx skills add "${packageRoot}" ${isGlobal ? '-g' : ''} -y`);
|
|
59
179
|
process.exit(1);
|
|
60
180
|
}
|
|
61
181
|
|
|
@@ -63,12 +183,15 @@ try {
|
|
|
63
183
|
log(`开始安装 Handover Skill...`, 'info');
|
|
64
184
|
log(`安装范围: ${isGlobal ? '全局(GLOBAL)' : '项目级(LOCAL)'}`, 'info');
|
|
65
185
|
|
|
66
|
-
//
|
|
186
|
+
// 清理旧的安装文件(解决增量更新导致的文件残留问题)
|
|
187
|
+
cleanOldInstallations();
|
|
188
|
+
|
|
189
|
+
// 构建 skills 命令
|
|
67
190
|
const commandParts = [
|
|
68
191
|
'npx',
|
|
69
|
-
'
|
|
192
|
+
'skills',
|
|
193
|
+
'add',
|
|
70
194
|
`"${packageRoot}"`,
|
|
71
|
-
// '-a', 'claude-code' // 由 add-skill 自动检测,如果检测失败那么会自动弹出菜单让用户手动选择
|
|
72
195
|
];
|
|
73
196
|
|
|
74
197
|
if (isGlobal) {
|
|
@@ -90,7 +213,7 @@ try {
|
|
|
90
213
|
}
|
|
91
214
|
|
|
92
215
|
// 执行安装
|
|
93
|
-
log('\n正在执行 add
|
|
216
|
+
log('\n正在执行 skills add...', 'info');
|
|
94
217
|
execSync(command, {
|
|
95
218
|
stdio: 'inherit',
|
|
96
219
|
cwd: packageRoot,
|
|
@@ -101,6 +224,9 @@ try {
|
|
|
101
224
|
`Skill 已安装到: ${isGlobal ? '~/.claude/skills/handover' : '.claude/skills/handover'}`,
|
|
102
225
|
'info'
|
|
103
226
|
);
|
|
227
|
+
|
|
228
|
+
// 显示使用指南
|
|
229
|
+
printUsageGuide();
|
|
104
230
|
} catch (error) {
|
|
105
231
|
handleError(error);
|
|
106
232
|
}
|
|
@@ -16,6 +16,9 @@ const path = require('path');
|
|
|
16
16
|
const fs = require('fs');
|
|
17
17
|
const os = require('os');
|
|
18
18
|
|
|
19
|
+
// 技能名称
|
|
20
|
+
const skillName = 'handover';
|
|
21
|
+
|
|
19
22
|
// 解析命令行参数
|
|
20
23
|
const args = process.argv.slice(2);
|
|
21
24
|
const forceGlobal = args.includes('--global');
|
|
@@ -46,18 +49,49 @@ function log(message, type = 'info') {
|
|
|
46
49
|
console.log(`${prefix} ${message}`);
|
|
47
50
|
}
|
|
48
51
|
|
|
49
|
-
//
|
|
50
|
-
function
|
|
51
|
-
if (!fs.existsSync(dirPath)) {
|
|
52
|
-
return false;
|
|
53
|
-
}
|
|
54
|
-
|
|
52
|
+
// 安全删除路径(支持符号链接、文件、目录)
|
|
53
|
+
function safeRemovePath(filePath, description) {
|
|
55
54
|
try {
|
|
56
|
-
fs.
|
|
57
|
-
|
|
55
|
+
if (!fs.existsSync(filePath)) {
|
|
56
|
+
return { success: true, removed: false, message: '不存在' };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const stats = fs.lstatSync(filePath);
|
|
60
|
+
const isLink = stats.isSymbolicLink();
|
|
61
|
+
const isDir = stats.isDirectory();
|
|
62
|
+
|
|
63
|
+
if (isLink) {
|
|
64
|
+
fs.unlinkSync(filePath);
|
|
65
|
+
return {
|
|
66
|
+
success: true,
|
|
67
|
+
removed: true,
|
|
68
|
+
message: `已删除符号链接: ${description}`
|
|
69
|
+
};
|
|
70
|
+
} else if (isDir) {
|
|
71
|
+
fs.rmSync(filePath, { recursive: true, force: true });
|
|
72
|
+
return {
|
|
73
|
+
success: true,
|
|
74
|
+
removed: true,
|
|
75
|
+
message: `已删除目录: ${description}`
|
|
76
|
+
};
|
|
77
|
+
} else {
|
|
78
|
+
fs.unlinkSync(filePath);
|
|
79
|
+
return {
|
|
80
|
+
success: true,
|
|
81
|
+
removed: true,
|
|
82
|
+
message: `已删除文件: ${description}`
|
|
83
|
+
};
|
|
84
|
+
}
|
|
58
85
|
} catch (error) {
|
|
59
|
-
|
|
60
|
-
|
|
86
|
+
// 忽略"文件不存在"错误,可能已被并发删除
|
|
87
|
+
if (error.code === 'ENOENT') {
|
|
88
|
+
return { success: true, removed: false, message: '已不存在' };
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
success: false,
|
|
92
|
+
removed: false,
|
|
93
|
+
message: `删除失败: ${error.message}`
|
|
94
|
+
};
|
|
61
95
|
}
|
|
62
96
|
}
|
|
63
97
|
|
|
@@ -65,42 +99,72 @@ try {
|
|
|
65
99
|
log(`开始卸载 Handover Skill...`, 'info');
|
|
66
100
|
log(`卸载范围: ${isGlobal ? '全局(GLOBAL)' : '项目级(LOCAL)'}`, 'info');
|
|
67
101
|
|
|
68
|
-
|
|
102
|
+
log('\n正在清理技能文件...', 'info');
|
|
103
|
+
|
|
104
|
+
const results = [];
|
|
69
105
|
|
|
70
106
|
if (isGlobal) {
|
|
71
107
|
// 全局卸载
|
|
72
108
|
const homeDir = os.homedir();
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
109
|
+
|
|
110
|
+
// 1. 清理规范副本目录(.agents/skills/handover)
|
|
111
|
+
const canonicalResult = safeRemovePath(
|
|
112
|
+
path.join(homeDir, '.agents', 'skills', skillName),
|
|
113
|
+
'规范副本'
|
|
114
|
+
);
|
|
115
|
+
results.push(canonicalResult);
|
|
116
|
+
|
|
117
|
+
// 2. 清理 Claude Code 全局符号链接
|
|
118
|
+
const globalResult = safeRemovePath(
|
|
119
|
+
path.join(homeDir, '.claude', 'skills', skillName),
|
|
120
|
+
'全局技能链接'
|
|
121
|
+
);
|
|
122
|
+
results.push(globalResult);
|
|
84
123
|
} else {
|
|
85
124
|
// 项目级卸载
|
|
86
125
|
const cwd = process.cwd();
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
126
|
+
|
|
127
|
+
// 1. 清理项目级规范副本(如果存在)
|
|
128
|
+
const canonicalResult = safeRemovePath(
|
|
129
|
+
path.join(cwd, '.agents', 'skills', skillName),
|
|
130
|
+
'项目级规范副本'
|
|
131
|
+
);
|
|
132
|
+
results.push(canonicalResult);
|
|
133
|
+
|
|
134
|
+
// 2. 清理 Claude Code 项目级技能
|
|
135
|
+
const localResult = safeRemovePath(
|
|
136
|
+
path.join(cwd, '.claude', 'skills', skillName),
|
|
137
|
+
'项目级技能'
|
|
138
|
+
);
|
|
139
|
+
results.push(localResult);
|
|
98
140
|
}
|
|
99
141
|
|
|
142
|
+
// 输出清理结果
|
|
143
|
+
let removedCount = 0;
|
|
144
|
+
let errorCount = 0;
|
|
145
|
+
|
|
146
|
+
results.forEach((result) => {
|
|
147
|
+
if (result.removed) {
|
|
148
|
+
log(` ✓ ${result.message}`, 'success');
|
|
149
|
+
removedCount++;
|
|
150
|
+
} else if (result.success) {
|
|
151
|
+
log(` ⊗ ${result.message} (跳过)`, 'info');
|
|
152
|
+
} else {
|
|
153
|
+
log(` ✗ ${result.message}`, 'error');
|
|
154
|
+
errorCount++;
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
// 总结
|
|
100
159
|
if (removedCount > 0) {
|
|
101
|
-
log(`\n卸载成功! 已删除 ${removedCount}
|
|
102
|
-
} else {
|
|
103
|
-
log('\n
|
|
160
|
+
log(`\n✓ 卸载成功! 已删除 ${removedCount} 个文件/目录`, 'success');
|
|
161
|
+
} else if (errorCount === 0) {
|
|
162
|
+
log('\n⊗ 未找到需要卸载的文件', 'warning');
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (errorCount > 0) {
|
|
166
|
+
log(`\n⚠ 有 ${errorCount} 个项目删除失败,请手动清理`, 'warning');
|
|
167
|
+
process.exit(1);
|
|
104
168
|
}
|
|
105
169
|
} catch (error) {
|
|
106
170
|
log(`卸载失败: ${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 };
|