prpm 0.1.8 → 0.1.10

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.
@@ -63,12 +63,12 @@ const FORMAT_EXAMPLES = {
63
63
  files: ['.windsurf/rules', 'README.md'],
64
64
  },
65
65
  copilot: {
66
- description: 'GitHub Copilot instructions',
67
- files: ['.github/copilot-instructions.md', 'README.md'],
66
+ description: 'GitHub Copilot (repository-wide, path-specific, and chat modes)',
67
+ files: ['.github/copilot-instructions.md', '.github/instructions/typescript.instructions.md', '.github/chatmodes/code-reviewer.chatmode.md', 'README.md'],
68
68
  },
69
69
  kiro: {
70
- description: 'Kiro steering files',
71
- files: ['.kiro/steering/example.md', 'README.md'],
70
+ description: 'Kiro steering files and hooks',
71
+ files: ['.kiro/steering/example.md', '.kiro/hooks/example-hook.kiro.hook', 'README.md'],
72
72
  },
73
73
  'agents.md': {
74
74
  description: 'OpenAI agents.md project instructions',
@@ -145,31 +145,49 @@ Add your Windsurf AI coding rules here.
145
145
  `,
146
146
  },
147
147
  copilot: {
148
- '.github/copilot-instructions.md': `---
149
- applyTo:
150
- - "**/*.ts"
151
- - "**/*.tsx"
152
- ---
148
+ '.github/copilot-instructions.md': `# GitHub Copilot Repository-Wide Instructions
153
149
 
154
- # GitHub Copilot Instructions
155
-
156
- Add your GitHub Copilot instructions here.
150
+ These instructions apply to all files in this repository.
157
151
 
158
152
  ## Code Standards
159
153
 
160
154
  - Use TypeScript strict mode
161
155
  - Follow ESLint rules
162
- - Write JSDoc comments
156
+ - Write JSDoc comments for public APIs
163
157
 
164
158
  ## Patterns to Follow
165
159
 
166
160
  - Use async/await for asynchronous operations
167
161
  - Implement error handling with try/catch
168
162
  - Export named functions instead of default exports
163
+ - Write unit tests for all new features
164
+ `,
165
+ '.github/instructions/typescript.instructions.md': `---
166
+ applyTo:
167
+ - "**/*.ts"
168
+ - "**/*.tsx"
169
+ ---
170
+
171
+ # TypeScript-Specific Instructions
172
+
173
+ These instructions apply only to TypeScript files.
174
+
175
+ ## Type Safety
176
+
177
+ - Use strict null checks
178
+ - Avoid 'any' type - use 'unknown' or specific types
179
+ - Define interfaces for all object shapes
180
+ - Use type guards for runtime type checking
181
+
182
+ ## Patterns
183
+
184
+ - Prefer const over let
185
+ - Use template literals for string concatenation
186
+ - Destructure objects and arrays when appropriate
169
187
  `,
170
- '.github/chatmodes/example.chatmode.md': `---
171
- name: Example Chat Mode
172
- description: Example custom chat mode for GitHub Copilot
188
+ '.github/chatmodes/code-reviewer.chatmode.md': `---
189
+ name: Code Reviewer
190
+ description: Expert code reviewer focusing on best practices, security, and maintainability
173
191
  ---
174
192
 
175
193
  # Example Chat Mode
@@ -221,6 +239,23 @@ Describe the context where this steering file applies.
221
239
 
222
240
  Provide examples of correct patterns.
223
241
  `,
242
+ '.kiro/hooks/example-hook.kiro.hook': `{
243
+ "enabled": false,
244
+ "name": "Example Hook",
245
+ "description": "Example Kiro hook - disabled by default. Replace with your actual hook logic.",
246
+ "version": "1",
247
+ "when": {
248
+ "type": "fileEdited",
249
+ "patterns": [
250
+ "**/*.ts",
251
+ "**/*.tsx"
252
+ ]
253
+ },
254
+ "then": {
255
+ "type": "askAgent",
256
+ "prompt": "A file has been modified. Please review it for best practices:\\n1. Check for code quality issues\\n2. Verify error handling\\n3. Suggest improvements\\n4. Ensure tests are updated"
257
+ }
258
+ }`,
224
259
  },
225
260
  'agents.md': {
226
261
  'agents.md': `# Project Coding Guidelines
@@ -37,6 +37,7 @@ var __importStar = (this && this.__importStar) || (function () {
37
37
  })();
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
39
  exports.handleInstall = handleInstall;
40
+ exports.installFromLockfile = installFromLockfile;
40
41
  exports.createInstallCommand = createInstallCommand;
41
42
  const commander_1 = require("commander");
42
43
  const registry_client_1 = require("@pr-pm/registry-client");
@@ -61,6 +62,7 @@ function getPackageIcon(format, subtype) {
61
62
  'collection': 'šŸ“¦',
62
63
  'chatmode': 'šŸ’¬',
63
64
  'tool': 'šŸ”§',
65
+ 'hook': 'šŸŖ',
64
66
  };
65
67
  // Format-specific icons for rules/defaults
66
68
  const formatIcons = {
@@ -100,6 +102,7 @@ function getPackageLabel(format, subtype) {
100
102
  'collection': 'Collection',
101
103
  'chatmode': 'Chat Mode',
102
104
  'tool': 'Tool',
105
+ 'hook': 'Hook',
103
106
  };
104
107
  const formatLabel = formatLabels[format];
105
108
  const subtypeLabel = subtypeLabels[subtype];
@@ -159,8 +162,8 @@ async function handleInstall(packageSpec, options) {
159
162
  // Normal mode - use specified version or locked version or latest
160
163
  version = options.version || specVersion || lockedVersion || 'latest';
161
164
  }
162
- // Check if package is already installed
163
- if (lockfile && lockfile.packages[packageId]) {
165
+ // Check if package is already installed (skip if --force option is set)
166
+ if (!options.force && lockfile && lockfile.packages[packageId]) {
164
167
  const installedPkg = lockfile.packages[packageId];
165
168
  const requestedVersion = options.version || specVersion;
166
169
  // If no specific version requested, or same version requested
@@ -301,6 +304,7 @@ async function handleInstall(packageSpec, options) {
301
304
  const packageName = (0, filesystem_1.stripAuthorNamespace)(packageId);
302
305
  // For Claude skills, use SKILL.md filename in the package directory
303
306
  // For agents.md, use package-name/AGENTS.md directory structure
307
+ // For Copilot, use official naming conventions
304
308
  // For other formats, use package name as filename
305
309
  if (effectiveFormat === 'claude' && effectiveSubtype === 'skill') {
306
310
  destPath = `${destDir}/SKILL.md`;
@@ -308,6 +312,21 @@ async function handleInstall(packageSpec, options) {
308
312
  else if (effectiveFormat === 'agents.md') {
309
313
  destPath = `${destDir}/${packageName}/AGENTS.md`;
310
314
  }
315
+ else if (effectiveFormat === 'copilot') {
316
+ // Official GitHub Copilot naming conventions
317
+ if (effectiveSubtype === 'chatmode') {
318
+ // Chat modes: .github/chatmodes/NAME.chatmode.md
319
+ destPath = `${destDir}/${packageName}.chatmode.md`;
320
+ }
321
+ else {
322
+ // Path-specific instructions: .github/instructions/NAME.instructions.md
323
+ destPath = `${destDir}/${packageName}.instructions.md`;
324
+ }
325
+ }
326
+ else if (effectiveFormat === 'kiro' && effectiveSubtype === 'hook') {
327
+ // Kiro hooks use .kiro.hook extension (JSON files)
328
+ destPath = `${destDir}/${packageName}.kiro.hook`;
329
+ }
311
330
  else {
312
331
  destPath = `${destDir}/${packageName}.${fileExtension}`;
313
332
  }
@@ -337,10 +356,14 @@ async function handleInstall(packageSpec, options) {
337
356
  const destDir = (0, filesystem_1.getDestinationDir)(effectiveFormat, effectiveSubtype, pkg.name);
338
357
  // Multi-file package - create directory for package
339
358
  // For Claude skills, destDir already includes package name, so use it directly
359
+ // For Cursor rules converted from Claude skills, use flat structure
340
360
  const packageName = (0, filesystem_1.stripAuthorNamespace)(packageId);
361
+ const isCursorConversion = (effectiveFormat === 'cursor' && pkg.format === 'claude' && pkg.subtype === 'skill');
341
362
  const packageDir = (effectiveFormat === 'claude' && effectiveSubtype === 'skill')
342
363
  ? destDir
343
- : `${destDir}/${packageName}`;
364
+ : isCursorConversion
365
+ ? destDir // Cursor uses flat structure
366
+ : `${destDir}/${packageName}`;
344
367
  destPath = packageDir;
345
368
  console.log(` šŸ“ Multi-file package - creating directory: ${packageDir}`);
346
369
  // For Claude skills, verify SKILL.md exists
@@ -366,6 +389,8 @@ async function handleInstall(packageSpec, options) {
366
389
  }
367
390
  }
368
391
  }
392
+ // Track JSON files for @reference insertion in Cursor conversion
393
+ const jsonFiles = [];
369
394
  for (const file of extractedFiles) {
370
395
  // Strip the tarball's root directory prefix to preserve subdirectories
371
396
  // Example: ".claude/skills/agent-builder/docs/examples.md" → "docs/examples.md"
@@ -385,10 +410,58 @@ async function handleInstall(packageSpec, options) {
385
410
  // Fallback: just take the filename (last part)
386
411
  relativeFileName = pathParts[pathParts.length - 1];
387
412
  }
388
- const filePath = `${packageDir}/${relativeFileName}`;
389
- await (0, filesystem_1.saveFile)(filePath, file.content);
413
+ let fileContent = file.content;
414
+ let fileName = relativeFileName;
415
+ // Handle Cursor conversion from Claude skill
416
+ if (isCursorConversion) {
417
+ // Convert SKILL.md to .mdc
418
+ if (fileName === 'SKILL.md' || fileName.endsWith('/SKILL.md')) {
419
+ fileName = `${packageName}.mdc`;
420
+ // Add MDC header if missing
421
+ if (!(0, cursor_config_1.hasMDCHeader)(fileContent)) {
422
+ console.log(` āš ļø Adding MDC header to converted skill...`);
423
+ fileContent = (0, cursor_config_1.addMDCHeader)(fileContent, pkg.description);
424
+ }
425
+ // Apply cursor config if available
426
+ if (config.cursor) {
427
+ console.log(` āš™ļø Applying cursor config...`);
428
+ fileContent = (0, cursor_config_1.applyCursorConfig)(fileContent, config.cursor);
429
+ }
430
+ }
431
+ // Track JSON files for @reference
432
+ else if (fileName.endsWith('.json')) {
433
+ // Flatten structure - remove subdirectories
434
+ const jsonFileName = fileName.split('/').pop() || fileName;
435
+ fileName = jsonFileName;
436
+ jsonFiles.push(jsonFileName);
437
+ }
438
+ // For other files (docs, etc), flatten the structure
439
+ else {
440
+ fileName = fileName.split('/').pop() || fileName;
441
+ }
442
+ }
443
+ const filePath = `${packageDir}/${fileName}`;
444
+ await (0, filesystem_1.saveFile)(filePath, fileContent);
390
445
  fileCount++;
391
446
  }
447
+ // Add @references to .mdc file for JSON files
448
+ if (isCursorConversion && jsonFiles.length > 0) {
449
+ const mdcFile = `${packageDir}/${packageName}.mdc`;
450
+ const { readFile } = await Promise.resolve().then(() => __importStar(require('fs/promises')));
451
+ let mdcContent = await readFile(mdcFile, 'utf-8');
452
+ // Find the end of frontmatter (if exists)
453
+ const frontmatterMatch = mdcContent.match(/^---\n[\s\S]*?\n---\n/);
454
+ if (frontmatterMatch) {
455
+ const frontmatterEnd = frontmatterMatch[0].length;
456
+ const beforeFrontmatter = mdcContent.slice(0, frontmatterEnd);
457
+ const afterFrontmatter = mdcContent.slice(frontmatterEnd);
458
+ // Add @references right after frontmatter
459
+ const references = jsonFiles.map(f => `@${f}`).join('\n');
460
+ mdcContent = `${beforeFrontmatter}\n${references}\n${afterFrontmatter}`;
461
+ await (0, filesystem_1.saveFile)(mdcFile, mdcContent);
462
+ console.log(` āœ“ Added ${jsonFiles.length} @reference(s) to ${packageName}.mdc`);
463
+ }
464
+ }
392
465
  }
393
466
  // Update or create lock file
394
467
  const updatedLockfile = lockfile || (0, lockfile_1.createLockfile)();
@@ -434,7 +507,7 @@ async function handleInstall(packageSpec, options) {
434
507
  error,
435
508
  duration: Date.now() - startTime,
436
509
  data: {
437
- packageId: packageSpec.split('@')[0],
510
+ packageId: packageSpec ? packageSpec.split('@')[0] : 'lockfile',
438
511
  version: options.version || 'latest',
439
512
  convertTo: options.as,
440
513
  },
@@ -530,11 +603,65 @@ function detectProjectFormat() {
530
603
  return 'windsurf';
531
604
  return null;
532
605
  }
606
+ /**
607
+ * Install all packages from prpm.lock
608
+ */
609
+ async function installFromLockfile(options) {
610
+ try {
611
+ // Read lockfile
612
+ const lockfile = await (0, lockfile_1.readLockfile)();
613
+ if (!lockfile) {
614
+ console.error('āŒ No prpm.lock file found');
615
+ console.log('\nšŸ’” Run "prpm install <package>" first to create a lockfile, or initialize a new project with "prpm init"');
616
+ process.exit(1);
617
+ }
618
+ const packageIds = Object.keys(lockfile.packages);
619
+ if (packageIds.length === 0) {
620
+ console.log('āœ… No packages to install (prpm.lock is empty)');
621
+ return;
622
+ }
623
+ console.log(`šŸ“¦ Installing ${packageIds.length} package${packageIds.length === 1 ? '' : 's'} from prpm.lock...\n`);
624
+ let successCount = 0;
625
+ let failCount = 0;
626
+ // Install each package from lockfile
627
+ for (const packageId of packageIds) {
628
+ const lockEntry = lockfile.packages[packageId];
629
+ try {
630
+ // Extract package spec (strip version if present in packageId)
631
+ const packageSpec = packageId.includes('@') && !packageId.startsWith('@')
632
+ ? packageId.substring(0, packageId.lastIndexOf('@'))
633
+ : packageId;
634
+ console.log(` Installing ${packageId}...`);
635
+ await handleInstall(packageSpec, {
636
+ version: lockEntry.version,
637
+ as: options.as || lockEntry.format,
638
+ subtype: options.subtype || lockEntry.subtype,
639
+ frozenLockfile: options.frozenLockfile,
640
+ force: true, // Force reinstall when installing from lockfile
641
+ });
642
+ successCount++;
643
+ }
644
+ catch (error) {
645
+ failCount++;
646
+ console.error(` āŒ Failed to install ${packageId}: ${error}`);
647
+ }
648
+ }
649
+ console.log(`\nāœ… Installed ${successCount}/${packageIds.length} packages`);
650
+ if (failCount > 0) {
651
+ console.error(`āŒ ${failCount} package${failCount === 1 ? '' : 's'} failed to install`);
652
+ process.exit(1);
653
+ }
654
+ }
655
+ catch (error) {
656
+ console.error(`āŒ Failed to install from lockfile: ${error}`);
657
+ process.exit(1);
658
+ }
659
+ }
533
660
  function createInstallCommand() {
534
661
  const command = new commander_1.Command('install');
535
662
  command
536
- .description('Install a package from the registry')
537
- .argument('<package>', 'Package to install (e.g., react-rules or react-rules@1.2.0)')
663
+ .description('Install a package from the registry, or install all packages from prpm.lock if no package specified')
664
+ .argument('[package]', 'Package to install (e.g., react-rules or react-rules@1.2.0). If omitted, installs all packages from prpm.lock')
538
665
  .option('--version <version>', 'Specific version to install')
539
666
  .option('--as <format>', 'Convert and install in specific format (cursor, claude, continue, windsurf, copilot, kiro, agents.md, canonical)')
540
667
  .option('--format <format>', 'Alias for --as')
@@ -553,6 +680,16 @@ function createInstallCommand() {
553
680
  console.log(' prpm install my-package # Install in native format');
554
681
  process.exit(1);
555
682
  }
683
+ // If no package specified, install from lockfile
684
+ if (!packageSpec) {
685
+ await installFromLockfile({
686
+ as: convertTo,
687
+ subtype: options.subtype,
688
+ frozenLockfile: options.frozenLockfile
689
+ });
690
+ process.exit(0);
691
+ return;
692
+ }
556
693
  await handleInstall(packageSpec, {
557
694
  version: options.version,
558
695
  as: convertTo,
@@ -254,6 +254,28 @@ function normalizeFilePaths(files) {
254
254
  }
255
255
  });
256
256
  }
257
+ /**
258
+ * Predict what the scoped package name will be after publishing
259
+ * This matches the server-side logic in packages.ts
260
+ */
261
+ function predictScopedPackageName(manifestName, username, organization) {
262
+ const usernameLowercase = username.toLowerCase();
263
+ // If organization is specified, use @org-name/
264
+ if (organization) {
265
+ const orgNameLowercase = organization.toLowerCase();
266
+ const expectedPrefix = `@${orgNameLowercase}/`;
267
+ if (!manifestName.startsWith(expectedPrefix)) {
268
+ return `${expectedPrefix}${manifestName}`;
269
+ }
270
+ return manifestName;
271
+ }
272
+ // If package name doesn't already have a scope, add @username/
273
+ if (!manifestName.startsWith('@')) {
274
+ return `@${usernameLowercase}/${manifestName}`;
275
+ }
276
+ // Package already has a scope, return as-is
277
+ return manifestName;
278
+ }
257
279
  /**
258
280
  * Create tarball from current directory
259
281
  */
@@ -442,6 +464,7 @@ async function handlePublish(options) {
442
464
  console.log('');
443
465
  }
444
466
  let selectedOrgId;
467
+ let selectedOrgName;
445
468
  // Check if organization is specified in manifest
446
469
  if (manifest.organization && userInfo) {
447
470
  const orgFromManifest = userInfo.organizations?.find((org) => org.name === manifest.organization || org.id === manifest.organization);
@@ -454,9 +477,12 @@ async function handlePublish(options) {
454
477
  `Your role: ${orgFromManifest.role}. Required: owner, admin, or maintainer`);
455
478
  }
456
479
  selectedOrgId = orgFromManifest.id;
480
+ selectedOrgName = orgFromManifest.name;
457
481
  }
482
+ // Predict what the scoped package name will be
483
+ const scopedPackageName = predictScopedPackageName(manifest.name, userInfo?.username || config.username || 'unknown', selectedOrgName || manifest.organization);
458
484
  console.log(` Source: ${source}`);
459
- console.log(` Package: ${manifest.name}@${manifest.version}`);
485
+ console.log(` Package: ${scopedPackageName}@${manifest.version}`);
460
486
  console.log(` Format: ${manifest.format} | Subtype: ${manifest.subtype}`);
461
487
  console.log(` Description: ${manifest.description}`);
462
488
  console.log(` Access: ${manifest.private ? 'private' : 'public'}`);
@@ -480,7 +506,7 @@ async function handlePublish(options) {
480
506
  manifest.license_url = licenseInfo.url || undefined;
481
507
  }
482
508
  // Validate and warn about license (optional - will extract if present)
483
- (0, license_extractor_1.validateLicenseInfo)(licenseInfo, manifest.name);
509
+ (0, license_extractor_1.validateLicenseInfo)(licenseInfo, scopedPackageName);
484
510
  console.log('');
485
511
  // Extract content snippet
486
512
  console.log('šŸ“ Extracting content snippet...');
@@ -488,7 +514,7 @@ async function handlePublish(options) {
488
514
  if (snippet) {
489
515
  manifest.snippet = snippet;
490
516
  }
491
- (0, snippet_extractor_1.validateSnippet)(snippet, manifest.name);
517
+ (0, snippet_extractor_1.validateSnippet)(snippet, scopedPackageName);
492
518
  console.log('');
493
519
  // Create tarball
494
520
  console.log('šŸ“¦ Creating package tarball...');
@@ -509,7 +535,7 @@ async function handlePublish(options) {
509
535
  if (options.dryRun) {
510
536
  console.log('āœ… Dry run successful! Package is ready to publish.');
511
537
  publishedPackages.push({
512
- name: manifest.name,
538
+ name: scopedPackageName,
513
539
  version: manifest.version,
514
540
  url: ''
515
541
  });
@@ -537,7 +563,8 @@ async function handlePublish(options) {
537
563
  // Default to registry URL for unknown environments
538
564
  webappUrl = registryUrl;
539
565
  }
540
- const packageUrl = `${webappUrl}/packages/${encodeURIComponent(manifest.name)}`;
566
+ // Use the name returned from the API (which includes auto-prefixed scope)
567
+ const packageUrl = `${webappUrl}/packages/${encodeURIComponent(result.name)}`;
541
568
  console.log('');
542
569
  console.log('āœ… Package published successfully!');
543
570
  console.log('');
@@ -545,16 +572,20 @@ async function handlePublish(options) {
545
572
  console.log(` Install: prpm install ${result.name}`);
546
573
  console.log('');
547
574
  publishedPackages.push({
548
- name: manifest.name,
575
+ name: result.name, // Use scoped name from server
549
576
  version: result.version,
550
577
  url: packageUrl
551
578
  });
552
579
  }
553
580
  catch (err) {
554
581
  const pkgError = err instanceof Error ? err.message : String(err);
555
- console.error(`\nāŒ Failed to publish ${manifest.name}: ${pkgError}\n`);
582
+ // Try to use scoped name if we have user info, otherwise fall back to manifest name
583
+ const displayName = userInfo
584
+ ? predictScopedPackageName(manifest.name, userInfo.username, manifest.organization)
585
+ : manifest.name;
586
+ console.error(`\nāŒ Failed to publish ${displayName}: ${pkgError}\n`);
556
587
  failedPackages.push({
557
- name: manifest.name,
588
+ name: displayName,
558
589
  error: pkgError
559
590
  });
560
591
  }
@@ -57,6 +57,7 @@ function getPackageIcon(format, subtype) {
57
57
  'collection': 'šŸ“¦',
58
58
  'chatmode': 'šŸ’¬',
59
59
  'tool': 'šŸ”§',
60
+ 'hook': 'šŸŖ',
60
61
  };
61
62
  // Format-specific icons for rules/defaults
62
63
  const formatIcons = {
@@ -96,6 +97,7 @@ function getPackageLabel(format, subtype) {
96
97
  'collection': 'Collection',
97
98
  'chatmode': 'Chat Mode',
98
99
  'tool': 'Tool',
100
+ 'hook': 'Hook',
99
101
  };
100
102
  const formatLabel = formatLabels[format];
101
103
  const subtypeLabel = subtypeLabels[subtype];
@@ -404,7 +406,7 @@ function createSearchCommand() {
404
406
  .description('Search for packages in the registry')
405
407
  .argument('[query]', 'Search query (optional when using --format/--subtype or --author)')
406
408
  .option('--format <format>', 'Filter by package format (cursor, claude, continue, windsurf, copilot, kiro, agents.md, generic, mcp)')
407
- .option('--subtype <subtype>', 'Filter by package subtype (rule, agent, skill, slash-command, prompt, workflow, tool, template, collection)')
409
+ .option('--subtype <subtype>', 'Filter by package subtype (rule, agent, skill, slash-command, prompt, workflow, tool, template, collection, chatmode, hook)')
408
410
  .option('--author <username>', 'Filter by author username')
409
411
  .option('--language <language>', 'Filter by programming language (javascript, typescript, python, etc.)')
410
412
  .option('--framework <framework>', 'Filter by framework (react, nextjs, django, etc.)')
@@ -54,8 +54,20 @@ function getDestinationDir(format, subtype, name) {
54
54
  case 'windsurf':
55
55
  return '.windsurf/rules';
56
56
  case 'copilot':
57
+ // Copilot has different locations based on subtype:
58
+ // - Repository-wide instructions: .github/copilot-instructions.md
59
+ // - Path-specific instructions: .github/instructions/*.instructions.md
60
+ // - Chat modes: .github/chatmodes/*.chatmode.md
61
+ if (subtype === 'chatmode')
62
+ return '.github/chatmodes';
63
+ // Default to path-specific instructions directory
57
64
  return '.github/instructions';
58
65
  case 'kiro':
66
+ // Kiro has different locations based on subtype:
67
+ // - Steering files: .kiro/steering/*.md
68
+ // - Hooks: .kiro/hooks/*.kiro.hook (JSON files)
69
+ if (subtype === 'hook')
70
+ return '.kiro/hooks';
59
71
  return '.kiro/steering';
60
72
  case 'agents.md':
61
73
  return '.agents';
package/dist/types.js CHANGED
@@ -32,4 +32,5 @@ exports.SUBTYPES = [
32
32
  'collection',
33
33
  'chatmode',
34
34
  'tool',
35
+ 'hook',
35
36
  ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prpm",
3
- "version": "0.1.8",
3
+ "version": "0.1.10",
4
4
  "description": "Prompt Package Manager CLI - Install and manage prompt-based files",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -45,8 +45,8 @@
45
45
  "license": "MIT",
46
46
  "dependencies": {
47
47
  "@octokit/rest": "^22.0.0",
48
- "@pr-pm/registry-client": "^1.3.6",
49
- "@pr-pm/types": "^0.2.7",
48
+ "@pr-pm/registry-client": "^1.3.8",
49
+ "@pr-pm/types": "^0.2.9",
50
50
  "ajv": "^8.17.1",
51
51
  "ajv-formats": "^3.0.1",
52
52
  "commander": "^11.1.0",