@lenne.tech/cli 0.0.124 → 1.0.0

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.
Files changed (30) hide show
  1. package/bin/lt +145 -14
  2. package/build/commands/claude/claude.js +25 -0
  3. package/build/commands/claude/install-skills.js +622 -0
  4. package/build/commands/config/config.js +25 -0
  5. package/build/commands/config/help.js +167 -0
  6. package/build/commands/config/init.js +143 -0
  7. package/build/commands/config/show.js +68 -0
  8. package/build/commands/fullstack/init.js +38 -16
  9. package/build/commands/server/add-property.js +199 -36
  10. package/build/commands/server/create.js +66 -4
  11. package/build/commands/server/module.js +150 -27
  12. package/build/commands/server/object.js +38 -22
  13. package/build/extensions/config.js +157 -0
  14. package/build/extensions/parse-properties.js +119 -0
  15. package/build/extensions/server.js +82 -47
  16. package/build/interfaces/lt-config.interface.js +3 -0
  17. package/build/templates/claude-skills/lt-cli/SKILL.md +272 -0
  18. package/build/templates/claude-skills/lt-cli/examples.md +542 -0
  19. package/build/templates/claude-skills/lt-cli/reference.md +506 -0
  20. package/build/templates/claude-skills/nest-server-generator/SKILL.md +2833 -0
  21. package/build/templates/claude-skills/nest-server-generator/examples.md +760 -0
  22. package/build/templates/claude-skills/nest-server-generator/reference.md +417 -0
  23. package/build/templates/nest-server-module/inputs/template-create.input.ts.ejs +1 -3
  24. package/build/templates/nest-server-module/inputs/template.input.ts.ejs +1 -1
  25. package/build/templates/nest-server-module/template.controller.ts.ejs +24 -13
  26. package/build/templates/nest-server-module/template.model.ts.ejs +2 -2
  27. package/build/templates/nest-server-module/template.module.ts.ejs +4 -0
  28. package/build/templates/nest-server-module/template.service.ts.ejs +6 -6
  29. package/build/templates/nest-server-object/template.object.ts.ejs +2 -2
  30. package/package.json +13 -11
@@ -0,0 +1,622 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const os_1 = require("os");
13
+ const path_1 = require("path");
14
+ /**
15
+ * Skill-specific permissions mapping
16
+ */
17
+ const SKILL_PERMISSIONS = {
18
+ 'lt-cli': [
19
+ 'Bash(lt:*)',
20
+ ],
21
+ 'nest-server-generator': [
22
+ 'Bash(lt server:*)',
23
+ ],
24
+ };
25
+ /**
26
+ * Get skill descriptions from SKILL.md frontmatter
27
+ */
28
+ function getSkillDescription(skillDir, filesystem) {
29
+ const skillMdPath = (0, path_1.join)(skillDir, 'SKILL.md');
30
+ if (!filesystem.exists(skillMdPath)) {
31
+ return 'No description available';
32
+ }
33
+ const content = filesystem.read(skillMdPath);
34
+ const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
35
+ if (!frontmatterMatch) {
36
+ return 'No description available';
37
+ }
38
+ const frontmatter = frontmatterMatch[1];
39
+ const descMatch = frontmatter.match(/description:\s*([^\n]+)/);
40
+ return descMatch ? descMatch[1].trim() : 'No description available';
41
+ }
42
+ /**
43
+ * Install a single skill
44
+ */
45
+ function installSingleSkill(skillName, cliRoot, filesystem, info, error) {
46
+ return __awaiter(this, void 0, void 0, function* () {
47
+ const templatesDir = (0, path_1.join)(cliRoot, 'templates', 'claude-skills', skillName);
48
+ // Check if templates exist
49
+ if (!filesystem.exists(templatesDir)) {
50
+ error(`Skill '${skillName}' not found in CLI installation.`);
51
+ info(`Expected location: ${templatesDir}`);
52
+ return { copiedCount: 0, skippedCount: 0, skippedFiles: [], success: false, updatedCount: 0 };
53
+ }
54
+ // Create ~/.claude/skills/<skillName> directory
55
+ const skillsDir = (0, path_1.join)((0, os_1.homedir)(), '.claude', 'skills', skillName);
56
+ if (!filesystem.exists(skillsDir)) {
57
+ filesystem.dir(skillsDir);
58
+ }
59
+ // Copy all skill files with version checking
60
+ const skillFiles = ['SKILL.md', 'examples.md', 'reference.md'];
61
+ let copiedCount = 0;
62
+ let skippedCount = 0;
63
+ let updatedCount = 0;
64
+ const skippedFiles = [];
65
+ info(`\nInstalling skill: ${skillName}`);
66
+ for (const file of skillFiles) {
67
+ const sourcePath = (0, path_1.join)(templatesDir, file);
68
+ const targetPath = (0, path_1.join)(skillsDir, file);
69
+ if (!filesystem.exists(sourcePath)) {
70
+ info(` Warning: ${file} not found in templates, skipping...`);
71
+ continue;
72
+ }
73
+ const sourceContent = filesystem.read(sourcePath);
74
+ // Check if target file exists
75
+ if (filesystem.exists(targetPath)) {
76
+ const targetContent = filesystem.read(targetPath);
77
+ // Parse versions from both files
78
+ const sourceVersion = parseVersion(sourceContent);
79
+ const targetVersion = parseVersion(targetContent);
80
+ // If both have versions, compare them
81
+ if (sourceVersion && targetVersion) {
82
+ if (isVersionNewer(sourceVersion, targetVersion)) {
83
+ // Source is newer or equal, update
84
+ filesystem.write(targetPath, sourceContent);
85
+ updatedCount++;
86
+ copiedCount++;
87
+ info(` ✓ Updated ${file} (${targetVersion} → ${sourceVersion})`);
88
+ }
89
+ else {
90
+ // Target is newer, skip
91
+ skippedCount++;
92
+ const reason = `local version ${targetVersion} is newer than ${sourceVersion}`;
93
+ skippedFiles.push({ file: `${skillName}/${file}`, reason });
94
+ info(` ⊙ Skipped ${file} (${reason})`);
95
+ }
96
+ }
97
+ else if (sourceVersion && !targetVersion) {
98
+ // Source has version, target doesn't - update
99
+ filesystem.write(targetPath, sourceContent);
100
+ updatedCount++;
101
+ copiedCount++;
102
+ info(` ✓ Updated ${file} (no version → ${sourceVersion})`);
103
+ }
104
+ else {
105
+ // No version info, always update (backward compatibility)
106
+ filesystem.write(targetPath, sourceContent);
107
+ updatedCount++;
108
+ copiedCount++;
109
+ info(` ✓ Updated ${file} (no version control)`);
110
+ }
111
+ }
112
+ else {
113
+ // Target doesn't exist, create new
114
+ filesystem.write(targetPath, sourceContent);
115
+ copiedCount++;
116
+ const version = parseVersion(sourceContent);
117
+ info(` + Created ${file}${version ? ` (v${version})` : ''}`);
118
+ }
119
+ }
120
+ return { copiedCount, skippedCount, skippedFiles, success: true, updatedCount };
121
+ });
122
+ }
123
+ /**
124
+ * Compare semantic versions
125
+ * Returns true if sourceVersion >= targetVersion
126
+ */
127
+ function isVersionNewer(sourceVersion, targetVersion) {
128
+ const parseSemver = (version) => {
129
+ return version.split('.').map(n => parseInt(n, 10) || 0);
130
+ };
131
+ const source = parseSemver(sourceVersion);
132
+ const target = parseSemver(targetVersion);
133
+ // Compare major, minor, patch
134
+ for (let i = 0; i < 3; i++) {
135
+ if (source[i] > target[i]) {
136
+ return true;
137
+ }
138
+ if (source[i] < target[i]) {
139
+ return false;
140
+ }
141
+ }
142
+ // Versions are equal
143
+ return true;
144
+ }
145
+ /**
146
+ * Parse frontmatter from markdown file and extract version
147
+ */
148
+ function parseVersion(content) {
149
+ const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
150
+ if (!frontmatterMatch) {
151
+ return null;
152
+ }
153
+ const frontmatter = frontmatterMatch[1];
154
+ const versionMatch = frontmatter.match(/version:\s*([^\n]+)/);
155
+ return versionMatch ? versionMatch[1].trim() : null;
156
+ }
157
+ /**
158
+ * Setup project detection hook for nest-server-generator
159
+ */
160
+ function setupProjectDetectionHook(filesystem, info, error, promptConfirm, skipInteractive) {
161
+ return __awaiter(this, void 0, void 0, function* () {
162
+ const globalSettingsPath = (0, path_1.join)((0, os_1.homedir)(), '.claude', 'settings.json');
163
+ const cwd = filesystem.cwd();
164
+ // Detect if we're in a project with package.json
165
+ let packageJsonPath = null;
166
+ let searchDir = cwd;
167
+ // Search up to 3 levels for package.json
168
+ for (let i = 0; i < 3; i++) {
169
+ const testPath = (0, path_1.join)(searchDir, 'package.json');
170
+ if (filesystem.exists(testPath)) {
171
+ packageJsonPath = testPath;
172
+ break;
173
+ }
174
+ const parent = (0, path_1.join)(searchDir, '..');
175
+ if (parent === searchDir)
176
+ break; // Reached root
177
+ searchDir = parent;
178
+ }
179
+ // Determine installation scope
180
+ let scope = 'global';
181
+ let settingsPath = globalSettingsPath;
182
+ let projectRoot = null;
183
+ if (packageJsonPath) {
184
+ projectRoot = searchDir;
185
+ const projectSettingsPath = (0, path_1.join)(projectRoot, '.claude', 'settings.json');
186
+ // Ask where to install the hook
187
+ if (!skipInteractive) {
188
+ info('');
189
+ info(`Detected project at: ${projectRoot}`);
190
+ const choices = [
191
+ { name: 'Global (~/.claude/settings.json) - Available for all projects', value: 'global' },
192
+ { name: `Project (${projectRoot}/.claude/settings.json) - Only this project`, value: 'project' }
193
+ ];
194
+ const answer = yield promptConfirm({
195
+ choices: choices.map(c => c.name),
196
+ initial: 1, // Default to project
197
+ message: 'Where should the project detection hook be installed?',
198
+ name: 'scope',
199
+ type: 'select',
200
+ });
201
+ // Map the choice back to the value
202
+ scope = choices[answer.scope === 0 ? 0 : 1].value;
203
+ }
204
+ else {
205
+ // In non-interactive mode, prefer project if we found one
206
+ scope = 'project';
207
+ }
208
+ if (scope === 'project') {
209
+ settingsPath = projectSettingsPath;
210
+ // Ensure .claude directory exists
211
+ filesystem.dir((0, path_1.join)(projectRoot, '.claude'));
212
+ }
213
+ }
214
+ try {
215
+ // Read existing settings
216
+ let settings = {};
217
+ if (filesystem.exists(settingsPath)) {
218
+ const content = filesystem.read(settingsPath);
219
+ settings = JSON.parse(content);
220
+ }
221
+ // Ensure hooks array exists
222
+ if (!settings.hooks) {
223
+ settings.hooks = [];
224
+ }
225
+ // Check if hook already exists
226
+ const hookExists = settings.hooks.some((hook) => hook.event === 'user-prompt-submit' &&
227
+ hook.name === 'nest-server-detector');
228
+ if (hookExists) {
229
+ return {
230
+ added: false,
231
+ alreadyExists: true,
232
+ scope,
233
+ success: true,
234
+ };
235
+ }
236
+ // Create the hook configuration
237
+ const hook = {
238
+ command: `
239
+ # Detect @lenne.tech/nest-server in package.json and suggest using nest-server-generator skill
240
+ # Supports both single projects and monorepos
241
+
242
+ # Check if the prompt mentions NestJS-related tasks first
243
+ if ! echo "$PROMPT" | grep -qiE "(module|service|controller|resolver|model|object|nestjs|nest-server|lt server)"; then
244
+ # Not a NestJS-related prompt, skip
245
+ echo '{}'
246
+ exit 0
247
+ fi
248
+
249
+ # Function to check if package.json contains @lenne.tech/nest-server
250
+ check_package_json() {
251
+ local pkg_json="$1"
252
+ if [ -f "$pkg_json" ] && grep -q "@lenne\\.tech/nest-server" "$pkg_json"; then
253
+ return 0
254
+ fi
255
+ return 1
256
+ }
257
+
258
+ # First, check package.json in project root
259
+ if check_package_json "$CLAUDE_PROJECT_DIR/package.json"; then
260
+ cat << 'EOF'
261
+ {
262
+ "contextToAppend": "\\n\\n📦 Detected @lenne.tech/nest-server in this project. Consider using the nest-server-generator skill for this task."
263
+ }
264
+ EOF
265
+ exit 0
266
+ fi
267
+
268
+ # If not found in root, check common monorepo patterns
269
+ for pattern in "projects/*/package.json" "packages/*/package.json" "apps/*/package.json"; do
270
+ for pkg_json in $CLAUDE_PROJECT_DIR/$pattern; do
271
+ if check_package_json "$pkg_json"; then
272
+ cat << 'EOF'
273
+ {
274
+ "contextToAppend": "\\n\\n📦 Detected @lenne.tech/nest-server in this monorepo. Consider using the nest-server-generator skill for this task."
275
+ }
276
+ EOF
277
+ exit 0
278
+ fi
279
+ done
280
+ done
281
+
282
+ # No @lenne.tech/nest-server found
283
+ echo '{}'
284
+ exit 0
285
+ `.trim(),
286
+ description: 'Detects projects using @lenne.tech/nest-server and suggests using nest-server-generator skill',
287
+ event: 'user-prompt-submit',
288
+ name: 'nest-server-detector',
289
+ type: 'command',
290
+ };
291
+ // Add the hook
292
+ settings.hooks.push(hook);
293
+ // Write back settings
294
+ filesystem.write(settingsPath, JSON.stringify(settings, null, 2));
295
+ return {
296
+ added: true,
297
+ alreadyExists: false,
298
+ scope,
299
+ success: true,
300
+ };
301
+ }
302
+ catch (err) {
303
+ error(`Could not configure project detection hook: ${err.message}`);
304
+ return {
305
+ added: false,
306
+ alreadyExists: false,
307
+ error: true,
308
+ scope: 'none',
309
+ success: false,
310
+ };
311
+ }
312
+ });
313
+ }
314
+ /**
315
+ * Setup global permissions for installed skills
316
+ */
317
+ function setupSkillPermissions(skills, filesystem, error) {
318
+ return __awaiter(this, void 0, void 0, function* () {
319
+ const settingsPath = (0, path_1.join)((0, os_1.homedir)(), '.claude', 'settings.json');
320
+ // Collect all requested permissions
321
+ const requestedPermissions = [];
322
+ skills.forEach(skill => {
323
+ const perms = SKILL_PERMISSIONS[skill];
324
+ if (perms) {
325
+ requestedPermissions.push(...perms);
326
+ }
327
+ });
328
+ if (requestedPermissions.length === 0) {
329
+ return { added: [], error: false, existing: [], requested: [], success: true };
330
+ }
331
+ try {
332
+ // Read existing settings
333
+ let settings = {};
334
+ if (filesystem.exists(settingsPath)) {
335
+ const content = filesystem.read(settingsPath);
336
+ settings = JSON.parse(content);
337
+ }
338
+ // Ensure permissions.allow exists
339
+ if (!settings.permissions) {
340
+ settings.permissions = {};
341
+ }
342
+ if (!settings.permissions.allow) {
343
+ settings.permissions.allow = [];
344
+ }
345
+ // Check which permissions are new vs existing
346
+ const existingPerms = new Set(settings.permissions.allow);
347
+ const added = [];
348
+ const existing = [];
349
+ requestedPermissions.forEach(perm => {
350
+ if (existingPerms.has(perm)) {
351
+ existing.push(perm);
352
+ }
353
+ else {
354
+ added.push(perm);
355
+ settings.permissions.allow.push(perm);
356
+ }
357
+ });
358
+ // Write back settings
359
+ filesystem.write(settingsPath, JSON.stringify(settings, null, 2));
360
+ return {
361
+ added,
362
+ existing,
363
+ requested: requestedPermissions,
364
+ success: true,
365
+ };
366
+ }
367
+ catch (err) {
368
+ error(`Could not configure permissions: ${err.message}`);
369
+ return {
370
+ added: [],
371
+ error: true,
372
+ existing: [],
373
+ requested: requestedPermissions,
374
+ success: false,
375
+ };
376
+ }
377
+ });
378
+ }
379
+ /**
380
+ * Install Claude Skills to ~/.claude/skills/
381
+ */
382
+ const NewCommand = {
383
+ alias: ['skills', 'is'],
384
+ description: 'Installs Claude Skills to ~/.claude/skills/ for Claude Code integration. Interactively select which skills to install. Use -y to skip interactive selection and install all skills.',
385
+ hidden: false,
386
+ name: 'install-skills',
387
+ run: (toolbox) => __awaiter(void 0, void 0, void 0, function* () {
388
+ // Retrieve the tools we need
389
+ const { filesystem, parameters, print: { error, info, spin, success }, prompt, } = toolbox;
390
+ try {
391
+ // Get the CLI installation directory
392
+ const cliRoot = (0, path_1.join)(__dirname, '..', '..');
393
+ const claudeSkillsDir = (0, path_1.join)(cliRoot, 'templates', 'claude-skills');
394
+ // Check if claude-skills directory exists
395
+ if (!filesystem.exists(claudeSkillsDir)) {
396
+ error('Claude skills directory not found in CLI installation.');
397
+ info(`Expected location: ${claudeSkillsDir}`);
398
+ info('Please reinstall the CLI or report this issue.');
399
+ return;
400
+ }
401
+ // Get all available skills
402
+ const items = filesystem.list(claudeSkillsDir);
403
+ const availableSkills = items.filter(item => filesystem.isDirectory((0, path_1.join)(claudeSkillsDir, item)));
404
+ if (availableSkills.length === 0) {
405
+ error('No skills found in CLI installation.');
406
+ return;
407
+ }
408
+ let skillsToInstall = [];
409
+ const skipInteractive = parameters.options.y || parameters.options.yes || parameters.options['no-interactive'];
410
+ // Check if specific skills provided as parameters
411
+ if (parameters.first && parameters.first !== 'all') {
412
+ // Non-interactive mode: install specific skill(s)
413
+ const requestedSkills = parameters.array || [parameters.first];
414
+ // Validate requested skills
415
+ const invalidSkills = requestedSkills.filter(s => !availableSkills.includes(s));
416
+ if (invalidSkills.length > 0) {
417
+ error(`Invalid skill(s): ${invalidSkills.join(', ')}`);
418
+ info('');
419
+ info('Available skills:');
420
+ availableSkills.forEach(s => {
421
+ const desc = getSkillDescription((0, path_1.join)(claudeSkillsDir, s), filesystem);
422
+ info(` • ${s}`);
423
+ info(` ${desc}`);
424
+ });
425
+ return;
426
+ }
427
+ skillsToInstall = requestedSkills;
428
+ }
429
+ else if (parameters.first === 'all' || skipInteractive) {
430
+ // Install all skills without prompting
431
+ skillsToInstall = availableSkills;
432
+ if (skipInteractive) {
433
+ info('Installing all skills (non-interactive mode)...');
434
+ }
435
+ }
436
+ else {
437
+ // Interactive mode: ask for each skill individually
438
+ info('');
439
+ info('Available skills:');
440
+ info('');
441
+ // Show all available skills with descriptions
442
+ availableSkills.forEach(skill => {
443
+ const desc = getSkillDescription((0, path_1.join)(claudeSkillsDir, skill), filesystem);
444
+ info(` • ${skill}`);
445
+ info(` ${desc.substring(0, 100)}${desc.length > 100 ? '...' : ''}`);
446
+ info('');
447
+ });
448
+ // Ask if user wants to install all or select individually
449
+ const installAll = yield prompt.confirm('Install all skills?', true);
450
+ if (installAll) {
451
+ skillsToInstall = availableSkills;
452
+ }
453
+ else {
454
+ // Ask for each skill
455
+ info('');
456
+ info('Select which skills to install:');
457
+ info('');
458
+ for (const skill of availableSkills) {
459
+ const shouldInstall = yield prompt.confirm(`Install ${skill}?`, true);
460
+ if (shouldInstall) {
461
+ skillsToInstall.push(skill);
462
+ }
463
+ }
464
+ if (skillsToInstall.length === 0) {
465
+ info('No skills selected. Installation cancelled.');
466
+ return;
467
+ }
468
+ }
469
+ }
470
+ const installSpinner = spin(`Installing ${skillsToInstall.length} skill(s)...`);
471
+ let totalCopied = 0;
472
+ let totalSkipped = 0;
473
+ let totalUpdated = 0;
474
+ const allSkippedFiles = [];
475
+ // Install each skill
476
+ for (const skill of skillsToInstall) {
477
+ const result = yield installSingleSkill(skill, cliRoot, filesystem, info, error);
478
+ if (!result.success) {
479
+ continue;
480
+ }
481
+ totalCopied += result.copiedCount;
482
+ totalSkipped += result.skippedCount;
483
+ totalUpdated += result.updatedCount;
484
+ allSkippedFiles.push(...result.skippedFiles);
485
+ }
486
+ if (totalCopied === 0 && totalSkipped === 0) {
487
+ installSpinner.fail();
488
+ error('No skill files were found.');
489
+ return;
490
+ }
491
+ if (totalCopied === 0 && totalSkipped > 0) {
492
+ installSpinner.succeed('All selected skills are already up to date!');
493
+ info('');
494
+ info(`Skipped: ${totalSkipped} file(s) across ${skillsToInstall.length} skill(s)`);
495
+ info(`Location: ${(0, path_1.join)((0, os_1.homedir)(), '.claude', 'skills')}`);
496
+ return;
497
+ }
498
+ installSpinner.succeed(`Successfully installed ${skillsToInstall.length} skill(s) to ~/.claude/skills/`);
499
+ info('');
500
+ if (totalUpdated > 0 && totalSkipped > 0) {
501
+ success(`Updated ${totalUpdated} file(s), skipped ${totalSkipped} file(s)`);
502
+ }
503
+ else if (totalUpdated > 0) {
504
+ success(`Updated ${totalUpdated} file(s)`);
505
+ }
506
+ else {
507
+ success(`Created ${totalCopied} file(s)`);
508
+ }
509
+ info('');
510
+ info('Installed skills:');
511
+ skillsToInstall.forEach(s => {
512
+ const desc = getSkillDescription((0, path_1.join)(claudeSkillsDir, s), filesystem);
513
+ info(` • ${s}`);
514
+ info(` ${desc.substring(0, 100)}${desc.length > 100 ? '...' : ''}`);
515
+ });
516
+ info('');
517
+ info('These skills are now available in Claude Code!');
518
+ info('Claude will automatically use them when appropriate.');
519
+ info('');
520
+ info('Examples:');
521
+ if (skillsToInstall.includes('lt-cli')) {
522
+ info(' • "Create a User module with email and username"');
523
+ }
524
+ if (skillsToInstall.includes('nest-server-generator')) {
525
+ info(' • "Generate the complete server structure from this specification"');
526
+ }
527
+ info('');
528
+ info(`Location: ${(0, path_1.join)((0, os_1.homedir)(), '.claude', 'skills')}`);
529
+ if (totalSkipped > 0) {
530
+ info('');
531
+ info(`Note: ${totalSkipped} file(s) were skipped because your local versions are newer:`);
532
+ allSkippedFiles.forEach(({ file, reason }) => {
533
+ info(` • ${file} (${reason})`);
534
+ });
535
+ info('');
536
+ info('To force update, manually delete the files and run this command again.');
537
+ }
538
+ // Ask about setting up permissions
539
+ info('');
540
+ const setupPermissions = skipInteractive ? true : yield prompt.confirm('Set up global permissions for these skills? (Recommended - auto-approves skill-related commands)', true);
541
+ if (setupPermissions) {
542
+ const permissionsResult = yield setupSkillPermissions(skillsToInstall, filesystem, error);
543
+ if (permissionsResult.success) {
544
+ info('');
545
+ success('Permissions configured successfully!');
546
+ if (permissionsResult.added.length > 0) {
547
+ info('Added permissions:');
548
+ permissionsResult.added.forEach(perm => {
549
+ info(` • ${perm}`);
550
+ });
551
+ }
552
+ if (permissionsResult.existing.length > 0) {
553
+ info('Already configured:');
554
+ permissionsResult.existing.forEach(perm => {
555
+ info(` • ${perm}`);
556
+ });
557
+ }
558
+ info('');
559
+ info('Location: ~/.claude/settings.json');
560
+ }
561
+ else if (permissionsResult.error) {
562
+ info('');
563
+ info('⚠ Could not automatically configure permissions.');
564
+ info('You can manually add these to ~/.claude/settings.json:');
565
+ info('');
566
+ info(JSON.stringify({
567
+ permissions: {
568
+ allow: permissionsResult.requested
569
+ }
570
+ }, null, 2));
571
+ }
572
+ }
573
+ // Ask about setting up project detection hook for nest-server-generator
574
+ if (skillsToInstall.includes('nest-server-generator')) {
575
+ info('');
576
+ const setupHook = skipInteractive ? false : yield prompt.confirm('Set up automatic project detection for @lenne.tech/nest-server? (Recommended - suggests nest-server-generator skill when detected)', false);
577
+ if (setupHook) {
578
+ const hookResult = yield setupProjectDetectionHook(filesystem, info, error, prompt.ask, skipInteractive);
579
+ if (hookResult.success) {
580
+ if (hookResult.added) {
581
+ info('');
582
+ success('Project detection hook configured successfully!');
583
+ info('');
584
+ info(`Scope: ${hookResult.scope === 'global' ? 'Global (all projects)' : 'Project-specific'}`);
585
+ info('');
586
+ info('How it works:');
587
+ info(' • Detects @lenne.tech/nest-server in package.json');
588
+ info(' • Supports monorepos: searches projects/*, packages/*, apps/* directories');
589
+ info(' • Suggests using nest-server-generator skill for NestJS tasks');
590
+ info(' • Works from any directory in the project');
591
+ info('');
592
+ info(`Location: ${hookResult.scope === 'global' ? '~/.claude/settings.json' : '.claude/settings.json'}`);
593
+ }
594
+ else if (hookResult.alreadyExists) {
595
+ info('');
596
+ info('✓ Project detection hook already configured');
597
+ info(` Scope: ${hookResult.scope === 'global' ? 'Global' : 'Project-specific'}`);
598
+ }
599
+ }
600
+ else if (hookResult.error) {
601
+ info('');
602
+ info('⚠ Could not automatically configure project detection hook.');
603
+ info('You can manually add this hook to your settings.json');
604
+ }
605
+ }
606
+ }
607
+ }
608
+ catch (err) {
609
+ error(`Failed to install skill(s): ${err.message}`);
610
+ info('');
611
+ info('Troubleshooting:');
612
+ info(' • Ensure ~/.claude directory exists and is writable');
613
+ info(' • Check file permissions');
614
+ info(' • Try running with sudo if permission issues persist');
615
+ return;
616
+ }
617
+ // For tests
618
+ return `claude install-skills`;
619
+ }),
620
+ };
621
+ exports.default = NewCommand;
622
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5zdGFsbC1za2lsbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvY29tbWFuZHMvY2xhdWRlL2luc3RhbGwtc2tpbGxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7O0FBQ0EsMkJBQTZCO0FBQzdCLCtCQUE0QjtBQUk1Qjs7R0FFRztBQUNILE1BQU0saUJBQWlCLEdBQTZCO0lBQ2xELFFBQVEsRUFBRTtRQUNSLFlBQVk7S0FDYjtJQUNELHVCQUF1QixFQUFFO1FBQ3ZCLG1CQUFtQjtLQUNwQjtDQUNGLENBQUM7QUFFRjs7R0FFRztBQUNILFNBQVMsbUJBQW1CLENBQUMsUUFBZ0IsRUFBRSxVQUFlO0lBQzVELE1BQU0sV0FBVyxHQUFHLElBQUEsV0FBSSxFQUFDLFFBQVEsRUFBRSxVQUFVLENBQUMsQ0FBQztJQUMvQyxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDO1FBQ3BDLE9BQU8sMEJBQTBCLENBQUM7SUFDcEMsQ0FBQztJQUVELE1BQU0sT0FBTyxHQUFHLFVBQVUsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7SUFDN0MsTUFBTSxnQkFBZ0IsR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDLHVCQUF1QixDQUFDLENBQUM7SUFDaEUsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7UUFDdEIsT0FBTywwQkFBMEIsQ0FBQztJQUNwQyxDQUFDO0lBRUQsTUFBTSxXQUFXLEdBQUcsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDeEMsTUFBTSxTQUFTLEdBQUcsV0FBVyxDQUFDLEtBQUssQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDO0lBRS9ELE9BQU8sU0FBUyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLDBCQUEwQixDQUFDO0FBQ3RFLENBQUM7QUFFRDs7R0FFRztBQUNILFNBQWUs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