Skip to content

Commit f02232e

Browse files
davila7claude
andcommitted
🎯 Implement shared location selection for batch installations
- Ask installation locations ONCE at the beginning for all settings and hooks - Eliminate repeated prompts during batch installation - Add sharedInstallLocations parameter to individual functions - Use shared locations when provided, fall back to individual prompts otherwise - Show clear message about selected locations before installation begins Flow: 1. User runs: --setting=model/use-sonnet,telemetry/enable-telemetry 2. CLI asks ONCE: 'Where would you like to install settings and hooks?' 3. User selects locations (e.g., user, project, local) 4. CLI shows: 'Will install settings and hooks in: user, project, local' 5. All settings install to those same locations automatically 6. No additional prompts, CLI exits after completion Prevents the frustrating loop where each component shows its own installation menu, creating a better user experience for batch operations. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 903734f commit f02232e

File tree

1 file changed

+60
-10
lines changed

1 file changed

+60
-10
lines changed

cli-tool/src/index.js

Lines changed: 60 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -586,9 +586,9 @@ async function installIndividualSetting(settingName, targetDir, options) {
586586
delete settingConfig.description;
587587
}
588588

589-
// Ask user where to install the setting (unless in silent mode) - allow multiple locations
590-
let installLocations = ['local']; // default to local settings
591-
if (!options.silent) {
589+
// Use shared locations if provided (batch mode), otherwise ask user
590+
let installLocations = options.sharedInstallLocations || ['local']; // default to local settings
591+
if (!options.silent && !options.sharedInstallLocations) {
592592
const inquirer = require('inquirer');
593593
const { selectedLocations } = await inquirer.prompt([{
594594
type: 'checkbox',
@@ -848,9 +848,9 @@ async function installIndividualHook(hookName, targetDir, options) {
848848
delete hookConfig.description;
849849
}
850850

851-
// Ask user where to install the hook (unless in silent mode) - allow multiple locations
852-
let installLocations = ['local']; // default to local settings
853-
if (!options.silent) {
851+
// Use shared locations if provided (batch mode), otherwise ask user
852+
let installLocations = options.sharedInstallLocations || ['local']; // default to local settings
853+
if (!options.silent && !options.sharedInstallLocations) {
854854
const inquirer = require('inquirer');
855855
const { selectedLocations } = await inquirer.prompt([{
856856
type: 'checkbox',
@@ -1208,6 +1208,48 @@ async function installMultipleComponents(options, targetDir) {
12081208
console.log(chalk.gray(` Settings: ${components.settings.length}`));
12091209
console.log(chalk.gray(` Hooks: ${components.hooks.length}`));
12101210

1211+
// Ask for installation locations once for settings and hooks (if any exist and not in silent mode)
1212+
let sharedInstallLocations = ['local']; // default
1213+
const hasSettingsOrHooks = components.settings.length > 0 || components.hooks.length > 0;
1214+
1215+
if (hasSettingsOrHooks && !options.yes) {
1216+
console.log(chalk.blue('\n📍 Choose installation locations for settings and hooks:'));
1217+
const inquirer = require('inquirer');
1218+
const { selectedLocations } = await inquirer.prompt([{
1219+
type: 'checkbox',
1220+
name: 'selectedLocations',
1221+
message: 'Where would you like to install settings and hooks? (Select one or more)',
1222+
choices: [
1223+
{
1224+
name: '🏠 User settings (~/.claude/settings.json) - Applies to all projects',
1225+
value: 'user'
1226+
},
1227+
{
1228+
name: '📁 Project settings (.claude/settings.json) - Shared with team',
1229+
value: 'project'
1230+
},
1231+
{
1232+
name: '⚙️ Local settings (.claude/settings.local.json) - Personal, not committed',
1233+
value: 'local',
1234+
checked: true // Default selection
1235+
},
1236+
{
1237+
name: '🏢 Enterprise managed settings - System-wide policy (requires admin)',
1238+
value: 'enterprise'
1239+
}
1240+
],
1241+
validate: function(answer) {
1242+
if (answer.length < 1) {
1243+
return 'You must choose at least one installation location.';
1244+
}
1245+
return true;
1246+
}
1247+
}]);
1248+
1249+
sharedInstallLocations = selectedLocations;
1250+
console.log(chalk.cyan(`📋 Will install settings and hooks in: ${sharedInstallLocations.join(', ')}`));
1251+
}
1252+
12111253
// Install agents
12121254
for (const agent of components.agents) {
12131255
console.log(chalk.gray(` Installing agent: ${agent}`));
@@ -1226,16 +1268,24 @@ async function installMultipleComponents(options, targetDir) {
12261268
await installIndividualMCP(mcp, targetDir, { ...options, silent: true });
12271269
}
12281270

1229-
// Install settings (with interactive prompts for location unless --yes flag is used)
1271+
// Install settings (using shared installation locations)
12301272
for (const setting of components.settings) {
12311273
console.log(chalk.gray(` Installing setting: ${setting}`));
1232-
await installIndividualSetting(setting, targetDir, { ...options, silent: options.yes });
1274+
await installIndividualSetting(setting, targetDir, {
1275+
...options,
1276+
silent: true,
1277+
sharedInstallLocations: sharedInstallLocations
1278+
});
12331279
}
12341280

1235-
// Install hooks (with interactive prompts for location unless --yes flag is used)
1281+
// Install hooks (using shared installation locations)
12361282
for (const hook of components.hooks) {
12371283
console.log(chalk.gray(` Installing hook: ${hook}`));
1238-
await installIndividualHook(hook, targetDir, { ...options, silent: options.yes });
1284+
await installIndividualHook(hook, targetDir, {
1285+
...options,
1286+
silent: true,
1287+
sharedInstallLocations: sharedInstallLocations
1288+
});
12391289
}
12401290

12411291
// Handle YAML workflow if provided

0 commit comments

Comments
 (0)