codymaster 4.5.2 → 4.5.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/dist/index.js +37 -27
- package/dist/ui/hamster.js +2 -2
- package/dist/ui/onboarding.js +18 -5
- package/install.sh +32 -9
- package/package.json +1 -1
- package/scripts/postinstall.js +23 -32
package/dist/index.js
CHANGED
|
@@ -71,6 +71,30 @@ const hamster_1 = require("./ui/hamster");
|
|
|
71
71
|
const hooks_1 = require("./ui/hooks");
|
|
72
72
|
const onboarding_1 = require("./ui/onboarding");
|
|
73
73
|
const VERSION = require('../package.json').version;
|
|
74
|
+
let ALL_SKILLS = [];
|
|
75
|
+
try {
|
|
76
|
+
const distSkillsDir = path_1.default.join(__dirname, '..', 'skills');
|
|
77
|
+
if (fs_1.default.existsSync(distSkillsDir)) {
|
|
78
|
+
ALL_SKILLS = fs_1.default.readdirSync(distSkillsDir).filter(f => {
|
|
79
|
+
const fullPath = path_1.default.join(distSkillsDir, f);
|
|
80
|
+
return fs_1.default.statSync(fullPath).isDirectory() && fs_1.default.existsSync(path_1.default.join(fullPath, 'SKILL.md'));
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
catch (e) {
|
|
85
|
+
// Silent fallback
|
|
86
|
+
}
|
|
87
|
+
if (ALL_SKILLS.length === 0) {
|
|
88
|
+
ALL_SKILLS = [
|
|
89
|
+
'cm-tdd', 'cm-debugging', 'cm-quality-gate', 'cm-test-gate', 'cm-code-review',
|
|
90
|
+
'cm-safe-deploy', 'cm-identity-guard', 'cm-git-worktrees', 'cm-terminal', 'cm-secret-shield', 'cm-security-gate', 'cm-safe-i18n',
|
|
91
|
+
'cm-planning', 'cm-ux-master', 'cm-ui-preview', 'cm-brainstorm-idea', 'cm-jtbd', 'cm-dockit', 'cm-project-bootstrap', 'cm-readit',
|
|
92
|
+
'cm-content-factory', 'cm-ads-tracker', 'cro-methodology', 'cm-deep-search',
|
|
93
|
+
'cm-execution', 'cm-continuity', 'cm-skill-index', 'cm-skill-mastery', 'cm-skill-chain',
|
|
94
|
+
'cm-start', 'cm-dashboard', 'cm-status', 'cm-how-it-work', 'cm-example',
|
|
95
|
+
];
|
|
96
|
+
}
|
|
97
|
+
const SKILL_COUNT = ALL_SKILLS.length;
|
|
74
98
|
// ─── Update Check ───────────────────────────────────────────────────────────
|
|
75
99
|
let _updateMessage = '';
|
|
76
100
|
function checkForUpdates() {
|
|
@@ -134,7 +158,7 @@ function printUpdateNotice() {
|
|
|
134
158
|
function showBanner() {
|
|
135
159
|
const cPath = process.cwd().replace(os_1.default.homedir(), '~');
|
|
136
160
|
const profile = (0, hooks_1.loadProfile)();
|
|
137
|
-
console.log((0, hamster_1.renderHamsterBanner)(profile.userName || undefined, VERSION, cPath));
|
|
161
|
+
console.log((0, hamster_1.renderHamsterBanner)(profile.userName || undefined, VERSION, cPath, SKILL_COUNT));
|
|
138
162
|
printUpdateNotice();
|
|
139
163
|
}
|
|
140
164
|
// ─── Utility ────────────────────────────────────────────────────────────────
|
|
@@ -177,7 +201,7 @@ function postInstallOnboarding(platform) {
|
|
|
177
201
|
message: 'What would you like to do?',
|
|
178
202
|
options: [
|
|
179
203
|
{ label: `${theme_1.ICONS.dashboard} Launch Dashboard`, value: 'dashboard', hint: `localhost:${data_1.DEFAULT_PORT}` },
|
|
180
|
-
{ label: `${theme_1.ICONS.skill} Browse all
|
|
204
|
+
{ label: `${theme_1.ICONS.skill} Browse all ${SKILL_COUNT} skills`, value: 'skills' },
|
|
181
205
|
{ label: `${theme_1.ICONS.deploy} Start with your AI`, value: 'invoke', hint: profile.platform || 'any agent' },
|
|
182
206
|
{ label: `${(0, theme_1.success)('✓')} Done`, value: 'done' },
|
|
183
207
|
],
|
|
@@ -258,7 +282,7 @@ function showInteractiveMenu() {
|
|
|
258
282
|
{ label: `${theme_1.ICONS.dashboard} Dashboard`, value: 'dashboard', hint: isDashboardRunning() ? 'Open' : 'Start & open' },
|
|
259
283
|
{ label: `${theme_1.ICONS.task} My Tasks`, value: 'tasks', hint: `${taskCounts.totalTasks} total` },
|
|
260
284
|
{ label: `📈 Status`, value: 'status', hint: 'Health snapshot' },
|
|
261
|
-
{ label: `${theme_1.ICONS.skill} Browse Skills`, value: 'skills', hint:
|
|
285
|
+
{ label: `${theme_1.ICONS.skill} Browse Skills`, value: 'skills', hint: `${SKILL_COUNT} skills` },
|
|
262
286
|
{ label: `➕ Add a Task`, value: 'addtask', hint: 'Quick add' },
|
|
263
287
|
{ label: `⚡ Install Skills`, value: 'install', hint: 'Update all' },
|
|
264
288
|
{ label: `${theme_1.ICONS.hamster} My Profile`, value: 'profile', hint: `${profile.level}` },
|
|
@@ -318,7 +342,7 @@ function showInteractiveMenu() {
|
|
|
318
342
|
`${(0, theme_1.brand)('cm task list')} ${(0, theme_1.dim)('View tasks')}`,
|
|
319
343
|
`${(0, theme_1.brand)('cm status')} ${(0, theme_1.dim)('Project health')}`,
|
|
320
344
|
`${(0, theme_1.brand)('cm dashboard')} ${(0, theme_1.dim)('Mission Control')}`,
|
|
321
|
-
`${(0, theme_1.brand)('cm list')} ${(0, theme_1.dim)(
|
|
345
|
+
`${(0, theme_1.brand)('cm list')} ${(0, theme_1.dim)(`Browse ${SKILL_COUNT} skills`)}`,
|
|
322
346
|
`${(0, theme_1.brand)('cm deploy')} ${(0, theme_1.dim)('<env>')} ${(0, theme_1.dim)('Record deploy')}`,
|
|
323
347
|
`${(0, theme_1.brand)('cm profile')} ${(0, theme_1.dim)('Your stats')}`,
|
|
324
348
|
];
|
|
@@ -332,7 +356,7 @@ function showInteractiveMenu() {
|
|
|
332
356
|
const program = new commander_1.Command();
|
|
333
357
|
program
|
|
334
358
|
.name('cm')
|
|
335
|
-
.description(
|
|
359
|
+
.description(`Cody — ${SKILL_COUNT} Skills. Ship 10x faster.`)
|
|
336
360
|
.version(VERSION, '-v, --version', 'Show version')
|
|
337
361
|
.argument('[cmd]', 'Command to run', '')
|
|
338
362
|
.action((cmd) => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -1093,20 +1117,6 @@ program
|
|
|
1093
1117
|
console.log((0, box_1.renderResult)('success', `Skill '${skill}' installed for ${opts.platform}!`));
|
|
1094
1118
|
}));
|
|
1095
1119
|
// ─── Add Command (npx codymaster add --skill cm-debugging) ───────────────────
|
|
1096
|
-
const ALL_SKILLS = [
|
|
1097
|
-
// Engineering
|
|
1098
|
-
'cm-tdd', 'cm-debugging', 'cm-quality-gate', 'cm-test-gate', 'cm-code-review',
|
|
1099
|
-
// Operations
|
|
1100
|
-
'cm-safe-deploy', 'cm-identity-guard', 'cm-git-worktrees', 'cm-terminal', 'cm-secret-shield', 'cm-security-gate', 'cm-safe-i18n',
|
|
1101
|
-
// Product
|
|
1102
|
-
'cm-planning', 'cm-ux-master', 'cm-ui-preview', 'cm-brainstorm-idea', 'cm-jtbd', 'cm-dockit', 'cm-project-bootstrap', 'cm-readit',
|
|
1103
|
-
// Growth
|
|
1104
|
-
'cm-content-factory', 'cm-ads-tracker', 'cro-methodology', 'cm-deep-search',
|
|
1105
|
-
// Orchestration
|
|
1106
|
-
'cm-execution', 'cm-continuity', 'cm-skill-index', 'cm-skill-mastery', 'cm-skill-chain',
|
|
1107
|
-
// Workflow
|
|
1108
|
-
'cm-start', 'cm-dashboard', 'cm-status', 'cm-how-it-work', 'cm-example',
|
|
1109
|
-
];
|
|
1110
1120
|
const PLATFORM_TARGETS = {
|
|
1111
1121
|
gemini: { dir: '.gemini/skills', invoke: '@[/<skill>]', note: 'or ~/.gemini/antigravity/skills/ for global' },
|
|
1112
1122
|
cursor: { dir: '.cursor/rules', invoke: '@<skill>', note: 'Cursor rules directory' },
|
|
@@ -1169,7 +1179,7 @@ function doAddSkills(skills, platform) {
|
|
|
1169
1179
|
const { execFileSync } = require('child_process');
|
|
1170
1180
|
if (platform === 'claude') {
|
|
1171
1181
|
console.log((0, theme_1.brand)('🟣 Claude Code — Installing via plugin system'));
|
|
1172
|
-
console.log((0, theme_1.dim)(' (Claude installs all
|
|
1182
|
+
console.log((0, theme_1.dim)(' (Claude installs all ${SKILL_COUNT} skills as one bundle)\n'));
|
|
1173
1183
|
// Step 1: Register marketplace
|
|
1174
1184
|
console.log((0, theme_1.dim)(' $ claude plugin marketplace add tody-agent/codymaster'));
|
|
1175
1185
|
try {
|
|
@@ -1193,7 +1203,7 @@ function doAddSkills(skills, platform) {
|
|
|
1193
1203
|
console.log((0, theme_1.dim)(' $ claude plugin install codymaster@codymaster'));
|
|
1194
1204
|
try {
|
|
1195
1205
|
execFileSync('claude', ['plugin', 'install', 'codymaster@codymaster'], { stdio: 'inherit' });
|
|
1196
|
-
console.log((0, box_1.renderResult)('success',
|
|
1206
|
+
console.log((0, box_1.renderResult)('success', `All ${SKILL_COUNT} skills installed!`));
|
|
1197
1207
|
yield postInstallOnboarding('claude');
|
|
1198
1208
|
}
|
|
1199
1209
|
catch (_b) {
|
|
@@ -1225,7 +1235,7 @@ function doAddSkills(skills, platform) {
|
|
|
1225
1235
|
}
|
|
1226
1236
|
const icons = { cursor: '🔵', windsurf: '🟠', cline: '⚫', opencode: '📦', kiro: '🔶' };
|
|
1227
1237
|
const icon = icons[platform] || '📦';
|
|
1228
|
-
const label = skills.length === ALL_SKILLS.length ?
|
|
1238
|
+
const label = skills.length === ALL_SKILLS.length ? `all ${SKILL_COUNT} skills` : skills.join(', ');
|
|
1229
1239
|
console.log(`${icon} ${(0, theme_1.brand)(`${platform} — Installing ${label}`)}`);
|
|
1230
1240
|
console.log((0, theme_1.dim)(` Target: ./${target.dir}/\n`));
|
|
1231
1241
|
let ok = 0, fail = 0;
|
|
@@ -1282,7 +1292,7 @@ program
|
|
|
1282
1292
|
.command('add')
|
|
1283
1293
|
.description('Add skills to your AI agent (npx codymaster add --skill cm-debugging)')
|
|
1284
1294
|
.option('--skill <name>', 'Specific skill to add (e.g. cm-debugging)')
|
|
1285
|
-
.option('--all',
|
|
1295
|
+
.option('--all', `Add all ${SKILL_COUNT} skills`)
|
|
1286
1296
|
.option('--platform <platform>', 'Target: claude|gemini|cursor|windsurf|cline|opencode|kiro|copilot')
|
|
1287
1297
|
.option('--list', 'Show available skills and exit')
|
|
1288
1298
|
.action((opts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -1339,7 +1349,7 @@ program
|
|
|
1339
1349
|
const mode = yield p.select({
|
|
1340
1350
|
message: 'What to install?',
|
|
1341
1351
|
options: [
|
|
1342
|
-
{ label:
|
|
1352
|
+
{ label: `All ${SKILL_COUNT} skills (full kit)`, value: 'all' },
|
|
1343
1353
|
{ label: 'Search & pick one skill', value: 'pick' },
|
|
1344
1354
|
],
|
|
1345
1355
|
});
|
|
@@ -1365,7 +1375,7 @@ program
|
|
|
1365
1375
|
program
|
|
1366
1376
|
.command('list')
|
|
1367
1377
|
.alias('ls')
|
|
1368
|
-
.description(
|
|
1378
|
+
.description(`List all ${SKILL_COUNT} available skills`)
|
|
1369
1379
|
.option('-d, --domain <domain>', 'Filter by domain')
|
|
1370
1380
|
.action((opts) => {
|
|
1371
1381
|
skillList(opts.domain);
|
|
@@ -1978,7 +1988,7 @@ const SKILL_CATALOG = {
|
|
|
1978
1988
|
{ name: 'cm-start', desc: 'Onboarding & session kick-off wizard' },
|
|
1979
1989
|
{ name: 'cm-dashboard', desc: 'Project status & task Kanban board' },
|
|
1980
1990
|
{ name: 'cm-status', desc: 'Quick project health snapshot' },
|
|
1981
|
-
{ name: 'cm-how-it-work', desc:
|
|
1991
|
+
{ name: 'cm-how-it-work', desc: `Interactive explainer for all ${SKILL_COUNT} skills` },
|
|
1982
1992
|
{ name: 'cm-example', desc: 'Minimal template for new skills' },
|
|
1983
1993
|
],
|
|
1984
1994
|
},
|
|
@@ -2024,7 +2034,7 @@ function skillList(filterDomain) {
|
|
|
2024
2034
|
console.log((0, box_1.renderResult)('error', `Domain not found: ${filterDomain}`, [(0, theme_1.dim)('Domains: engineering, operations, product, growth, orchestration, workflow')]));
|
|
2025
2035
|
return;
|
|
2026
2036
|
}
|
|
2027
|
-
console.log((0, box_1.renderCommandHeader)(
|
|
2037
|
+
console.log((0, box_1.renderCommandHeader)(`Cody Master — ${SKILL_COUNT} Skills`, '🧩'));
|
|
2028
2038
|
let total = 0;
|
|
2029
2039
|
for (const [domain, data] of entries) {
|
|
2030
2040
|
console.log((0, theme_1.brand)(` ${data.icon} ${domain.charAt(0).toUpperCase() + domain.slice(1)}`));
|
package/dist/ui/hamster.js
CHANGED
|
@@ -193,7 +193,7 @@ function getErrorGuidance() {
|
|
|
193
193
|
/**
|
|
194
194
|
* Render the full hamster banner with greeting
|
|
195
195
|
*/
|
|
196
|
-
function renderHamsterBanner(userName, version, cwd) {
|
|
196
|
+
function renderHamsterBanner(userName, version, cwd, skillCount = 34) {
|
|
197
197
|
const art = getHamsterArt(getTimeOfDay() === 'night' ? 'sleeping' : 'greeting');
|
|
198
198
|
const greeting = getGreeting(userName);
|
|
199
199
|
const lines = [
|
|
@@ -202,7 +202,7 @@ function renderHamsterBanner(userName, version, cwd) {
|
|
|
202
202
|
'',
|
|
203
203
|
` ${(0, theme_1.brandBold)(greeting)}`,
|
|
204
204
|
'',
|
|
205
|
-
` ${(0, theme_1.dim)('CodyMaster')} ${(0, theme_1.brand)(`v${version || '?'}`)} ${(0, theme_1.dim)('•')} ${(0, theme_1.dim)(
|
|
205
|
+
` ${(0, theme_1.dim)('CodyMaster')} ${(0, theme_1.brand)(`v${version || '?'}`)} ${(0, theme_1.dim)('•')} ${(0, theme_1.dim)(`${skillCount} Skills`)} ${(0, theme_1.dim)('•')} ${(0, theme_1.dim)(cwd || '~')}`,
|
|
206
206
|
(0, theme_1.dim)(' ' + '─'.repeat(50)),
|
|
207
207
|
];
|
|
208
208
|
return lines.join('\n');
|
package/dist/ui/onboarding.js
CHANGED
|
@@ -56,13 +56,26 @@ const theme_2 = require("./theme");
|
|
|
56
56
|
const box_1 = require("./box");
|
|
57
57
|
const hamster_1 = require("./hamster");
|
|
58
58
|
const hooks_1 = require("./hooks");
|
|
59
|
+
let SKILL_COUNT = 33;
|
|
60
|
+
try {
|
|
61
|
+
const fs = require('fs');
|
|
62
|
+
const path = require('path');
|
|
63
|
+
const distSkillsDir = path.join(__dirname, '..', '..', 'skills');
|
|
64
|
+
if (fs.existsSync(distSkillsDir)) {
|
|
65
|
+
SKILL_COUNT = fs.readdirSync(distSkillsDir).filter((f) => {
|
|
66
|
+
const fullPath = path.join(distSkillsDir, f);
|
|
67
|
+
return fs.statSync(fullPath).isDirectory() && fs.existsSync(path.join(fullPath, 'SKILL.md'));
|
|
68
|
+
}).length;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
catch (e) { }
|
|
59
72
|
// ─── Onboarding Steps ──────────────────────────────────────────────────────
|
|
60
73
|
const TOTAL_STEPS = 5;
|
|
61
74
|
const STEP_INFO = {
|
|
62
75
|
1: { title: 'Meet your assistant', desc: 'What should I call you?' },
|
|
63
76
|
2: { title: 'Pick your platform', desc: 'Where do you code?' },
|
|
64
77
|
3: { title: 'Your first task', desc: 'Add something to build' },
|
|
65
|
-
4: { title: 'See the magic', desc:
|
|
78
|
+
4: { title: 'See the magic', desc: `Discover your ${SKILL_COUNT} skills` },
|
|
66
79
|
5: { title: 'You\'re ready!', desc: 'Welcome to the team' },
|
|
67
80
|
};
|
|
68
81
|
/**
|
|
@@ -219,7 +232,7 @@ function runOnboarding(version) {
|
|
|
219
232
|
if (startStep < 4) {
|
|
220
233
|
console.log((0, box_1.renderStepProgress)(4, TOTAL_STEPS));
|
|
221
234
|
console.log('');
|
|
222
|
-
console.log(` ${(0, theme_1.brandBold)(
|
|
235
|
+
console.log(` ${(0, theme_1.brandBold)(`You have ${SKILL_COUNT} superpowers!`)} ${theme_2.ICONS.skill}`);
|
|
223
236
|
console.log(` ${(0, theme_1.dim)('Grouped by what they help you do:')}`);
|
|
224
237
|
console.log('');
|
|
225
238
|
const SKILL_DOMAINS = [
|
|
@@ -267,10 +280,10 @@ function runOnboarding(version) {
|
|
|
267
280
|
}
|
|
268
281
|
console.log('');
|
|
269
282
|
}
|
|
270
|
-
console.log(` ${(0, theme_1.dim)(`Total:
|
|
283
|
+
console.log(` ${(0, theme_1.dim)(`Total: ${SKILL_COUNT} skills across 6 domains`)}`);
|
|
271
284
|
console.log('');
|
|
272
285
|
const viewAll = yield p.confirm({
|
|
273
|
-
message:
|
|
286
|
+
message: `Want to browse all ${SKILL_COUNT} skills in detail?`,
|
|
274
287
|
initialValue: false,
|
|
275
288
|
});
|
|
276
289
|
profile.onboardingStep = 4;
|
|
@@ -317,5 +330,5 @@ function runOnboarding(version) {
|
|
|
317
330
|
* Displays hamster + trigger + quick action
|
|
318
331
|
*/
|
|
319
332
|
function showReturningWelcome(profile, version, cwd) {
|
|
320
|
-
console.log((0, hamster_1.renderHamsterBanner)(profile.userName, version, cwd));
|
|
333
|
+
console.log((0, hamster_1.renderHamsterBanner)(profile.userName, version, cwd, SKILL_COUNT));
|
|
321
334
|
}
|
package/install.sh
CHANGED
|
@@ -27,6 +27,15 @@ RAW_URL="https://raw.githubusercontent.com/tody-agent/codymaster/main"
|
|
|
27
27
|
VERSION="4.4.0"
|
|
28
28
|
SCOPE="user" # default scope for Claude Code
|
|
29
29
|
|
|
30
|
+
if [ -d "skills" ]; then
|
|
31
|
+
TOTAL_SKILLS=$(ls -1d skills/*/SKILL.md 2>/dev/null | wc -l | tr -d ' ')
|
|
32
|
+
elif [ -d "$HOME/.cody-master/skills" ]; then
|
|
33
|
+
TOTAL_SKILLS=$(ls -1d "$HOME/.cody-master/skills"/*/SKILL.md 2>/dev/null | wc -l | tr -d ' ')
|
|
34
|
+
else
|
|
35
|
+
TOTAL_SKILLS="60+"
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
|
|
30
39
|
# ── i18n ────────────────────────────────────────────────────────
|
|
31
40
|
detect_lang() {
|
|
32
41
|
local lang="${LANG:-en}"
|
|
@@ -115,7 +124,7 @@ print_header() {
|
|
|
115
124
|
echo ""
|
|
116
125
|
echo -e " ${O}${BOLD}$(msg welcome)${NC} 🐹"
|
|
117
126
|
echo ""
|
|
118
|
-
echo -e " ${DIM}CodyMaster${NC} ${O}v${VERSION}${NC} ${DIM}•
|
|
127
|
+
echo -e " ${DIM}CodyMaster${NC} ${O}v${VERSION}${NC} ${DIM}• ${TOTAL_SKILLS} Skills • ~${NC}"
|
|
119
128
|
echo -e "${DIM} ──────────────────────────────────────────────────${NC}"
|
|
120
129
|
echo ""
|
|
121
130
|
}
|
|
@@ -206,7 +215,7 @@ hamster_sentiment() {
|
|
|
206
215
|
"start")
|
|
207
216
|
case $idx in
|
|
208
217
|
0) echo -e " ${C}🐹: Whiskers twitching... CodyMaster incoming!${NC}" ;;
|
|
209
|
-
1) echo -e " ${C}🐹: Let's fill these cheeks with
|
|
218
|
+
1) echo -e " ${C}🐹: Let's fill these cheeks with ${TOTAL_SKILLS} skills! ✨${NC}" ;;
|
|
210
219
|
2) echo -e " ${C}🐹: Waking up from a power nap! Let's build! 🐭${NC}" ;;
|
|
211
220
|
esac
|
|
212
221
|
;;
|
|
@@ -220,7 +229,7 @@ hamster_sentiment() {
|
|
|
220
229
|
"finish")
|
|
221
230
|
case $idx in
|
|
222
231
|
0) echo -e " ${C}🐹: Mission accomplished! Can I have a walnut now? 🥜${NC}" ;;
|
|
223
|
-
1) echo -e " ${C}🐹: My cheeks are stuffed with
|
|
232
|
+
1) echo -e " ${C}🐹: My cheeks are stuffed with ${TOTAL_SKILLS} skills for you! ✨${NC}" ;;
|
|
224
233
|
2) echo -e " ${C}🐹: Terminal is Hamster-approved! Better than a wheel! 🎡${NC}" ;;
|
|
225
234
|
esac
|
|
226
235
|
;;
|
|
@@ -403,7 +412,7 @@ print_onboarding() {
|
|
|
403
412
|
print_header
|
|
404
413
|
|
|
405
414
|
if [ "$LANG_CODE" = "vi" ]; then
|
|
406
|
-
echo -e " ${W}${BOLD}🎉 Thành công! Bạn đã mở khóa
|
|
415
|
+
echo -e " ${W}${BOLD}🎉 Thành công! Bạn đã mở khóa ${TOTAL_SKILLS} kỹ năng AI toàn năng:${NC}"
|
|
407
416
|
echo ""
|
|
408
417
|
hamster_sentiment "finish"
|
|
409
418
|
echo ""
|
|
@@ -429,7 +438,7 @@ print_onboarding() {
|
|
|
429
438
|
echo -e " 11. ${Y}Xem Demo tự động ${NC} → /cm:demo"
|
|
430
439
|
echo -e " 12. ${Y}Trợ giúp & Cú pháp lệnh ${NC} → cm help"
|
|
431
440
|
else
|
|
432
|
-
echo -e " ${W}${BOLD}🎉 Success! You just unlocked
|
|
441
|
+
echo -e " ${W}${BOLD}🎉 Success! You just unlocked ${TOTAL_SKILLS} omnipotent AI skills:${NC}"
|
|
433
442
|
echo ""
|
|
434
443
|
hamster_sentiment "finish"
|
|
435
444
|
echo ""
|
|
@@ -611,6 +620,7 @@ install_skills_to() {
|
|
|
611
620
|
echo ""
|
|
612
621
|
mkdir -p "$target"
|
|
613
622
|
local count=0
|
|
623
|
+
local installed=()
|
|
614
624
|
for skill_dir in "${CLONE_DIR}"/skills/*/; do
|
|
615
625
|
skill_name=$(basename "$skill_dir")
|
|
616
626
|
if [ -f "${skill_dir}SKILL.md" ]; then
|
|
@@ -621,19 +631,32 @@ install_skills_to() {
|
|
|
621
631
|
echo "globs: *" >> "${target}/${skill_name}.mdc"
|
|
622
632
|
echo "---" >> "${target}/${skill_name}.mdc"
|
|
623
633
|
cat "${skill_dir}SKILL.md" >> "${target}/${skill_name}.mdc"
|
|
624
|
-
|
|
634
|
+
installed+=("${skill_name}.mdc")
|
|
625
635
|
elif [[ "$format" == "md" ]]; then
|
|
626
636
|
cp "${skill_dir}SKILL.md" "${target}/${skill_name}.md"
|
|
627
|
-
|
|
637
|
+
installed+=("${skill_name}.md")
|
|
628
638
|
else
|
|
629
639
|
cp -r "$skill_dir" "${target}/${skill_name}"
|
|
630
|
-
|
|
640
|
+
installed+=("$skill_name")
|
|
631
641
|
fi
|
|
632
642
|
count=$((count + 1))
|
|
633
643
|
fi
|
|
634
644
|
done
|
|
645
|
+
|
|
646
|
+
local line=" ${DIM}"
|
|
647
|
+
for s in "${installed[@]}"; do
|
|
648
|
+
if [ ${#line} -gt 70 ]; then
|
|
649
|
+
echo -e "${line}${NC}"
|
|
650
|
+
line=" ${DIM}"
|
|
651
|
+
fi
|
|
652
|
+
line="${line}${s}, "
|
|
653
|
+
done
|
|
654
|
+
if [ "${line}" != " ${DIM}" ]; then
|
|
655
|
+
echo -e "${line%, }${NC}"
|
|
656
|
+
fi
|
|
657
|
+
|
|
635
658
|
echo ""
|
|
636
|
-
echo -e "${G}${count} skills installed to ${target}${NC}"
|
|
659
|
+
echo -e "${G}✅ ${count} skills installed to ${target}${NC}"
|
|
637
660
|
}
|
|
638
661
|
|
|
639
662
|
# ── Legacy alias ─────────────────────────────────────────────────
|
package/package.json
CHANGED
package/scripts/postinstall.js
CHANGED
|
@@ -9,13 +9,29 @@ const BOLD = '\x1b[1m';
|
|
|
9
9
|
const DIM = '\x1b[2m';
|
|
10
10
|
const NC = '\x1b[0m';
|
|
11
11
|
|
|
12
|
+
const fs = require('fs');
|
|
13
|
+
const path = require('path');
|
|
14
|
+
let skillCount = 60;
|
|
15
|
+
try {
|
|
16
|
+
const skillsDir = path.join(__dirname, '..', 'skills');
|
|
17
|
+
if (fs.existsSync(skillsDir)) {
|
|
18
|
+
skillCount = fs.readdirSync(skillsDir)
|
|
19
|
+
.filter(f => {
|
|
20
|
+
const fullPath = path.join(skillsDir, f);
|
|
21
|
+
return fs.statSync(fullPath).isDirectory() && fs.existsSync(path.join(fullPath, 'SKILL.md'));
|
|
22
|
+
})
|
|
23
|
+
.length;
|
|
24
|
+
}
|
|
25
|
+
} catch (e) {}
|
|
26
|
+
|
|
27
|
+
|
|
12
28
|
// Simple check for Vietnamese environment for the CORE UI
|
|
13
29
|
const isVi = Intl.DateTimeFormat().resolvedOptions().locale.startsWith('vi');
|
|
14
30
|
|
|
15
31
|
const sentiments = {
|
|
16
32
|
start: [
|
|
17
33
|
"🐹: Whiskers twitching... CodyMaster incoming!",
|
|
18
|
-
|
|
34
|
+
`🐹: Let's fill these cheeks with ${skillCount} skills! ✨`,
|
|
19
35
|
"🐹: Waking up from a power nap! Let's build! 🐭"
|
|
20
36
|
],
|
|
21
37
|
progress: [
|
|
@@ -25,9 +41,9 @@ const sentiments = {
|
|
|
25
41
|
],
|
|
26
42
|
finish: [
|
|
27
43
|
"🐹: Mission accomplished! Can I have a walnut now? 🥜",
|
|
28
|
-
|
|
44
|
+
`🐹: My cheeks are stuffed with ${skillCount} skills for you! ✨`,
|
|
29
45
|
"🐹: Terminal is Hamster-approved! Better than a wheel! 🎡",
|
|
30
|
-
|
|
46
|
+
`🐹: ${skillCount} skills stored. I'm ready for vibe coding! ⚡`
|
|
31
47
|
]
|
|
32
48
|
};
|
|
33
49
|
|
|
@@ -209,9 +225,9 @@ const printMenu = () => {
|
|
|
209
225
|
console.log('');
|
|
210
226
|
|
|
211
227
|
if (isVi) {
|
|
212
|
-
console.log(` ${W}${BOLD}🎉 Thành công! Bạn đã mở khóa
|
|
228
|
+
console.log(` ${W}${BOLD}🎉 Thành công! Bạn đã mở khóa ${skillCount} kỹ năng AI toàn năng:${NC}`);
|
|
213
229
|
} else {
|
|
214
|
-
console.log(` ${W}${BOLD}🎉 Success! You just unlocked
|
|
230
|
+
console.log(` ${W}${BOLD}🎉 Success! You just unlocked ${skillCount} omnipotent AI skills:${NC}`);
|
|
215
231
|
}
|
|
216
232
|
|
|
217
233
|
console.log('');
|
|
@@ -267,35 +283,10 @@ const printMenu = () => {
|
|
|
267
283
|
console.log('');
|
|
268
284
|
console.log(` ${W}${BOLD}${isVi ? '📚 Tài liệu:' : '📚 Documentation:'}${NC} ${C}https://cody.todyle.com/docs${NC}`);
|
|
269
285
|
console.log('');
|
|
270
|
-
console.log(` ${DIM}Press 'q' to exit.${NC}`);
|
|
271
286
|
};
|
|
272
287
|
|
|
273
|
-
const main =
|
|
274
|
-
|
|
275
|
-
printMenu();
|
|
276
|
-
return;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
const readline = require('readline');
|
|
280
|
-
const rl = readline.createInterface({
|
|
281
|
-
input: process.stdin,
|
|
282
|
-
output: process.stdout
|
|
283
|
-
});
|
|
284
|
-
|
|
285
|
-
const question = (query) => new Promise(resolve => rl.question(query, resolve));
|
|
286
|
-
|
|
287
|
-
while (true) {
|
|
288
|
-
printMenu();
|
|
289
|
-
const answer = await question(' > ');
|
|
290
|
-
if (answer.toLowerCase() === 'q') break;
|
|
291
|
-
if (parseInt(answer) >= 1 && parseInt(answer) <= 12) {
|
|
292
|
-
showSkillGuide(answer);
|
|
293
|
-
await question('');
|
|
294
|
-
} else if (answer === '') {
|
|
295
|
-
break;
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
rl.close();
|
|
288
|
+
const main = () => {
|
|
289
|
+
printMenu();
|
|
299
290
|
};
|
|
300
291
|
|
|
301
292
|
main();
|