agentic-team-templates 0.4.2 → 0.5.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 (3) hide show
  1. package/README.md +30 -5
  2. package/package.json +1 -1
  3. package/src/index.js +308 -130
package/README.md CHANGED
@@ -7,12 +7,14 @@
7
7
 
8
8
  ![Cursor](https://img.shields.io/badge/Cursor_IDE-black?style=flat&logo=cursor)
9
9
  ![Claude Code](https://img.shields.io/badge/Claude_Code-cc785c?style=flat&logo=anthropic)
10
+ ![GitHub Copilot](https://img.shields.io/badge/GitHub_Copilot-000?style=flat&logo=githubcopilot)
10
11
 
11
- AI coding assistant templates for Cursor IDE and Claude Code. Pre-configured rules and guidelines that help AI assistants write better code in your projects.
12
+ AI coding assistant templates for Cursor IDE, Claude Code, and GitHub Copilot. Pre-configured rules and guidelines that help AI assistants write better code in your projects.
12
13
 
13
- **Installs:**
14
+ **Installs (configurable via `--ide`):**
14
15
  - **`CLAUDE.md`** - Development guide for Claude-based assistants (Claude Code, Cursor with Claude)
15
16
  - **`.cursorrules/`** - Rule files for Cursor IDE
17
+ - **`.github/copilot-instructions.md`** - Instructions for GitHub Copilot
16
18
 
17
19
  > **Disclaimer:** This project is provided for **educational and experimental purposes only**. The author takes no responsibility for any actions, outputs, or consequences resulting from an LLM or AI assistant following these rules. Use at your own risk. Always review AI-generated code before deploying to production.
18
20
 
@@ -73,14 +75,33 @@ Re-run with `@latest` to get updated templates:
73
75
  npx cursor-templates@latest web-frontend
74
76
  ```
75
77
 
78
+ ### Install for Specific IDE
79
+
80
+ By default, templates install for all supported IDEs (Cursor, Claude, Copilot). Use `--ide` to target specific tools:
81
+
82
+ ```bash
83
+ # Install only for Cursor IDE
84
+ npx cursor-templates web-frontend --ide=cursor
85
+
86
+ # Install only for Claude Code
87
+ npx cursor-templates web-frontend --ide=claude
88
+
89
+ # Install only for GitHub Copilot
90
+ npx cursor-templates web-frontend --ide=codex
91
+
92
+ # Install for multiple IDEs
93
+ npx cursor-templates web-frontend --ide=cursor --ide=codex
94
+ ```
95
+
76
96
  ### CLI Options
77
97
 
78
98
  | Option | Description |
79
99
  |--------|-------------|
100
+ | `--ide=<name>` | Target IDE: `cursor`, `claude`, or `codex` (can be used multiple times) |
80
101
  | `--list`, `-l` | List all available templates |
81
- | `--dry-run`, `-d` | Preview changes without writing files |
102
+ | `--dry-run` | Preview changes without writing files |
103
+ | `--force`, `-f` | Overwrite existing files |
82
104
  | `--help`, `-h` | Show help message |
83
- | `--version`, `-v` | Show version number |
84
105
 
85
106
  ## Available Templates
86
107
 
@@ -131,7 +152,10 @@ After running `npx cursor-templates web-frontend`:
131
152
  ```
132
153
  your-project/
133
154
  ├── CLAUDE.md # Development guide (Claude Code, Cursor)
134
- └── .cursorrules/ # Rule files (Cursor IDE)
155
+ ├── .cursorrules/ # Rule files (Cursor IDE)
156
+ │ └── ...
157
+ └── .github/
158
+ └── copilot-instructions.md # Instructions (GitHub Copilot)
135
159
  ├── core-principles.md # Shared
136
160
  ├── code-quality.md # Shared
137
161
  ├── security-fundamentals.md # Shared
@@ -206,6 +230,7 @@ npx cursor-templates ml-ai data-engineering
206
230
  - **Supported IDEs/Tools**:
207
231
  - Cursor IDE (any version with `.cursorrules/` support)
208
232
  - Claude Code (reads `CLAUDE.md` automatically)
233
+ - GitHub Copilot (reads `.github/copilot-instructions.md`)
209
234
 
210
235
  ## How to Contribute
211
236
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentic-team-templates",
3
- "version": "0.4.2",
3
+ "version": "0.5.0",
4
4
  "description": "AI coding assistant templates for Cursor IDE. Pre-configured rules and guidelines that help AI assistants write better code. - use at your own risk",
5
5
  "keywords": [
6
6
  "cursor",
package/src/index.js CHANGED
@@ -50,6 +50,10 @@ const SHARED_RULES = [
50
50
  'security-fundamentals.md'
51
51
  ];
52
52
 
53
+ // Supported IDEs/tools
54
+ const SUPPORTED_IDES = ['cursor', 'claude', 'codex'];
55
+ const DEFAULT_IDES = ['cursor', 'claude', 'codex']; // Default: install for all IDEs
56
+
53
57
  // Colors
54
58
  const colors = {
55
59
  red: (s) => `\x1b[31m${s}\x1b[0m`,
@@ -69,19 +73,27 @@ function printBanner() {
69
73
 
70
74
  function printHelp() {
71
75
  console.log(`${colors.yellow('Usage:')}
72
- npx cursor-templates <templates...>
76
+ npx cursor-templates <templates...> [options]
73
77
 
74
78
  ${colors.yellow('Options:')}
79
+ --ide=<name> Install for specific IDE (cursor, claude, codex)
80
+ Can be specified multiple times: --ide=cursor --ide=claude
81
+ Default: all (cursor, claude, codex)
75
82
  --list, -l List available templates
76
83
  --help, -h Show this help message
77
84
  --dry-run Show what would be installed
78
85
  --force, -f Overwrite existing files (default: skip)
79
86
 
87
+ ${colors.yellow('IDE Targets:')}
88
+ cursor .cursorrules/ directory (Cursor IDE)
89
+ claude CLAUDE.md file (Claude Code, Cursor with Claude)
90
+ codex .github/copilot-instructions.md (GitHub Copilot)
91
+
80
92
  ${colors.yellow('Examples:')}
81
93
  npx cursor-templates web-frontend
82
- npx cursor-templates web-frontend web-backend
83
- npx cursor-templates fullstack
84
- npx cursor-templates mobile utility-agent
94
+ npx cursor-templates web-frontend --ide=cursor
95
+ npx cursor-templates web-frontend --ide=claude --ide=codex
96
+ npx cursor-templates fullstack --ide=codex
85
97
  npx cursor-templates web-backend --force
86
98
 
87
99
  ${colors.dim('Shared rules (code-quality, security, git-workflow, etc.) are always included.')}
@@ -469,146 +481,291 @@ function generateClaudeMdToPath(targetDir, installedTemplates, destPath) {
469
481
  fs.writeFileSync(destPath, content);
470
482
  }
471
483
 
472
- function install(targetDir, templates, dryRun = false, force = false) {
473
- const cursorrules = path.join(targetDir, '.cursorrules');
474
-
475
- if (!dryRun && !fs.existsSync(cursorrules)) {
476
- fs.mkdirSync(cursorrules, { recursive: true });
477
- }
484
+ /**
485
+ * Generate content for GitHub Copilot instructions file
486
+ */
487
+ function generateCopilotInstructionsContent(installedTemplates) {
488
+ const templateList = installedTemplates
489
+ .map(t => `- ${t}: ${TEMPLATES[t].description}`)
490
+ .join('\n');
491
+
492
+ // Read and concatenate all shared rules
493
+ const sharedRulesContent = SHARED_RULES.map(rule => {
494
+ const rulePath = path.join(TEMPLATES_DIR, '_shared', rule);
495
+ try {
496
+ return fs.readFileSync(rulePath, 'utf8');
497
+ } catch {
498
+ return '';
499
+ }
500
+ }).filter(Boolean).join('\n\n---\n\n');
501
+
502
+ // Read and concatenate template-specific rules
503
+ const templateRulesContent = installedTemplates.map(template => {
504
+ return TEMPLATES[template].rules.map(rule => {
505
+ const rulePath = path.join(TEMPLATES_DIR, template, '.cursorrules', rule);
506
+ try {
507
+ return fs.readFileSync(rulePath, 'utf8');
508
+ } catch {
509
+ return '';
510
+ }
511
+ }).filter(Boolean).join('\n\n');
512
+ }).join('\n\n---\n\n');
513
+
514
+ return `# Copilot Instructions
515
+
516
+ This file provides coding guidelines for GitHub Copilot in this project.
517
+
518
+ ## Project Configuration
519
+
520
+ **Installed Templates:** ${installedTemplates.join(', ')}
521
+
522
+ ${templateList}
523
+
524
+ ---
525
+
526
+ ## Core Principles
527
+
528
+ ### Honesty Over Output
529
+ - If something doesn't work, say it doesn't work
530
+ - If you don't know, say you don't know
531
+ - Never hide errors or suppress warnings
532
+
533
+ ### Security First
534
+ - Zero trust: Every input is hostile until proven otherwise
535
+ - Validate and sanitize all inputs
536
+ - No secrets in code or logs
537
+
538
+ ### Tests Are Required
539
+ - No feature is complete without tests
540
+ - Test behavior, not implementation
541
+
542
+ ### Code Quality
543
+ - SOLID principles
544
+ - DRY (Don't Repeat Yourself)
545
+ - Explicit over implicit
546
+
547
+ ---
548
+
549
+ ## Shared Guidelines
550
+
551
+ ${sharedRulesContent}
552
+
553
+ ---
554
+
555
+ ## Template-Specific Guidelines
556
+
557
+ ${templateRulesContent}
558
+
559
+ ---
560
+
561
+ ## Definition of Done
562
+
563
+ A feature is complete when:
564
+ - [ ] Code written and reviewed
565
+ - [ ] Tests written and passing
566
+ - [ ] No linting errors
567
+ - [ ] Security reviewed
568
+ - [ ] Documentation updated
569
+ `;
570
+ }
571
+
572
+ function install(targetDir, templates, dryRun = false, force = false, ides = DEFAULT_IDES) {
573
+ const stats = { copied: 0, skipped: 0, updated: 0, renamed: 0 };
574
+ const renamedFiles = [];
575
+ const installedFor = [];
478
576
 
479
577
  console.log(`${colors.blue('Installing to:')} ${targetDir}`);
578
+ console.log(`${colors.blue('Target IDEs:')} ${ides.join(', ')}`);
480
579
  if (!force) {
481
580
  console.log(colors.dim('(identical files skipped, modified files preserved with ours saved as *-1.md)'));
482
- console.log(colors.dim('(CLAUDE.md: missing sections merged intelligently)'));
483
581
  }
484
582
  console.log();
485
583
 
486
- const stats = { copied: 0, skipped: 0, updated: 0, renamed: 0 };
487
- const renamedFiles = [];
488
-
489
- // 1. Install shared rules
490
- console.log(colors.green('► Installing shared rules...'));
491
- for (const rule of SHARED_RULES) {
492
- const src = path.join(TEMPLATES_DIR, '_shared', rule);
493
- const dest = path.join(cursorrules, rule);
584
+ // 1. Install .cursorrules/ for Cursor IDE
585
+ if (ides.includes('cursor')) {
586
+ installedFor.push('cursor');
587
+ const cursorrules = path.join(targetDir, '.cursorrules');
494
588
 
495
- if (dryRun) {
496
- const exists = fs.existsSync(dest);
497
- if (!exists) {
498
- console.log(` ${colors.dim('[copy]')} ${rule}`);
499
- } else if (force) {
500
- console.log(` ${colors.dim('[update]')} ${rule}`);
501
- } else if (filesMatch(src, dest)) {
502
- console.log(` ${colors.yellow('[skip]')} ${rule} (identical)`);
503
- } else {
504
- const altName = path.basename(getAlternateFilename(dest));
505
- console.log(` ${colors.blue('[rename]')} ${rule} → ${altName}`);
506
- }
507
- } else {
508
- const result = copyFile(src, dest, force);
509
- stats[result.status]++;
510
- if (result.status === 'skipped') {
511
- console.log(` ${colors.yellow('[skip]')} ${rule} (identical)`);
512
- } else if (result.status === 'renamed') {
513
- const altName = path.basename(result.destFile);
514
- renamedFiles.push({ original: rule, renamed: altName });
515
- console.log(` ${colors.blue('[rename]')} ${rule} → ${altName}`);
516
- } else {
517
- console.log(` ${colors.dim(`[${result.status}]`)} ${rule}`);
518
- }
589
+ if (!dryRun && !fs.existsSync(cursorrules)) {
590
+ fs.mkdirSync(cursorrules, { recursive: true });
519
591
  }
520
- }
521
- console.log();
522
592
 
523
- // 2. Install template-specific rules
524
- for (const template of templates) {
525
- console.log(colors.green(`► Installing ${template} template...`));
526
-
527
- for (const rule of TEMPLATES[template].rules) {
528
- const src = path.join(TEMPLATES_DIR, template, '.cursorrules', rule);
529
- const dest = path.join(cursorrules, `${template}-${rule}`);
530
- const destName = `${template}-${rule}`;
593
+ // Install shared rules
594
+ console.log(colors.green('► Installing shared rules (.cursorrules/)...'));
595
+ for (const rule of SHARED_RULES) {
596
+ const src = path.join(TEMPLATES_DIR, '_shared', rule);
597
+ const dest = path.join(cursorrules, rule);
531
598
 
532
599
  if (dryRun) {
533
600
  const exists = fs.existsSync(dest);
534
601
  if (!exists) {
535
- console.log(` ${colors.dim('[copy]')} ${destName}`);
602
+ console.log(` ${colors.dim('[copy]')} ${rule}`);
536
603
  } else if (force) {
537
- console.log(` ${colors.dim('[update]')} ${destName}`);
604
+ console.log(` ${colors.dim('[update]')} ${rule}`);
538
605
  } else if (filesMatch(src, dest)) {
539
- console.log(` ${colors.yellow('[skip]')} ${destName} (identical)`);
606
+ console.log(` ${colors.yellow('[skip]')} ${rule} (identical)`);
540
607
  } else {
541
608
  const altName = path.basename(getAlternateFilename(dest));
542
- console.log(` ${colors.blue('[rename]')} ${destName} → ${altName}`);
609
+ console.log(` ${colors.blue('[rename]')} ${rule} → ${altName}`);
543
610
  }
544
611
  } else {
545
612
  const result = copyFile(src, dest, force);
546
613
  stats[result.status]++;
547
614
  if (result.status === 'skipped') {
548
- console.log(` ${colors.yellow('[skip]')} ${destName} (identical)`);
615
+ console.log(` ${colors.yellow('[skip]')} ${rule} (identical)`);
549
616
  } else if (result.status === 'renamed') {
550
617
  const altName = path.basename(result.destFile);
551
- renamedFiles.push({ original: destName, renamed: altName });
552
- console.log(` ${colors.blue('[rename]')} ${destName} → ${altName}`);
618
+ renamedFiles.push({ original: rule, renamed: altName });
619
+ console.log(` ${colors.blue('[rename]')} ${rule} → ${altName}`);
553
620
  } else {
554
- console.log(` ${colors.dim(`[${result.status}]`)} ${destName}`);
621
+ console.log(` ${colors.dim(`[${result.status}]`)} ${rule}`);
555
622
  }
556
623
  }
557
624
  }
558
625
  console.log();
626
+
627
+ // Install template-specific rules
628
+ for (const template of templates) {
629
+ console.log(colors.green(`► Installing ${template} template (.cursorrules/)...`));
630
+
631
+ for (const rule of TEMPLATES[template].rules) {
632
+ const src = path.join(TEMPLATES_DIR, template, '.cursorrules', rule);
633
+ const dest = path.join(cursorrules, `${template}-${rule}`);
634
+ const destName = `${template}-${rule}`;
635
+
636
+ if (dryRun) {
637
+ const exists = fs.existsSync(dest);
638
+ if (!exists) {
639
+ console.log(` ${colors.dim('[copy]')} ${destName}`);
640
+ } else if (force) {
641
+ console.log(` ${colors.dim('[update]')} ${destName}`);
642
+ } else if (filesMatch(src, dest)) {
643
+ console.log(` ${colors.yellow('[skip]')} ${destName} (identical)`);
644
+ } else {
645
+ const altName = path.basename(getAlternateFilename(dest));
646
+ console.log(` ${colors.blue('[rename]')} ${destName} → ${altName}`);
647
+ }
648
+ } else {
649
+ const result = copyFile(src, dest, force);
650
+ stats[result.status]++;
651
+ if (result.status === 'skipped') {
652
+ console.log(` ${colors.yellow('[skip]')} ${destName} (identical)`);
653
+ } else if (result.status === 'renamed') {
654
+ const altName = path.basename(result.destFile);
655
+ renamedFiles.push({ original: destName, renamed: altName });
656
+ console.log(` ${colors.blue('[rename]')} ${destName} → ${altName}`);
657
+ } else {
658
+ console.log(` ${colors.dim(`[${result.status}]`)} ${destName}`);
659
+ }
660
+ }
661
+ }
662
+ console.log();
663
+ }
559
664
  }
560
665
 
561
- // 3. Generate CLAUDE.md
562
- const claudePath = path.join(targetDir, 'CLAUDE.md');
563
- const claudeExists = fs.existsSync(claudePath);
564
- const templateContent = generateClaudeMdContent(templates);
565
-
566
- console.log(colors.green('► Generating CLAUDE.md...'));
567
- if (dryRun) {
568
- if (!claudeExists) {
569
- console.log(` ${colors.dim('[copy]')} CLAUDE.md`);
666
+ // 2. Generate CLAUDE.md for Claude Code
667
+ if (ides.includes('claude')) {
668
+ installedFor.push('claude');
669
+ const claudePath = path.join(targetDir, 'CLAUDE.md');
670
+ const claudeExists = fs.existsSync(claudePath);
671
+ const templateContent = generateClaudeMdContent(templates);
672
+
673
+ console.log(colors.green('► Generating CLAUDE.md (Claude Code)...'));
674
+ if (dryRun) {
675
+ if (!claudeExists) {
676
+ console.log(` ${colors.dim('[copy]')} CLAUDE.md`);
677
+ } else if (force) {
678
+ console.log(` ${colors.dim('[update]')} CLAUDE.md`);
679
+ } else {
680
+ const existingContent = fs.readFileSync(claudePath, 'utf8');
681
+ const { missing } = findMissingSections(existingContent, templateContent);
682
+ if (missing.length === 0) {
683
+ console.log(` ${colors.yellow('[skip]')} CLAUDE.md (all sections present)`);
684
+ } else {
685
+ console.log(` ${colors.blue('[merge]')} CLAUDE.md (would add ${missing.length} section(s))`);
686
+ for (const section of missing) {
687
+ console.log(` ${colors.dim('+')} ${section.heading}`);
688
+ }
689
+ }
690
+ }
691
+ } else if (!claudeExists) {
692
+ fs.writeFileSync(claudePath, templateContent);
693
+ console.log(` ${colors.dim('[copied]')} CLAUDE.md`);
694
+ stats.copied++;
570
695
  } else if (force) {
571
- console.log(` ${colors.dim('[update]')} CLAUDE.md`);
696
+ fs.writeFileSync(claudePath, templateContent);
697
+ console.log(` ${colors.dim('[updated]')} CLAUDE.md`);
698
+ stats.updated++;
572
699
  } else {
573
- // Check what would be merged
574
700
  const existingContent = fs.readFileSync(claudePath, 'utf8');
575
- const { missing } = findMissingSections(existingContent, templateContent);
576
- if (missing.length === 0) {
701
+ const { merged, addedSections } = mergeClaudeContent(existingContent, templateContent);
702
+
703
+ if (addedSections.length === 0) {
577
704
  console.log(` ${colors.yellow('[skip]')} CLAUDE.md (all sections present)`);
705
+ stats.skipped++;
578
706
  } else {
579
- console.log(` ${colors.blue('[merge]')} CLAUDE.md (would add ${missing.length} section(s))`);
580
- for (const section of missing) {
581
- console.log(` ${colors.dim('+')} ${section.heading}`);
707
+ fs.writeFileSync(claudePath, merged);
708
+ console.log(` ${colors.blue('[merged]')} CLAUDE.md`);
709
+ console.log(` ${colors.green('Added sections:')}`);
710
+ for (const heading of addedSections) {
711
+ console.log(` ${colors.dim('+')} ${heading}`);
582
712
  }
713
+ stats.updated++;
583
714
  }
584
715
  }
585
- } else if (!claudeExists) {
586
- fs.writeFileSync(claudePath, templateContent);
587
- console.log(` ${colors.dim('[copied]')} CLAUDE.md`);
588
- stats.copied++;
589
- } else if (force) {
590
- fs.writeFileSync(claudePath, templateContent);
591
- console.log(` ${colors.dim('[updated]')} CLAUDE.md`);
592
- stats.updated++;
593
- } else {
594
- // Intelligent merge: append only missing sections
595
- const existingContent = fs.readFileSync(claudePath, 'utf8');
596
- const { merged, addedSections } = mergeClaudeContent(existingContent, templateContent);
716
+ console.log();
717
+ }
718
+
719
+ // 3. Generate .github/copilot-instructions.md for GitHub Copilot (Codex)
720
+ if (ides.includes('codex')) {
721
+ installedFor.push('codex');
722
+ const githubDir = path.join(targetDir, '.github');
723
+ const copilotPath = path.join(githubDir, 'copilot-instructions.md');
724
+ const copilotExists = fs.existsSync(copilotPath);
725
+ const copilotContent = generateCopilotInstructionsContent(templates);
726
+
727
+ if (!dryRun && !fs.existsSync(githubDir)) {
728
+ fs.mkdirSync(githubDir, { recursive: true });
729
+ }
597
730
 
598
- if (addedSections.length === 0) {
599
- console.log(` ${colors.yellow('[skip]')} CLAUDE.md (all sections present)`);
600
- stats.skipped++;
601
- } else {
602
- fs.writeFileSync(claudePath, merged);
603
- console.log(` ${colors.blue('[merged]')} CLAUDE.md`);
604
- console.log(` ${colors.green('Added sections:')}`);
605
- for (const heading of addedSections) {
606
- console.log(` ${colors.dim('+')} ${heading}`);
731
+ console.log(colors.green('► Generating .github/copilot-instructions.md (GitHub Copilot)...'));
732
+ if (dryRun) {
733
+ if (!copilotExists) {
734
+ console.log(` ${colors.dim('[copy]')} .github/copilot-instructions.md`);
735
+ } else if (force) {
736
+ console.log(` ${colors.dim('[update]')} .github/copilot-instructions.md`);
737
+ } else {
738
+ const existingContent = fs.readFileSync(copilotPath, 'utf8');
739
+ const { missing } = findMissingSections(existingContent, copilotContent);
740
+ if (missing.length === 0) {
741
+ console.log(` ${colors.yellow('[skip]')} .github/copilot-instructions.md (all sections present)`);
742
+ } else {
743
+ console.log(` ${colors.blue('[merge]')} .github/copilot-instructions.md (would add ${missing.length} section(s))`);
744
+ }
607
745
  }
746
+ } else if (!copilotExists) {
747
+ fs.writeFileSync(copilotPath, copilotContent);
748
+ console.log(` ${colors.dim('[copied]')} .github/copilot-instructions.md`);
749
+ stats.copied++;
750
+ } else if (force) {
751
+ fs.writeFileSync(copilotPath, copilotContent);
752
+ console.log(` ${colors.dim('[updated]')} .github/copilot-instructions.md`);
608
753
  stats.updated++;
754
+ } else {
755
+ const existingContent = fs.readFileSync(copilotPath, 'utf8');
756
+ const { merged, addedSections } = mergeClaudeContent(existingContent, copilotContent);
757
+
758
+ if (addedSections.length === 0) {
759
+ console.log(` ${colors.yellow('[skip]')} .github/copilot-instructions.md (all sections present)`);
760
+ stats.skipped++;
761
+ } else {
762
+ fs.writeFileSync(copilotPath, merged);
763
+ console.log(` ${colors.blue('[merged]')} .github/copilot-instructions.md`);
764
+ stats.updated++;
765
+ }
609
766
  }
767
+ console.log();
610
768
  }
611
- console.log();
612
769
 
613
770
  // Summary
614
771
  console.log(colors.green('════════════════════════════════════════════════════════════'));
@@ -627,7 +784,18 @@ function install(targetDir, templates, dryRun = false, force = false) {
627
784
  }
628
785
  console.log();
629
786
 
630
- console.log(colors.yellow('Templates installed:'));
787
+ console.log(colors.yellow('Installed for:'));
788
+ for (const ide of installedFor) {
789
+ const ideInfo = {
790
+ cursor: '.cursorrules/ (Cursor IDE)',
791
+ claude: 'CLAUDE.md (Claude Code)',
792
+ codex: '.github/copilot-instructions.md (GitHub Copilot)'
793
+ };
794
+ console.log(` - ${ideInfo[ide]}`);
795
+ }
796
+ console.log();
797
+
798
+ console.log(colors.yellow('Templates:'));
631
799
  console.log(' - _shared (always included)');
632
800
  for (const template of templates) {
633
801
  console.log(` - ${template}`);
@@ -645,45 +813,52 @@ function install(targetDir, templates, dryRun = false, force = false) {
645
813
  }
646
814
 
647
815
  console.log(colors.blue('Next steps:'));
648
- console.log(' 1. Review CLAUDE.md for any customization');
649
- console.log(' 2. Commit the new files to your repository');
816
+ if (installedFor.includes('claude')) {
817
+ console.log(' 1. Review CLAUDE.md for any customization');
818
+ }
819
+ if (installedFor.includes('codex')) {
820
+ console.log(' 2. Review .github/copilot-instructions.md');
821
+ }
822
+ console.log(' 3. Commit the new files to your repository');
650
823
  console.log();
651
824
  }
652
825
 
653
826
  export function run(args) {
654
827
  const templates = [];
828
+ const ides = [];
655
829
  let dryRun = false;
656
830
  let force = false;
657
831
 
658
832
  // Parse arguments
659
833
  for (const arg of args) {
660
- switch (arg) {
661
- case '--list':
662
- case '-l':
663
- printBanner();
664
- printTemplates();
665
- process.exit(0);
666
- break;
667
- case '--help':
668
- case '-h':
669
- printBanner();
670
- printHelp();
671
- process.exit(0);
672
- break;
673
- case '--dry-run':
674
- dryRun = true;
675
- break;
676
- case '--force':
677
- case '-f':
678
- force = true;
679
- break;
680
- default:
681
- if (arg.startsWith('-')) {
682
- console.error(colors.red(`Error: Unknown option '${arg}'`));
683
- printHelp();
684
- process.exit(1);
685
- }
686
- templates.push(arg);
834
+ if (arg === '--list' || arg === '-l') {
835
+ printBanner();
836
+ printTemplates();
837
+ process.exit(0);
838
+ } else if (arg === '--help' || arg === '-h') {
839
+ printBanner();
840
+ printHelp();
841
+ process.exit(0);
842
+ } else if (arg === '--dry-run') {
843
+ dryRun = true;
844
+ } else if (arg === '--force' || arg === '-f') {
845
+ force = true;
846
+ } else if (arg.startsWith('--ide=')) {
847
+ const ide = arg.slice(6).toLowerCase();
848
+ if (!SUPPORTED_IDES.includes(ide)) {
849
+ console.error(colors.red(`Error: Unknown IDE '${ide}'`));
850
+ console.error(colors.dim(`Supported: ${SUPPORTED_IDES.join(', ')}`));
851
+ process.exit(1);
852
+ }
853
+ if (!ides.includes(ide)) {
854
+ ides.push(ide);
855
+ }
856
+ } else if (arg.startsWith('-')) {
857
+ console.error(colors.red(`Error: Unknown option '${arg}'`));
858
+ printHelp();
859
+ process.exit(1);
860
+ } else {
861
+ templates.push(arg);
687
862
  }
688
863
  }
689
864
 
@@ -704,6 +879,9 @@ export function run(args) {
704
879
  }
705
880
  }
706
881
 
882
+ // Use default IDEs if none specified
883
+ const targetIdes = ides.length > 0 ? ides : DEFAULT_IDES;
884
+
707
885
  if (dryRun) {
708
886
  console.log(colors.yellow('DRY RUN - No changes will be made\n'));
709
887
  }
@@ -713,5 +891,5 @@ export function run(args) {
713
891
  }
714
892
 
715
893
  // Install to current directory
716
- install(process.cwd(), templates, dryRun, force);
894
+ install(process.cwd(), templates, dryRun, force, targetIdes);
717
895
  }