claude-code-templates 1.17.1 → 1.18.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 (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.js +182 -18
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-code-templates",
3
- "version": "1.17.1",
3
+ "version": "1.18.0",
4
4
  "description": "CLI tool to setup Claude Code configurations with framework-specific commands, automation hooks and MCP Servers for your projects",
5
5
  "main": "src/index.js",
6
6
  "bin": {
package/src/index.js CHANGED
@@ -586,17 +586,99 @@ async function installIndividualSetting(settingName, targetDir, options) {
586
586
  delete settingConfig.description;
587
587
  }
588
588
 
589
- // Check if .claude/settings.json exists in target directory
589
+ // Ask user where to install the setting (unless in silent mode)
590
+ let settingsFile = 'settings.json'; // default
591
+ if (!options.silent) {
592
+ const inquirer = require('inquirer');
593
+ const { installLocation } = await inquirer.prompt([{
594
+ type: 'list',
595
+ name: 'installLocation',
596
+ message: 'Where would you like to install this setting?',
597
+ choices: [
598
+ {
599
+ name: '🏠 User settings (~/.claude/settings.json) - Applies to all projects',
600
+ value: 'user'
601
+ },
602
+ {
603
+ name: '📁 Project settings (.claude/settings.json) - Shared with team',
604
+ value: 'project'
605
+ },
606
+ {
607
+ name: '⚙️ Local settings (.claude/settings.local.json) - Personal, not committed',
608
+ value: 'local'
609
+ },
610
+ {
611
+ name: '🏢 Enterprise managed settings - System-wide policy (requires admin)',
612
+ value: 'enterprise'
613
+ }
614
+ ],
615
+ default: 'local'
616
+ }]);
617
+
618
+ if (installLocation === 'user') {
619
+ const os = require('os');
620
+ targetDir = os.homedir();
621
+ settingsFile = 'settings.json';
622
+ } else if (installLocation === 'project') {
623
+ settingsFile = 'settings.json';
624
+ } else if (installLocation === 'local') {
625
+ settingsFile = 'settings.local.json';
626
+ } else if (installLocation === 'enterprise') {
627
+ const os = require('os');
628
+ const platform = os.platform();
629
+
630
+ if (platform === 'darwin') {
631
+ // macOS
632
+ targetDir = '/Library/Application Support/ClaudeCode';
633
+ settingsFile = 'managed-settings.json';
634
+ } else if (platform === 'linux' || (process.platform === 'win32' && process.env.WSL_DISTRO_NAME)) {
635
+ // Linux and WSL
636
+ targetDir = '/etc/claude-code';
637
+ settingsFile = 'managed-settings.json';
638
+ } else if (platform === 'win32') {
639
+ // Windows
640
+ targetDir = 'C:\\ProgramData\\ClaudeCode';
641
+ settingsFile = 'managed-settings.json';
642
+ } else {
643
+ console.log(chalk.yellow('⚠️ Platform not supported for enterprise settings. Using user settings instead.'));
644
+ const os = require('os');
645
+ targetDir = os.homedir();
646
+ settingsFile = 'settings.json';
647
+ }
648
+
649
+ console.log(chalk.yellow(`⚠️ Enterprise settings require administrator privileges.`));
650
+ console.log(chalk.gray(`📍 Target path: ${path.join(targetDir, settingsFile)}`));
651
+ }
652
+ }
653
+
654
+ // Determine target directory and file based on selection
590
655
  const claudeDir = path.join(targetDir, '.claude');
591
- const targetSettingsFile = path.join(claudeDir, 'settings.json');
656
+ const targetSettingsFile = path.join(claudeDir, settingsFile);
592
657
  let existingConfig = {};
593
658
 
594
- // Ensure .claude directory exists
595
- await fs.ensureDir(claudeDir);
659
+ // For enterprise settings, create directory structure directly (not under .claude)
660
+ if (settingsFile === 'managed-settings.json') {
661
+ // Ensure enterprise directory exists (requires admin privileges)
662
+ try {
663
+ await fs.ensureDir(targetDir);
664
+ } catch (error) {
665
+ console.log(chalk.red(`❌ Failed to create enterprise directory: ${error.message}`));
666
+ console.log(chalk.yellow('💡 Try running with administrator privileges or choose a different installation location.'));
667
+ return;
668
+ }
669
+ } else {
670
+ // Ensure .claude directory exists for regular settings
671
+ await fs.ensureDir(claudeDir);
672
+ }
596
673
 
597
- if (await fs.pathExists(targetSettingsFile)) {
598
- existingConfig = await fs.readJson(targetSettingsFile);
599
- console.log(chalk.yellow('📝 Existing .claude/settings.json found, merging configurations...'));
674
+ // Read existing configuration
675
+ const actualTargetFile = settingsFile === 'managed-settings.json'
676
+ ? path.join(targetDir, settingsFile)
677
+ : targetSettingsFile;
678
+
679
+ if (await fs.pathExists(actualTargetFile)) {
680
+ existingConfig = await fs.readJson(actualTargetFile);
681
+ console.log(chalk.yellow(`📝 Existing ${settingsFile} found, merging configurations...`));
600
682
  }
601
683
 
602
684
  // Check for conflicts before merging
@@ -680,11 +762,11 @@ async function installIndividualSetting(settingName, targetDir, options) {
680
762
  }
681
763
 
682
764
  // Write the merged configuration
683
- await fs.writeJson(targetSettingsFile, mergedConfig, { spaces: 2 });
765
+ await fs.writeJson(actualTargetFile, mergedConfig, { spaces: 2 });
684
766
 
685
767
  if (!options.silent) {
686
768
  console.log(chalk.green(`✅ Setting "${settingName}" installed successfully!`));
687
- console.log(chalk.cyan(`📁 Configuration merged into: ${path.relative(targetDir, targetSettingsFile)}`));
769
+ console.log(chalk.cyan(`📁 Configuration merged into: ${actualTargetFile}`));
688
770
  console.log(chalk.cyan(`📦 Downloaded from: ${githubUrl}`));
689
771
  }
690
772
 
@@ -734,17 +816,99 @@ async function installIndividualHook(hookName, targetDir, options) {
734
816
  delete hookConfig.description;
735
817
  }
736
818
 
737
- // Check if .claude/settings.json exists in target directory (hooks go in settings.json)
819
+ // Ask user where to install the hook (unless in silent mode)
820
+ let settingsFile = 'settings.json'; // default
821
+ if (!options.silent) {
822
+ const inquirer = require('inquirer');
823
+ const { installLocation } = await inquirer.prompt([{
824
+ type: 'list',
825
+ name: 'installLocation',
826
+ message: 'Where would you like to install this hook?',
827
+ choices: [
828
+ {
829
+ name: '🏠 User settings (~/.claude/settings.json) - Applies to all projects',
830
+ value: 'user'
831
+ },
832
+ {
833
+ name: '📁 Project settings (.claude/settings.json) - Shared with team',
834
+ value: 'project'
835
+ },
836
+ {
837
+ name: '⚙️ Local settings (.claude/settings.local.json) - Personal, not committed',
838
+ value: 'local'
839
+ },
840
+ {
841
+ name: '🏢 Enterprise managed settings - System-wide policy (requires admin)',
842
+ value: 'enterprise'
843
+ }
844
+ ],
845
+ default: 'local'
846
+ }]);
847
+
848
+ if (installLocation === 'user') {
849
+ const os = require('os');
850
+ targetDir = os.homedir();
851
+ settingsFile = 'settings.json';
852
+ } else if (installLocation === 'project') {
853
+ settingsFile = 'settings.json';
854
+ } else if (installLocation === 'local') {
855
+ settingsFile = 'settings.local.json';
856
+ } else if (installLocation === 'enterprise') {
857
+ const os = require('os');
858
+ const platform = os.platform();
859
+
860
+ if (platform === 'darwin') {
861
+ // macOS
862
+ targetDir = '/Library/Application Support/ClaudeCode';
863
+ settingsFile = 'managed-settings.json';
864
+ } else if (platform === 'linux' || (process.platform === 'win32' && process.env.WSL_DISTRO_NAME)) {
865
+ // Linux and WSL
866
+ targetDir = '/etc/claude-code';
867
+ settingsFile = 'managed-settings.json';
868
+ } else if (platform === 'win32') {
869
+ // Windows
870
+ targetDir = 'C:\\ProgramData\\ClaudeCode';
871
+ settingsFile = 'managed-settings.json';
872
+ } else {
873
+ console.log(chalk.yellow('⚠️ Platform not supported for enterprise settings. Using user settings instead.'));
874
+ const os = require('os');
875
+ targetDir = os.homedir();
876
+ settingsFile = 'settings.json';
877
+ }
878
+
879
+ console.log(chalk.yellow(`⚠️ Enterprise settings require administrator privileges.`));
880
+ console.log(chalk.gray(`📍 Target path: ${path.join(targetDir, settingsFile)}`));
881
+ }
882
+ }
883
+
884
+ // Determine target directory and file based on selection
738
885
  const claudeDir = path.join(targetDir, '.claude');
739
- const targetSettingsFile = path.join(claudeDir, 'settings.json');
886
+ const targetSettingsFile = path.join(claudeDir, settingsFile);
740
887
  let existingConfig = {};
741
888
 
742
- // Ensure .claude directory exists
743
- await fs.ensureDir(claudeDir);
889
+ // For enterprise settings, create directory structure directly (not under .claude)
890
+ if (settingsFile === 'managed-settings.json') {
891
+ // Ensure enterprise directory exists (requires admin privileges)
892
+ try {
893
+ await fs.ensureDir(targetDir);
894
+ } catch (error) {
895
+ console.log(chalk.red(`❌ Failed to create enterprise directory: ${error.message}`));
896
+ console.log(chalk.yellow('💡 Try running with administrator privileges or choose a different installation location.'));
897
+ return;
898
+ }
899
+ } else {
900
+ // Ensure .claude directory exists for regular settings
901
+ await fs.ensureDir(claudeDir);
902
+ }
744
903
 
745
- if (await fs.pathExists(targetSettingsFile)) {
746
- existingConfig = await fs.readJson(targetSettingsFile);
747
- console.log(chalk.yellow('📝 Existing .claude/settings.json found, merging hook configurations...'));
904
+ // Read existing configuration
905
+ const actualTargetFile = settingsFile === 'managed-settings.json'
906
+ ? path.join(targetDir, settingsFile)
907
+ : targetSettingsFile;
908
+
909
+ if (await fs.pathExists(actualTargetFile)) {
910
+ existingConfig = await fs.readJson(actualTargetFile);
911
+ console.log(chalk.yellow(`📝 Existing ${settingsFile} found, merging hook configurations...`));
748
912
  }
749
913
 
750
914
  // Check for conflicts before merging (simplified for new array format)
@@ -823,11 +987,11 @@ async function installIndividualHook(hookName, targetDir, options) {
823
987
  }
824
988
 
825
989
  // Write the merged configuration
826
- await fs.writeJson(targetSettingsFile, mergedConfig, { spaces: 2 });
990
+ await fs.writeJson(actualTargetFile, mergedConfig, { spaces: 2 });
827
991
 
828
992
  if (!options.silent) {
829
993
  console.log(chalk.green(`✅ Hook "${hookName}" installed successfully!`));
830
- console.log(chalk.cyan(`📁 Configuration merged into: ${path.relative(targetDir, targetSettingsFile)}`));
994
+ console.log(chalk.cyan(`📁 Configuration merged into: ${actualTargetFile}`));
831
995
  console.log(chalk.cyan(`📦 Downloaded from: ${githubUrl}`));
832
996
  }
833
997