ccconfig 1.4.3 → 1.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.
- package/ccconfig.js +113 -53
- package/package.json +1 -1
package/ccconfig.js
CHANGED
|
@@ -90,7 +90,7 @@ function ensureProfileAvailable(
|
|
|
90
90
|
// All supported commands
|
|
91
91
|
const COMMANDS = [
|
|
92
92
|
'list', 'ls', 'add', 'update', 'use', 'start', 'safe-start', 'remove', 'rm',
|
|
93
|
-
'current', 'mode', 'env', '
|
|
93
|
+
'current', 'mode', 'env', 'completion'
|
|
94
94
|
];
|
|
95
95
|
|
|
96
96
|
// ccconfig markers for shell config files
|
|
@@ -688,9 +688,8 @@ async function add(name) {
|
|
|
688
688
|
if (profilesMap[name]) {
|
|
689
689
|
console.error(`Error: Configuration '${name}' already exists`);
|
|
690
690
|
console.error('');
|
|
691
|
-
console.error('To modify this configuration, use
|
|
692
|
-
console.error(` ccconfig update ${name}
|
|
693
|
-
console.error(` ccconfig edit # Manual edit`);
|
|
691
|
+
console.error('To modify this configuration, use:');
|
|
692
|
+
console.error(` ccconfig update ${name}`);
|
|
694
693
|
process.exit(1);
|
|
695
694
|
}
|
|
696
695
|
|
|
@@ -704,18 +703,60 @@ async function add(name) {
|
|
|
704
703
|
|
|
705
704
|
console.log(`✓ Configuration '${name}' added`);
|
|
706
705
|
console.log('');
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
706
|
+
|
|
707
|
+
// Check if claude binary exists before offering to start
|
|
708
|
+
let claudeAvailable = false;
|
|
709
|
+
try {
|
|
710
|
+
const command =
|
|
711
|
+
process.platform === 'win32' ? 'where claude' : 'which claude';
|
|
712
|
+
execSync(command, {stdio: 'pipe'});
|
|
713
|
+
claudeAvailable = true;
|
|
714
|
+
} catch (err) {
|
|
715
|
+
// Claude not found, don't offer to start
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
// Ask if user wants to start Claude Code with this profile immediately
|
|
719
|
+
const shouldStart = claudeAvailable ?
|
|
720
|
+
await helper.ask(`Start Claude Code with ${name} now? (yes/no)`, 'no') :
|
|
721
|
+
'no';
|
|
722
|
+
const normalized = shouldStart.trim().toLowerCase();
|
|
723
|
+
|
|
712
724
|
console.log('');
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
725
|
+
|
|
726
|
+
// Create auto-execute output manager (RAII-style)
|
|
727
|
+
const output = (() => {
|
|
728
|
+
let executed = false;
|
|
729
|
+
return {
|
|
730
|
+
execute: () => {
|
|
731
|
+
if (!executed) {
|
|
732
|
+
console.log('');
|
|
733
|
+
console.log(`Configuration '${name}' summary:`);
|
|
734
|
+
console.log('');
|
|
735
|
+
console.log('Saved environment variables:');
|
|
736
|
+
displayEnvVars(envVars);
|
|
737
|
+
console.log('');
|
|
738
|
+
console.log(`To start Claude Code with this configuration:`);
|
|
739
|
+
console.log(` ccconfig start ${name}`);
|
|
740
|
+
console.log('');
|
|
741
|
+
console.log('To update this configuration:');
|
|
742
|
+
console.log(` ccconfig update ${name}`);
|
|
743
|
+
console.log('');
|
|
744
|
+
console.log('Configuration saved to:');
|
|
745
|
+
console.log(` ${PROFILES_FILE}`);
|
|
746
|
+
executed = true;
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
};
|
|
750
|
+
})();
|
|
751
|
+
|
|
752
|
+
// Attempt to start Claude (if user chose yes), deferring output to exit
|
|
753
|
+
const shouldStartClaude = normalized === 'yes' || normalized === 'y';
|
|
754
|
+
if (shouldStartClaude) {
|
|
755
|
+
start(name, [], {onExit: output.execute});
|
|
756
|
+
} else {
|
|
757
|
+
// If not starting Claude, show output immediately
|
|
758
|
+
output.execute();
|
|
759
|
+
}
|
|
719
760
|
} finally {
|
|
720
761
|
helper.close();
|
|
721
762
|
}
|
|
@@ -781,17 +822,20 @@ async function update(name) {
|
|
|
781
822
|
/**
|
|
782
823
|
* Remove configuration
|
|
783
824
|
*/
|
|
784
|
-
function remove(name) {
|
|
825
|
+
async function remove(name) {
|
|
785
826
|
if (!name) {
|
|
786
827
|
console.error('Error: Missing configuration name');
|
|
787
828
|
console.error('Usage: ccconfig remove <name>');
|
|
788
829
|
process.exit(1);
|
|
789
830
|
}
|
|
790
831
|
|
|
832
|
+
// Check if terminal is interactive before proceeding
|
|
833
|
+
requireInteractive('removing configurations');
|
|
834
|
+
|
|
791
835
|
// Validate configuration name
|
|
792
836
|
validateConfigName(name);
|
|
793
837
|
|
|
794
|
-
const {profiles} = ensureProfileAvailable(name, {
|
|
838
|
+
const {profile, profiles} = ensureProfileAvailable(name, {
|
|
795
839
|
allowEmptyEnv: true,
|
|
796
840
|
onEmptyProfiles: () => {
|
|
797
841
|
console.error('Error: Configuration file does not exist');
|
|
@@ -801,9 +845,45 @@ function remove(name) {
|
|
|
801
845
|
}
|
|
802
846
|
});
|
|
803
847
|
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
console.log(
|
|
848
|
+
// Display profile information before removal
|
|
849
|
+
console.log('');
|
|
850
|
+
console.log('WARNING: PERMANENT DELETION');
|
|
851
|
+
console.log('═══════════════════════════════════════════════════════════');
|
|
852
|
+
console.log('');
|
|
853
|
+
console.log(`Configuration to be removed: ${name}`);
|
|
854
|
+
console.log('');
|
|
855
|
+
console.log('Profile details:');
|
|
856
|
+
if (profile.env && Object.keys(profile.env).length > 0) {
|
|
857
|
+
displayEnvVars(profile.env, true, ' ');
|
|
858
|
+
} else {
|
|
859
|
+
console.log(' (no environment variables configured)');
|
|
860
|
+
}
|
|
861
|
+
console.log('');
|
|
862
|
+
console.log('This action CANNOT be undone!');
|
|
863
|
+
console.log('All configuration data for this profile will be \x1b[1mpermanently deleted\x1b[0m.');
|
|
864
|
+
console.log('');
|
|
865
|
+
|
|
866
|
+
// Ask for confirmation
|
|
867
|
+
const helper = new ReadlineHelper();
|
|
868
|
+
try {
|
|
869
|
+
const confirmation = await helper.ask(
|
|
870
|
+
`Are you sure you want to remove '${name}'? (yes/no)`, 'no');
|
|
871
|
+
const normalized = confirmation.trim().toLowerCase();
|
|
872
|
+
|
|
873
|
+
if (normalized !== 'yes' && normalized !== 'y') {
|
|
874
|
+
console.log('');
|
|
875
|
+
console.log('Operation cancelled.');
|
|
876
|
+
return;
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
// Proceed with removal
|
|
880
|
+
delete getProfilesMap(profiles)[name];
|
|
881
|
+
saveProfiles(profiles);
|
|
882
|
+
console.log('');
|
|
883
|
+
console.log(`✓ Configuration '${name}' removed`);
|
|
884
|
+
} finally {
|
|
885
|
+
helper.close();
|
|
886
|
+
}
|
|
807
887
|
}
|
|
808
888
|
|
|
809
889
|
/**
|
|
@@ -1262,25 +1342,6 @@ function current(showSecret = false) {
|
|
|
1262
1342
|
console.log('═══════════════════════════════════════════');
|
|
1263
1343
|
}
|
|
1264
1344
|
|
|
1265
|
-
/**
|
|
1266
|
-
* Show configuration file path
|
|
1267
|
-
*/
|
|
1268
|
-
function edit() {
|
|
1269
|
-
if (!fs.existsSync(PROFILES_FILE)) {
|
|
1270
|
-
console.error('Error: Configuration file does not exist');
|
|
1271
|
-
console.error('Please add a configuration first: ccconfig add <name>');
|
|
1272
|
-
process.exit(1);
|
|
1273
|
-
}
|
|
1274
|
-
|
|
1275
|
-
const editor = process.env.EDITOR || process.env.VISUAL || 'vim';
|
|
1276
|
-
|
|
1277
|
-
console.log('Configuration file path:');
|
|
1278
|
-
console.log(` ${PROFILES_FILE}`);
|
|
1279
|
-
console.log('');
|
|
1280
|
-
console.log('Open it with your preferred editor, for example:');
|
|
1281
|
-
console.log(` ${editor} ${PROFILES_FILE}`);
|
|
1282
|
-
}
|
|
1283
|
-
|
|
1284
1345
|
/**
|
|
1285
1346
|
* Switch/view mode
|
|
1286
1347
|
*/
|
|
@@ -1376,9 +1437,10 @@ function env(format = 'bash') {
|
|
|
1376
1437
|
* @param {Array} extraArgs - Additional arguments to pass to Claude
|
|
1377
1438
|
* @param {Object} options - Options object
|
|
1378
1439
|
* @param {boolean} options.safe - Whether to run in safe mode (default: false)
|
|
1440
|
+
* @param {Function} options.onExit - Callback to execute before process exits
|
|
1379
1441
|
*/
|
|
1380
1442
|
function startClaude(name, extraArgs = [], options = {}) {
|
|
1381
|
-
const {safe = false} = options;
|
|
1443
|
+
const {safe = false, onExit = null} = options;
|
|
1382
1444
|
const commandName = safe ? 'safe-start' : 'start';
|
|
1383
1445
|
|
|
1384
1446
|
if (!name) {
|
|
@@ -1531,6 +1593,11 @@ function startClaude(name, extraArgs = [], options = {}) {
|
|
|
1531
1593
|
process.removeListener('SIGINT', signalHandler);
|
|
1532
1594
|
process.removeListener('SIGTERM', signalHandler);
|
|
1533
1595
|
|
|
1596
|
+
// Execute onExit callback before showing promotion message
|
|
1597
|
+
if (typeof onExit === 'function') {
|
|
1598
|
+
onExit();
|
|
1599
|
+
}
|
|
1600
|
+
|
|
1534
1601
|
// Show project promotion message on exit
|
|
1535
1602
|
console.log('');
|
|
1536
1603
|
console.log('──────────────────────────────────────────');
|
|
@@ -1566,16 +1633,16 @@ function startClaude(name, extraArgs = [], options = {}) {
|
|
|
1566
1633
|
/**
|
|
1567
1634
|
* Start Claude Code with specified profile (auto-approve mode)
|
|
1568
1635
|
*/
|
|
1569
|
-
function start(name, extraArgs = []) {
|
|
1570
|
-
return startClaude(name, extraArgs, {safe: false});
|
|
1636
|
+
function start(name, extraArgs = [], options = {}) {
|
|
1637
|
+
return startClaude(name, extraArgs, {safe: false, ...options});
|
|
1571
1638
|
}
|
|
1572
1639
|
|
|
1573
1640
|
/**
|
|
1574
1641
|
* Start Claude Code with specified profile (safe mode - requires permission
|
|
1575
1642
|
* confirmation)
|
|
1576
1643
|
*/
|
|
1577
|
-
function safeStart(name, extraArgs = []) {
|
|
1578
|
-
return startClaude(name, extraArgs, {safe: true});
|
|
1644
|
+
function safeStart(name, extraArgs = [], options = {}) {
|
|
1645
|
+
return startClaude(name, extraArgs, {safe: true, ...options});
|
|
1579
1646
|
}
|
|
1580
1647
|
|
|
1581
1648
|
/**
|
|
@@ -1663,7 +1730,6 @@ _ccconfig() {
|
|
|
1663
1730
|
'current:Display current configuration'
|
|
1664
1731
|
'mode:View or switch mode'
|
|
1665
1732
|
'env:Output environment variables'
|
|
1666
|
-
'edit:Show configuration file location'
|
|
1667
1733
|
)
|
|
1668
1734
|
|
|
1669
1735
|
modes=('settings' 'env')
|
|
@@ -1724,7 +1790,6 @@ complete -c ccconfig -f -n "__fish_use_subcommand" -a "rm" -d "Remove configurat
|
|
|
1724
1790
|
complete -c ccconfig -f -n "__fish_use_subcommand" -a "current" -d "Display current configuration"
|
|
1725
1791
|
complete -c ccconfig -f -n "__fish_use_subcommand" -a "mode" -d "View or switch mode"
|
|
1726
1792
|
complete -c ccconfig -f -n "__fish_use_subcommand" -a "env" -d "Output environment variables"
|
|
1727
|
-
complete -c ccconfig -f -n "__fish_use_subcommand" -a "edit" -d "Show configuration file location"
|
|
1728
1793
|
|
|
1729
1794
|
# Get profile names dynamically
|
|
1730
1795
|
function __ccconfig_profiles
|
|
@@ -1776,7 +1841,7 @@ function Get-CconfigProfiles {
|
|
|
1776
1841
|
Register-ArgumentCompleter -Native -CommandName ccconfig -ScriptBlock {
|
|
1777
1842
|
param($wordToComplete, $commandAst, $cursorPosition)
|
|
1778
1843
|
|
|
1779
|
-
$commands = @('list', 'ls', 'add', 'update', 'use', 'start', 'safe-start', 'remove', 'rm', 'current', 'mode', 'env', '
|
|
1844
|
+
$commands = @('list', 'ls', 'add', 'update', 'use', 'start', 'safe-start', 'remove', 'rm', 'current', 'mode', 'env', 'completion')
|
|
1780
1845
|
$modes = @('settings', 'env')
|
|
1781
1846
|
$formats = @('bash', 'zsh', 'fish', 'sh', 'powershell', 'pwsh', 'dotenv')
|
|
1782
1847
|
|
|
@@ -1889,8 +1954,6 @@ function help() {
|
|
|
1889
1954
|
' mode [settings|env] View or switch mode');
|
|
1890
1955
|
console.log(
|
|
1891
1956
|
' env [format] Output environment variables (env mode)');
|
|
1892
|
-
console.log(
|
|
1893
|
-
' edit Show configuration file location');
|
|
1894
1957
|
console.log(
|
|
1895
1958
|
' completion <bash|zsh|fish|pwsh> Generate shell completion script');
|
|
1896
1959
|
console.log('');
|
|
@@ -2001,7 +2064,7 @@ async function main() {
|
|
|
2001
2064
|
break;
|
|
2002
2065
|
case 'remove':
|
|
2003
2066
|
case 'rm':
|
|
2004
|
-
remove(filteredArgs[1]);
|
|
2067
|
+
await remove(filteredArgs[1]);
|
|
2005
2068
|
break;
|
|
2006
2069
|
case 'current':
|
|
2007
2070
|
current(showSecret);
|
|
@@ -2012,9 +2075,6 @@ async function main() {
|
|
|
2012
2075
|
case 'env':
|
|
2013
2076
|
env(filteredArgs[1] || 'bash');
|
|
2014
2077
|
break;
|
|
2015
|
-
case 'edit':
|
|
2016
|
-
edit();
|
|
2017
|
-
break;
|
|
2018
2078
|
case 'start':
|
|
2019
2079
|
if (!filteredArgs[1]) {
|
|
2020
2080
|
console.error('Error: Missing configuration name');
|