codymaster 4.1.2 → 4.1.3
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/CHANGELOG.md +25 -2
- package/README.md +108 -35
- package/dist/index.js +263 -158
- package/dist/ui/box.js +188 -0
- package/dist/ui/hamster.js +223 -0
- package/dist/ui/hooks.js +253 -0
- package/dist/ui/onboarding.js +315 -0
- package/dist/ui/theme.js +105 -0
- package/install.sh +143 -64
- package/package.json +6 -6
- package/skills/cm-quality-gate/SKILL.md +15 -0
- package/skills/cm-safe-i18n/SKILL.md +4 -1
package/dist/index.js
CHANGED
|
@@ -59,28 +59,84 @@ const skill_chain_1 = require("./skill-chain");
|
|
|
59
59
|
const path_1 = __importDefault(require("path"));
|
|
60
60
|
const os_1 = __importDefault(require("os"));
|
|
61
61
|
const https_1 = __importDefault(require("https"));
|
|
62
|
-
|
|
62
|
+
// 🐹 Hamster Shell UI modules
|
|
63
|
+
const theme_1 = require("./ui/theme");
|
|
64
|
+
const box_1 = require("./ui/box");
|
|
65
|
+
const hamster_1 = require("./ui/hamster");
|
|
66
|
+
const hooks_1 = require("./ui/hooks");
|
|
67
|
+
const onboarding_1 = require("./ui/onboarding");
|
|
68
|
+
const VERSION = require('../package.json').version;
|
|
69
|
+
// ─── Update Check ───────────────────────────────────────────────────────────
|
|
70
|
+
let _updateMessage = '';
|
|
71
|
+
function checkForUpdates() {
|
|
72
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
73
|
+
try {
|
|
74
|
+
const cacheDir = path_1.default.join(os_1.default.homedir(), '.codymaster');
|
|
75
|
+
const cacheFile = path_1.default.join(cacheDir, '.update-check');
|
|
76
|
+
// Check cache (24h TTL)
|
|
77
|
+
try {
|
|
78
|
+
if (fs_1.default.existsSync(cacheFile)) {
|
|
79
|
+
const stat = fs_1.default.statSync(cacheFile);
|
|
80
|
+
const age = Date.now() - stat.mtimeMs;
|
|
81
|
+
if (age < 24 * 60 * 60 * 1000) {
|
|
82
|
+
const cached = fs_1.default.readFileSync(cacheFile, 'utf-8').trim();
|
|
83
|
+
if (cached && cached !== VERSION) {
|
|
84
|
+
_updateMessage = cached;
|
|
85
|
+
}
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
catch ( /* ignore cache errors */_a) { /* ignore cache errors */ }
|
|
91
|
+
// Fetch latest version from npm (2s timeout)
|
|
92
|
+
const latestVersion = yield new Promise((resolve, reject) => {
|
|
93
|
+
const timer = setTimeout(() => reject(new Error('timeout')), 2000);
|
|
94
|
+
https_1.default.get('https://registry.npmjs.org/codymaster/latest', { headers: { 'Accept': 'application/json' } }, (res) => {
|
|
95
|
+
let data = '';
|
|
96
|
+
res.on('data', (chunk) => { data += chunk; });
|
|
97
|
+
res.on('end', () => {
|
|
98
|
+
clearTimeout(timer);
|
|
99
|
+
try {
|
|
100
|
+
const json = JSON.parse(data);
|
|
101
|
+
resolve(json.version || VERSION);
|
|
102
|
+
}
|
|
103
|
+
catch (_a) {
|
|
104
|
+
resolve(VERSION);
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
}).on('error', () => { clearTimeout(timer); reject(new Error('fetch failed')); });
|
|
108
|
+
});
|
|
109
|
+
// Cache result
|
|
110
|
+
try {
|
|
111
|
+
if (!fs_1.default.existsSync(cacheDir))
|
|
112
|
+
fs_1.default.mkdirSync(cacheDir, { recursive: true });
|
|
113
|
+
fs_1.default.writeFileSync(cacheFile, latestVersion);
|
|
114
|
+
}
|
|
115
|
+
catch ( /* ignore */_b) { /* ignore */ }
|
|
116
|
+
if (latestVersion !== VERSION) {
|
|
117
|
+
_updateMessage = latestVersion;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
catch ( /* silently skip — offline or timeout */_c) { /* silently skip — offline or timeout */ }
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
function printUpdateNotice() {
|
|
124
|
+
if (_updateMessage) {
|
|
125
|
+
console.log(chalk_1.default.yellow(` ⚠️ Update available: ${VERSION} → ${_updateMessage}`) + chalk_1.default.gray(' Run: ') + chalk_1.default.cyan('npm i -g codymaster'));
|
|
126
|
+
}
|
|
127
|
+
}
|
|
63
128
|
// ─── Branding ───────────────────────────────────────────────────────────────
|
|
64
129
|
function showBanner() {
|
|
65
130
|
const cPath = process.cwd().replace(os_1.default.homedir(), '~');
|
|
66
|
-
const
|
|
67
|
-
console.log(
|
|
68
|
-
|
|
69
|
-
console.log(` ${bg.black.bold(' CM ')} ${chalk_1.default.gray('34 Skills. Ship 10x faster.')}`);
|
|
70
|
-
console.log(` ${bg(' ')} ${chalk_1.default.gray(cPath)}`);
|
|
71
|
-
console.log(chalk_1.default.gray(' ' + '─'.repeat(46)));
|
|
131
|
+
const profile = (0, hooks_1.loadProfile)();
|
|
132
|
+
console.log((0, hamster_1.renderHamsterBanner)(profile.userName || undefined, VERSION, cPath));
|
|
133
|
+
printUpdateNotice();
|
|
72
134
|
}
|
|
73
135
|
// ─── Utility ────────────────────────────────────────────────────────────────
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
const
|
|
78
|
-
'low': chalk_1.default.green, 'medium': chalk_1.default.yellow, 'high': chalk_1.default.red, 'urgent': chalk_1.default.magenta,
|
|
79
|
-
};
|
|
80
|
-
const STATUS_COLORS = {
|
|
81
|
-
'success': chalk_1.default.green, 'failed': chalk_1.default.red, 'pending': chalk_1.default.yellow,
|
|
82
|
-
'running': chalk_1.default.blue, 'rolled_back': chalk_1.default.magenta,
|
|
83
|
-
};
|
|
136
|
+
// Color maps now imported from ./ui/theme (COL, PRI, STATUS)
|
|
137
|
+
const COL_COLORS = theme_1.COL;
|
|
138
|
+
const PRIORITY_COLORS = theme_1.PRI;
|
|
139
|
+
const STATUS_COLORS = theme_1.STATUS;
|
|
84
140
|
function padRight(str, len) {
|
|
85
141
|
return str.length >= len ? str.substring(0, len) : str + ' '.repeat(len - str.length);
|
|
86
142
|
}
|
|
@@ -94,138 +150,132 @@ function openUrl(url) {
|
|
|
94
150
|
// ─── Post-install Onboarding ─────────────────────────────────────────────────
|
|
95
151
|
function postInstallOnboarding(platform) {
|
|
96
152
|
return __awaiter(this, void 0, void 0, function* () {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
153
|
+
// Run the self-onboarding wizard
|
|
154
|
+
const profile = (0, hooks_1.loadProfile)();
|
|
155
|
+
if (!profile.onboardingComplete) {
|
|
156
|
+
// Set platform from install if not already set
|
|
157
|
+
if (platform && !profile.platform) {
|
|
158
|
+
profile.platform = platform;
|
|
159
|
+
(0, hooks_1.saveProfile)(profile);
|
|
160
|
+
}
|
|
161
|
+
yield (0, onboarding_1.runOnboarding)(VERSION);
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
// Already onboarded — show returning welcome
|
|
165
|
+
const p = yield Promise.resolve().then(() => __importStar(require('@clack/prompts')));
|
|
166
|
+
console.log('');
|
|
167
|
+
console.log((0, hamster_1.getHamsterArt)('celebrating'));
|
|
168
|
+
console.log('');
|
|
169
|
+
console.log(` ${(0, theme_1.success)('🎉')} ${(0, theme_1.brandBold)(`Welcome back, ${profile.userName || 'friend'}!`)}`);
|
|
170
|
+
console.log('');
|
|
171
|
+
const action = yield p.select({
|
|
172
|
+
message: 'What would you like to do?',
|
|
173
|
+
options: [
|
|
174
|
+
{ label: `${theme_1.ICONS.dashboard} Launch Dashboard`, value: 'dashboard', hint: `localhost:${data_1.DEFAULT_PORT}` },
|
|
175
|
+
{ label: `${theme_1.ICONS.skill} Browse all 34 skills`, value: 'skills' },
|
|
176
|
+
{ label: `${theme_1.ICONS.deploy} Start with your AI`, value: 'invoke', hint: profile.platform || 'any agent' },
|
|
177
|
+
{ label: `${(0, theme_1.success)('✓')} Done`, value: 'done' },
|
|
178
|
+
],
|
|
179
|
+
});
|
|
180
|
+
if (p.isCancel(action))
|
|
181
|
+
return;
|
|
182
|
+
switch (action) {
|
|
183
|
+
case 'dashboard':
|
|
184
|
+
if (!isDashboardRunning()) {
|
|
185
|
+
(0, dashboard_1.launchDashboard)(data_1.DEFAULT_PORT, false);
|
|
186
|
+
yield new Promise(r => setTimeout(r, 800));
|
|
187
|
+
}
|
|
188
|
+
console.log((0, theme_1.info)(`\n 🌐 Opening http://localhost:${data_1.DEFAULT_PORT} ...\n`));
|
|
189
|
+
openUrl(`http://localhost:${data_1.DEFAULT_PORT}`);
|
|
190
|
+
break;
|
|
191
|
+
case 'skills':
|
|
192
|
+
console.log('');
|
|
193
|
+
skillList();
|
|
194
|
+
break;
|
|
195
|
+
case 'invoke':
|
|
196
|
+
console.log('');
|
|
197
|
+
const invoke = profile.platform === 'claude' ? '/cm:demo' :
|
|
198
|
+
profile.platform === 'gemini' ? '@[/cm-planning]' :
|
|
199
|
+
'@cm-planning';
|
|
200
|
+
console.log(` ${(0, theme_1.brand)('→')} Type ${(0, theme_1.brandBold)(invoke)} in your AI agent\n`);
|
|
201
|
+
break;
|
|
202
|
+
default:
|
|
203
|
+
console.log((0, theme_1.dim)('\n Run cm any time! 🐹\n'));
|
|
143
204
|
}
|
|
144
|
-
case 'invoke':
|
|
145
|
-
console.log();
|
|
146
|
-
if (platform === 'claude') {
|
|
147
|
-
console.log(chalk_1.default.white('Open Claude Code and type:\n'));
|
|
148
|
-
console.log(chalk_1.default.cyan(' /cm:demo'));
|
|
149
|
-
console.log(chalk_1.default.gray('\n This will run an interactive tour of all 34 skills.\n'));
|
|
150
|
-
}
|
|
151
|
-
else {
|
|
152
|
-
console.log(chalk_1.default.cyan(` ${invoke}\n`));
|
|
153
|
-
}
|
|
154
|
-
break;
|
|
155
|
-
case 'skills':
|
|
156
|
-
console.log();
|
|
157
|
-
skillList();
|
|
158
|
-
break;
|
|
159
|
-
case 'global':
|
|
160
|
-
console.log();
|
|
161
|
-
console.log(chalk_1.default.white('Run this to install the `cm` CLI globally:\n'));
|
|
162
|
-
console.log(chalk_1.default.cyan(' npm install -g codymaster'));
|
|
163
|
-
console.log(chalk_1.default.gray('\nThen use:'));
|
|
164
|
-
console.log(chalk_1.default.cyan(' cm task add "My task"'));
|
|
165
|
-
console.log(chalk_1.default.cyan(' cm dashboard'));
|
|
166
|
-
console.log(chalk_1.default.cyan(' cm status\n'));
|
|
167
|
-
break;
|
|
168
|
-
default:
|
|
169
|
-
console.log(chalk_1.default.gray('\nRun `npx codymaster` any time to open the menu.\n'));
|
|
170
205
|
}
|
|
171
206
|
});
|
|
172
207
|
}
|
|
173
208
|
// ─── Interactive Quick Menu (no-args entry point) ─────────────────────────────
|
|
174
209
|
function showInteractiveMenu() {
|
|
175
210
|
return __awaiter(this, void 0, void 0, function* () {
|
|
211
|
+
const profile = (0, hooks_1.loadProfile)();
|
|
212
|
+
// 🎳 First Run → Start onboarding wizard
|
|
213
|
+
if (!profile.onboardingComplete) {
|
|
214
|
+
yield (0, onboarding_1.runOnboarding)(VERSION);
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
// 🪝 Hook: Record command + check achievements
|
|
218
|
+
(0, hooks_1.recordCommand)(profile, 'menu');
|
|
219
|
+
const newAchievements = (0, hooks_1.checkAchievements)(profile);
|
|
220
|
+
(0, hooks_1.saveProfile)(profile);
|
|
221
|
+
// Show banner with hamster
|
|
176
222
|
showBanner();
|
|
223
|
+
// 🪝 Hook: Contextual trigger
|
|
224
|
+
const data = (0, data_1.loadData)();
|
|
225
|
+
const taskCounts = {
|
|
226
|
+
tasksInProgress: data.tasks.filter(t => t.column === 'in-progress').length,
|
|
227
|
+
tasksInReview: data.tasks.filter(t => t.column === 'review').length,
|
|
228
|
+
tasksDone: data.tasks.filter(t => t.column === 'done').length,
|
|
229
|
+
totalTasks: data.tasks.length,
|
|
230
|
+
};
|
|
231
|
+
const trigger = (0, hooks_1.getContextualTrigger)(profile, taskCounts);
|
|
232
|
+
console.log(` ${(0, theme_1.brand)(theme_1.ICONS.hamster)} ${(0, theme_1.dim)(trigger)}`);
|
|
233
|
+
// Dashboard status
|
|
177
234
|
const dashStatus = isDashboardRunning()
|
|
178
|
-
?
|
|
179
|
-
:
|
|
180
|
-
console.log(
|
|
181
|
-
console.log();
|
|
182
|
-
|
|
183
|
-
const
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
{
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
},
|
|
200
|
-
{
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
},
|
|
204
|
-
{
|
|
205
|
-
title: chalk_1.default.yellow('➕ Add a Task'), value: 'addtask',
|
|
206
|
-
description: 'Quickly add a task to backlog'
|
|
207
|
-
},
|
|
208
|
-
{
|
|
209
|
-
title: chalk_1.default.green('⚡ Install/Update Skills'), value: 'install',
|
|
210
|
-
description: 'npx codymaster add --all'
|
|
211
|
-
},
|
|
212
|
-
{ title: chalk_1.default.gray('❓ Help'), value: 'help' },
|
|
235
|
+
? (0, theme_1.success)(`${theme_1.ICONS.dot} RUNNING`) + (0, theme_1.dim)(` http://localhost:${data_1.DEFAULT_PORT}`)
|
|
236
|
+
: (0, theme_1.muted)(`${theme_1.ICONS.dotEmpty} stopped`);
|
|
237
|
+
console.log(` ${(0, theme_1.dim)('Dashboard:')} ${dashStatus}`);
|
|
238
|
+
console.log('');
|
|
239
|
+
// Show new achievements
|
|
240
|
+
for (const id of newAchievements) {
|
|
241
|
+
console.log((0, hooks_1.formatAchievement)(id));
|
|
242
|
+
}
|
|
243
|
+
if (newAchievements.length > 0)
|
|
244
|
+
console.log('');
|
|
245
|
+
// Level indicator
|
|
246
|
+
console.log(` ${(0, theme_1.dim)('Level:')} ${(0, hooks_1.getLevelDisplay)(profile.level)} ${(0, theme_1.dim)('•')} ${(0, theme_1.dim)('Streak:')} ${profile.streak > 0 ? (0, theme_1.brand)(`${theme_1.ICONS.fire} ${profile.streak}d`) : (0, theme_1.muted)('—')}`);
|
|
247
|
+
console.log('');
|
|
248
|
+
// Quick menu with @clack/prompts
|
|
249
|
+
const p = yield Promise.resolve().then(() => __importStar(require('@clack/prompts')));
|
|
250
|
+
const action = yield p.select({
|
|
251
|
+
message: 'Quick menu',
|
|
252
|
+
options: [
|
|
253
|
+
{ label: `${theme_1.ICONS.dashboard} Dashboard`, value: 'dashboard', hint: isDashboardRunning() ? 'Open' : 'Start & open' },
|
|
254
|
+
{ label: `${theme_1.ICONS.task} My Tasks`, value: 'tasks', hint: `${taskCounts.totalTasks} total` },
|
|
255
|
+
{ label: `📈 Status`, value: 'status', hint: 'Health snapshot' },
|
|
256
|
+
{ label: `${theme_1.ICONS.skill} Browse Skills`, value: 'skills', hint: '34 skills' },
|
|
257
|
+
{ label: `➕ Add a Task`, value: 'addtask', hint: 'Quick add' },
|
|
258
|
+
{ label: `⚡ Install Skills`, value: 'install', hint: 'Update all' },
|
|
259
|
+
{ label: `${theme_1.ICONS.hamster} My Profile`, value: 'profile', hint: `${profile.level}` },
|
|
260
|
+
{ label: `❓ Help`, value: 'help' },
|
|
213
261
|
],
|
|
214
|
-
hint: '↑↓ navigate · Enter select · Ctrl+C exit',
|
|
215
262
|
});
|
|
216
|
-
|
|
217
|
-
|
|
263
|
+
if (p.isCancel(action)) {
|
|
264
|
+
console.log((0, theme_1.dim)('\n See you soon! 🐹\n'));
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
console.log('');
|
|
268
|
+
switch (action) {
|
|
218
269
|
case 'dashboard':
|
|
219
270
|
if (!isDashboardRunning()) {
|
|
220
271
|
(0, dashboard_1.launchDashboard)(data_1.DEFAULT_PORT, false);
|
|
221
272
|
yield new Promise(r => setTimeout(r, 800));
|
|
222
273
|
}
|
|
223
|
-
console.log(
|
|
274
|
+
console.log((0, theme_1.info)(` 🌐 Opening http://localhost:${data_1.DEFAULT_PORT} ...`));
|
|
224
275
|
openUrl(`http://localhost:${data_1.DEFAULT_PORT}`);
|
|
225
|
-
console.log(
|
|
276
|
+
console.log((0, theme_1.dim)(' Dashboard is running. Ctrl+C to stop.\n'));
|
|
226
277
|
break;
|
|
227
278
|
case 'tasks':
|
|
228
|
-
// Inline task list
|
|
229
279
|
require('child_process').spawnSync(process.execPath, [process.argv[1], 'task', 'list'], { stdio: 'inherit' });
|
|
230
280
|
break;
|
|
231
281
|
case 'status':
|
|
@@ -235,25 +285,41 @@ function showInteractiveMenu() {
|
|
|
235
285
|
skillList();
|
|
236
286
|
break;
|
|
237
287
|
case 'addtask': {
|
|
238
|
-
const
|
|
239
|
-
|
|
240
|
-
|
|
288
|
+
const title = yield p.text({
|
|
289
|
+
message: 'Task title:',
|
|
290
|
+
placeholder: 'What are you working on?',
|
|
291
|
+
validate: (val) => {
|
|
292
|
+
if (!val || val.trim().length === 0)
|
|
293
|
+
return 'Give your task a title!';
|
|
294
|
+
return undefined;
|
|
295
|
+
},
|
|
296
|
+
});
|
|
297
|
+
if (!p.isCancel(title) && title) {
|
|
298
|
+
require('child_process').spawnSync(process.execPath, [process.argv[1], 'task', 'add', title], { stdio: 'inherit' });
|
|
241
299
|
}
|
|
242
300
|
break;
|
|
243
301
|
}
|
|
244
302
|
case 'install':
|
|
245
|
-
console.log(
|
|
303
|
+
console.log(` ${(0, theme_1.brand)('→')} Run: ${(0, theme_1.brandBold)('npx codymaster add --all')}\n`);
|
|
304
|
+
break;
|
|
305
|
+
case 'profile':
|
|
306
|
+
console.log((0, hooks_1.formatProfileSummary)(profile));
|
|
246
307
|
break;
|
|
247
308
|
case 'help':
|
|
248
|
-
default:
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
309
|
+
default: {
|
|
310
|
+
const helpItems = [
|
|
311
|
+
`${(0, theme_1.brand)('cm')} ${(0, theme_1.dim)('Quick menu')}`,
|
|
312
|
+
`${(0, theme_1.brand)('cm task add')} ${(0, theme_1.dim)('"..."')} ${(0, theme_1.dim)('Add a task')}`,
|
|
313
|
+
`${(0, theme_1.brand)('cm task list')} ${(0, theme_1.dim)('View tasks')}`,
|
|
314
|
+
`${(0, theme_1.brand)('cm status')} ${(0, theme_1.dim)('Project health')}`,
|
|
315
|
+
`${(0, theme_1.brand)('cm dashboard')} ${(0, theme_1.dim)('Mission Control')}`,
|
|
316
|
+
`${(0, theme_1.brand)('cm list')} ${(0, theme_1.dim)('Browse 34 skills')}`,
|
|
317
|
+
`${(0, theme_1.brand)('cm deploy')} ${(0, theme_1.dim)('<env>')} ${(0, theme_1.dim)('Record deploy')}`,
|
|
318
|
+
`${(0, theme_1.brand)('cm profile')} ${(0, theme_1.dim)('Your stats')}`,
|
|
319
|
+
];
|
|
320
|
+
console.log((0, box_1.renderBox)(helpItems, { title: 'Commands', width: 52 }));
|
|
321
|
+
console.log('');
|
|
322
|
+
}
|
|
257
323
|
}
|
|
258
324
|
});
|
|
259
325
|
}
|
|
@@ -1043,6 +1109,10 @@ const PLATFORM_TARGETS = {
|
|
|
1043
1109
|
opencode: { dir: '.opencode/skills', invoke: '@[/<skill>]', note: 'OpenCode skills directory' },
|
|
1044
1110
|
kiro: { dir: '.kiro/steering', invoke: '@<skill>', note: 'Kiro steering documents' },
|
|
1045
1111
|
copilot: { dir: '.github', invoke: '(auto-context)', note: 'Added to copilot-instructions.md' },
|
|
1112
|
+
aider: { dir: '.aider/skills', invoke: '@[/<skill>]', note: 'Aider skills directory (reference in .aider.conf.yml)' },
|
|
1113
|
+
continue: { dir: '.continue/rules', invoke: '@<skill>', note: 'Continue.dev rules directory' },
|
|
1114
|
+
amazonq: { dir: '.aws/amazonq/skills', invoke: '@<skill>', note: 'Amazon Q skills directory' },
|
|
1115
|
+
amp: { dir: '.amp/skills', invoke: '@<skill>', note: 'Amp skills directory' },
|
|
1046
1116
|
};
|
|
1047
1117
|
const RAW_BASE = 'https://raw.githubusercontent.com/tody-agent/codymaster/main';
|
|
1048
1118
|
function autoDetectPlatform() {
|
|
@@ -1129,19 +1199,8 @@ function doAddSkills(skills, platform) {
|
|
|
1129
1199
|
}
|
|
1130
1200
|
return;
|
|
1131
1201
|
}
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
try {
|
|
1135
|
-
execFileSync('gemini', ['extensions', 'install', 'https://github.com/tody-agent/codymaster'], { stdio: 'inherit' });
|
|
1136
|
-
console.log('\n' + chalk_1.default.green('✅ All 34 skills installed for Gemini CLI!'));
|
|
1137
|
-
yield postInstallOnboarding('gemini');
|
|
1138
|
-
}
|
|
1139
|
-
catch (_c) {
|
|
1140
|
-
console.log(chalk_1.default.yellow('💡 Run this in your terminal:\n'));
|
|
1141
|
-
console.log(chalk_1.default.cyan(' gemini extensions install https://github.com/tody-agent/codymaster\n'));
|
|
1142
|
-
}
|
|
1143
|
-
return;
|
|
1144
|
-
}
|
|
1202
|
+
// Removed the fictional gemini extensions install block.
|
|
1203
|
+
// Gemini now falls through to the standard file-cloning logic below.
|
|
1145
1204
|
const target = PLATFORM_TARGETS[platform];
|
|
1146
1205
|
if (!target) {
|
|
1147
1206
|
console.log(chalk_1.default.red(`❌ Unknown platform: ${platform}`));
|
|
@@ -1169,8 +1228,30 @@ function doAddSkills(skills, platform) {
|
|
|
1169
1228
|
let ok = 0, fail = 0;
|
|
1170
1229
|
for (const skill of skills) {
|
|
1171
1230
|
const url = `${RAW_BASE}/skills/${skill}/SKILL.md`;
|
|
1172
|
-
|
|
1231
|
+
let dest = path_1.default.join(target.dir, skill, 'SKILL.md');
|
|
1232
|
+
// Formatting logic to adapt to specific IDE required formats
|
|
1233
|
+
if (platform === 'cursor') {
|
|
1234
|
+
dest = path_1.default.join(target.dir, `${skill}.mdc`);
|
|
1235
|
+
}
|
|
1236
|
+
else if (platform === 'continue') {
|
|
1237
|
+
dest = path_1.default.join(target.dir, `${skill}.md`);
|
|
1238
|
+
}
|
|
1173
1239
|
const success = yield downloadFile(url, dest);
|
|
1240
|
+
// Prepend Cursor MDC glob formatting
|
|
1241
|
+
if (success && platform === 'cursor') {
|
|
1242
|
+
try {
|
|
1243
|
+
const content = fs_1.default.readFileSync(dest, 'utf-8');
|
|
1244
|
+
if (!content.startsWith('---')) {
|
|
1245
|
+
const yamlFrontmatter = `---\ndescription: ${skill}\nglobs: *\n---\n`;
|
|
1246
|
+
fs_1.default.writeFileSync(dest, yamlFrontmatter + content);
|
|
1247
|
+
}
|
|
1248
|
+
else if (!content.includes('globs:')) {
|
|
1249
|
+
const newContent = content.replace(/^---/, '---\nglobs: *');
|
|
1250
|
+
fs_1.default.writeFileSync(dest, newContent);
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
1253
|
+
catch (err) { }
|
|
1254
|
+
}
|
|
1174
1255
|
if (success) {
|
|
1175
1256
|
process.stdout.write(chalk_1.default.green(` ✅ ${skill}\n`));
|
|
1176
1257
|
ok++;
|
|
@@ -1229,13 +1310,17 @@ program
|
|
|
1229
1310
|
type: 'select', name: 'platform', message: 'Select your AI coding platform:',
|
|
1230
1311
|
choices: [
|
|
1231
1312
|
{ title: '🟣 Claude Code (recommended)', value: 'claude' },
|
|
1232
|
-
{ title: '💻 Gemini CLI', value: 'gemini' },
|
|
1313
|
+
{ title: '💻 Gemini CLI & Antigravity', value: 'gemini' },
|
|
1233
1314
|
{ title: '🔵 Cursor', value: 'cursor' },
|
|
1234
1315
|
{ title: '🟠 Windsurf', value: 'windsurf' },
|
|
1235
1316
|
{ title: '⚫ Cline / RooCode', value: 'cline' },
|
|
1236
1317
|
{ title: '📦 OpenCode', value: 'opencode' },
|
|
1237
1318
|
{ title: '🔶 Kiro (AWS)', value: 'kiro' },
|
|
1238
1319
|
{ title: '🐙 GitHub Copilot', value: 'copilot' },
|
|
1320
|
+
{ title: '🤖 Aider', value: 'aider' },
|
|
1321
|
+
{ title: '🔗 Continue.dev', value: 'continue' },
|
|
1322
|
+
{ title: '☁️ Amazon Q', value: 'amazonq' },
|
|
1323
|
+
{ title: '⚡ Amp', value: 'amp' },
|
|
1239
1324
|
],
|
|
1240
1325
|
});
|
|
1241
1326
|
if (!resp.platform)
|
|
@@ -1281,6 +1366,24 @@ program
|
|
|
1281
1366
|
.action((opts) => {
|
|
1282
1367
|
skillList(opts.domain);
|
|
1283
1368
|
});
|
|
1369
|
+
// ─── Profile Command ──────────────────────────────────────────────────────────
|
|
1370
|
+
program
|
|
1371
|
+
.command('profile')
|
|
1372
|
+
.description('View your CodyMaster profile, stats, and achievements')
|
|
1373
|
+
.action(() => {
|
|
1374
|
+
const profile = (0, hooks_1.loadProfile)();
|
|
1375
|
+
if (!profile.onboardingComplete) {
|
|
1376
|
+
console.log((0, theme_1.dim)('\n Run cm first to complete setup! 🐹\n'));
|
|
1377
|
+
return;
|
|
1378
|
+
}
|
|
1379
|
+
(0, hooks_1.recordCommand)(profile, 'profile');
|
|
1380
|
+
const newAchievements = (0, hooks_1.checkAchievements)(profile);
|
|
1381
|
+
(0, hooks_1.saveProfile)(profile);
|
|
1382
|
+
console.log((0, hooks_1.formatProfileSummary)(profile));
|
|
1383
|
+
for (const id of newAchievements) {
|
|
1384
|
+
console.log((0, hooks_1.formatAchievement)(id));
|
|
1385
|
+
}
|
|
1386
|
+
});
|
|
1284
1387
|
// ─── Continuity Command (Working Memory) ────────────────────────────────────
|
|
1285
1388
|
program
|
|
1286
1389
|
.command('continuity [cmd]')
|
|
@@ -2431,4 +2534,6 @@ if (!SKIP_DASHBOARD_CMDS.has(firstArg) && firstArg !== '' && !firstArg.startsWit
|
|
|
2431
2534
|
(0, dashboard_1.launchDashboard)(data_1.DEFAULT_PORT, true);
|
|
2432
2535
|
}
|
|
2433
2536
|
}
|
|
2537
|
+
// Kick off update check (non-blocking)
|
|
2538
|
+
checkForUpdates().catch(() => { });
|
|
2434
2539
|
program.parse(process.argv);
|