ccconfig 1.4.3 → 1.5.1

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/README.md CHANGED
@@ -264,6 +264,46 @@ Do you want to set ANTHROPIC_SMALL_FAST_MODEL? (y/N) [n]:
264
264
  - Use `ccconfig start work` to launch Claude Code with the updated profile
265
265
  - Or use `ccconfig use work` to activate it in current shell
266
266
 
267
+ ### Copy Configuration (fork)
268
+
269
+ If you need to create a new configuration based on an existing one, use the `fork` command:
270
+
271
+ ```bash
272
+ # Fork a configuration interactively
273
+ ccconfig fork work
274
+
275
+ # The tool will:
276
+ # 1. Ask for a new configuration name
277
+ # 2. Copy all environment variables from the source
278
+ # 3. Allow you to update values (press Enter to keep current value)
279
+ ```
280
+
281
+ **Example:**
282
+ ```bash
283
+ $ ccconfig fork work
284
+ Please enter source configuration name to copy from: work
285
+ Please enter new configuration name: work-dev
286
+ Creating configuration 'work-dev' from 'work'...
287
+ Press Enter to keep current value/default, or enter new value to update
288
+
289
+ ANTHROPIC_BASE_URL [https://api.company.com]: https://dev-api.company.com
290
+ ANTHROPIC_AUTH_TOKEN [sk-ant-api...]: <press Enter to keep>
291
+ ANTHROPIC_API_KEY [sk-...]: <press Enter to keep>
292
+ ANTHROPIC_MODEL [claude-sonnet-4-5-20250929]: <press Enter to keep>
293
+
294
+ ✓ Configuration 'work-dev' created from 'work'
295
+ Environment variables:
296
+ ANTHROPIC_BASE_URL=https://dev-api.company.com
297
+ ANTHROPIC_AUTH_TOKEN=sk-ant-api...
298
+ ANTHROPIC_API_KEY=sk-...
299
+ ANTHROPIC_MODEL=claude-sonnet-4-5-20250929
300
+
301
+ Run the following command to activate:
302
+ ccconfig use work-dev
303
+ ```
304
+
305
+ This is useful when you need similar configurations with slight variations (e.g., production vs development endpoints).
306
+
267
307
  ### Shell Completion
268
308
 
269
309
  ccconfig supports shell completion for commands, profile names, and options. This makes it easier to discover and use commands.
package/README_zh.md CHANGED
@@ -264,6 +264,46 @@ Do you want to set ANTHROPIC_SMALL_FAST_MODEL? (y/N) [n]:
264
264
  - 使用 `ccconfig start work` 以更新后的配置启动 Claude Code
265
265
  - 或使用 `ccconfig use work` 在当前 shell 中激活配置
266
266
 
267
+ ### 复制配置 (fork)
268
+
269
+ 如果您需要基于现有配置创建新配置,使用 `fork` 命令:
270
+
271
+ ```bash
272
+ # 交互式复制配置
273
+ ccconfig fork work
274
+
275
+ # 工具会:
276
+ # 1. 要求输入新配置名称
277
+ # 2. 从源配置复制所有环境变量
278
+ # 3. 允许您更新值(按 Enter 保持当前值)
279
+ ```
280
+
281
+ **示例:**
282
+ ```bash
283
+ $ ccconfig fork work
284
+ Please enter source configuration name to copy from: work
285
+ Please enter new configuration name: work-dev
286
+ Creating configuration 'work-dev' from 'work'...
287
+ Press Enter to keep current value/default, or enter new value to update
288
+
289
+ ANTHROPIC_BASE_URL [https://api.company.com]: https://dev-api.company.com
290
+ ANTHROPIC_AUTH_TOKEN [sk-ant-api...]: <按 Enter 保持不变>
291
+ ANTHROPIC_API_KEY [sk-...]: <按 Enter 保持不变>
292
+ ANTHROPIC_MODEL [claude-sonnet-4-5-20250929]: <按 Enter 保持不变>
293
+
294
+ ✓ Configuration 'work-dev' created from 'work'
295
+ Environment variables:
296
+ ANTHROPIC_BASE_URL=https://dev-api.company.com
297
+ ANTHROPIC_AUTH_TOKEN=sk-ant-api...
298
+ ANTHROPIC_API_KEY=sk-...
299
+ ANTHROPIC_MODEL=claude-sonnet-4-5-20250929
300
+
301
+ Run the following command to activate:
302
+ ccconfig use work-dev
303
+ ```
304
+
305
+ 当您需要相似配置但略有差异时很有用(例如生产环境与开发环境端点)。
306
+
267
307
  ### Shell 自动补全
268
308
 
269
309
  ccconfig 支持命令、配置名称和选项的 shell 自动补全,让您更容易发现和使用命令。
package/ccconfig.js CHANGED
@@ -89,8 +89,8 @@ function ensureProfileAvailable(
89
89
 
90
90
  // All supported commands
91
91
  const COMMANDS = [
92
- 'list', 'ls', 'add', 'update', 'use', 'start', 'safe-start', 'remove', 'rm',
93
- 'current', 'mode', 'env', 'edit', 'completion'
92
+ 'list', 'ls', 'add', 'update', 'fork', 'use', 'start', 'safe-start', 'remove', 'rm',
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 one of:');
692
- console.error(` ccconfig update ${name} # Interactive update`);
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
- console.log('Run the following command to activate:');
708
- console.log(` ccconfig use ${name}`);
709
- console.log('');
710
- console.log('Saved environment variables:');
711
- displayEnvVars(envVars);
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
- console.log('This information has been saved to:');
714
- console.log(` ${PROFILES_FILE}`);
715
- console.log(
716
- 'You can edit this file directly to further customize the profile:');
717
- console.log(` vim ${PROFILES_FILE}`);
718
- console.log('Or run ccconfig edit to open it with your preferred editor');
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
  }
@@ -778,20 +819,105 @@ async function update(name) {
778
819
  }
779
820
  }
780
821
 
822
+ /**
823
+ * Fork (copy) existing configuration
824
+ */
825
+ async function fork(sourceName) {
826
+ initIfNeeded();
827
+ requireInteractive('forking configurations');
828
+
829
+ const helper = new ReadlineHelper();
830
+
831
+ try {
832
+ if (!sourceName) {
833
+ sourceName = await helper.ask('Please enter source configuration name to copy from');
834
+ }
835
+
836
+ validateConfigName(sourceName);
837
+
838
+ const {profile: sourceProfile} = ensureProfileAvailable(sourceName, {
839
+ allowEmptyEnv: true,
840
+ onEmptyProfiles: () => {
841
+ console.error('Error: Configuration file does not exist');
842
+ },
843
+ onMissingProfile: () => {
844
+ console.error(`Error: Configuration '${sourceName}' does not exist`);
845
+ console.error('');
846
+ console.error('Run ccconfig list to see available configurations');
847
+ }
848
+ });
849
+
850
+ const profiles = loadProfiles() || {profiles: {}};
851
+ const profilesMap = getProfilesMap(profiles);
852
+
853
+ // Ask for new name with validation loop (default to source name)
854
+ let newName = '';
855
+ while (true) {
856
+ newName = await helper.ask(
857
+ `Please enter new configuration name`, sourceName);
858
+
859
+ // Validate name format
860
+ try {
861
+ validateConfigName(newName);
862
+ } catch (error) {
863
+ // validateConfigName calls process.exit, but just in case
864
+ continue;
865
+ }
866
+
867
+ // Check if name already exists
868
+ if (profilesMap[newName]) {
869
+ console.error(`Error: Configuration '${newName}' already exists`);
870
+ console.error('Please choose a different name.');
871
+ console.error('');
872
+ continue;
873
+ }
874
+
875
+ // Name is valid and unique
876
+ break;
877
+ }
878
+
879
+ console.log(`Creating configuration '${newName}' from '${sourceName}'...`);
880
+ console.log('Press Enter to keep current value/default, or enter new value to update');
881
+ console.log('');
882
+
883
+ // Get environment variables (inherited from source)
884
+ const existingEnv = sourceProfile.env || {};
885
+ const envVars = await helper.askEnvVars(existingEnv);
886
+
887
+ // Now save everything at once
888
+ profilesMap[newName] = {env: envVars};
889
+ saveProfiles(profiles);
890
+
891
+ console.log(`✓ Configuration '${newName}' created from '${sourceName}'`);
892
+ console.log('');
893
+ console.log('Environment variables:');
894
+ displayEnvVars(envVars);
895
+ console.log('');
896
+ console.log('Run the following command to activate:');
897
+ console.log(` ccconfig use ${newName}`);
898
+
899
+ } finally {
900
+ helper.close();
901
+ }
902
+ }
903
+
781
904
  /**
782
905
  * Remove configuration
783
906
  */
784
- function remove(name) {
907
+ async function remove(name) {
785
908
  if (!name) {
786
909
  console.error('Error: Missing configuration name');
787
910
  console.error('Usage: ccconfig remove <name>');
788
911
  process.exit(1);
789
912
  }
790
913
 
914
+ // Check if terminal is interactive before proceeding
915
+ requireInteractive('removing configurations');
916
+
791
917
  // Validate configuration name
792
918
  validateConfigName(name);
793
919
 
794
- const {profiles} = ensureProfileAvailable(name, {
920
+ const {profile, profiles} = ensureProfileAvailable(name, {
795
921
  allowEmptyEnv: true,
796
922
  onEmptyProfiles: () => {
797
923
  console.error('Error: Configuration file does not exist');
@@ -801,9 +927,45 @@ function remove(name) {
801
927
  }
802
928
  });
803
929
 
804
- delete getProfilesMap(profiles)[name];
805
- saveProfiles(profiles);
806
- console.log(`✓ Configuration '${name}' removed`);
930
+ // Display profile information before removal
931
+ console.log('');
932
+ console.log('WARNING: PERMANENT DELETION');
933
+ console.log('═══════════════════════════════════════════════════════════');
934
+ console.log('');
935
+ console.log(`Configuration to be removed: ${name}`);
936
+ console.log('');
937
+ console.log('Profile details:');
938
+ if (profile.env && Object.keys(profile.env).length > 0) {
939
+ displayEnvVars(profile.env, true, ' ');
940
+ } else {
941
+ console.log(' (no environment variables configured)');
942
+ }
943
+ console.log('');
944
+ console.log('This action CANNOT be undone!');
945
+ console.log('All configuration data for this profile will be \x1b[1mpermanently deleted\x1b[0m.');
946
+ console.log('');
947
+
948
+ // Ask for confirmation
949
+ const helper = new ReadlineHelper();
950
+ try {
951
+ const confirmation = await helper.ask(
952
+ `Are you sure you want to remove '${name}'? (yes/no)`, 'no');
953
+ const normalized = confirmation.trim().toLowerCase();
954
+
955
+ if (normalized !== 'yes' && normalized !== 'y') {
956
+ console.log('');
957
+ console.log('Operation cancelled.');
958
+ return;
959
+ }
960
+
961
+ // Proceed with removal
962
+ delete getProfilesMap(profiles)[name];
963
+ saveProfiles(profiles);
964
+ console.log('');
965
+ console.log(`✓ Configuration '${name}' removed`);
966
+ } finally {
967
+ helper.close();
968
+ }
807
969
  }
808
970
 
809
971
  /**
@@ -1262,25 +1424,6 @@ function current(showSecret = false) {
1262
1424
  console.log('═══════════════════════════════════════════');
1263
1425
  }
1264
1426
 
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
1427
  /**
1285
1428
  * Switch/view mode
1286
1429
  */
@@ -1376,9 +1519,10 @@ function env(format = 'bash') {
1376
1519
  * @param {Array} extraArgs - Additional arguments to pass to Claude
1377
1520
  * @param {Object} options - Options object
1378
1521
  * @param {boolean} options.safe - Whether to run in safe mode (default: false)
1522
+ * @param {Function} options.onExit - Callback to execute before process exits
1379
1523
  */
1380
1524
  function startClaude(name, extraArgs = [], options = {}) {
1381
- const {safe = false} = options;
1525
+ const {safe = false, onExit = null} = options;
1382
1526
  const commandName = safe ? 'safe-start' : 'start';
1383
1527
 
1384
1528
  if (!name) {
@@ -1531,6 +1675,11 @@ function startClaude(name, extraArgs = [], options = {}) {
1531
1675
  process.removeListener('SIGINT', signalHandler);
1532
1676
  process.removeListener('SIGTERM', signalHandler);
1533
1677
 
1678
+ // Execute onExit callback before showing promotion message
1679
+ if (typeof onExit === 'function') {
1680
+ onExit();
1681
+ }
1682
+
1534
1683
  // Show project promotion message on exit
1535
1684
  console.log('');
1536
1685
  console.log('──────────────────────────────────────────');
@@ -1566,16 +1715,16 @@ function startClaude(name, extraArgs = [], options = {}) {
1566
1715
  /**
1567
1716
  * Start Claude Code with specified profile (auto-approve mode)
1568
1717
  */
1569
- function start(name, extraArgs = []) {
1570
- return startClaude(name, extraArgs, {safe: false});
1718
+ function start(name, extraArgs = [], options = {}) {
1719
+ return startClaude(name, extraArgs, {safe: false, ...options});
1571
1720
  }
1572
1721
 
1573
1722
  /**
1574
1723
  * Start Claude Code with specified profile (safe mode - requires permission
1575
1724
  * confirmation)
1576
1725
  */
1577
- function safeStart(name, extraArgs = []) {
1578
- return startClaude(name, extraArgs, {safe: true});
1726
+ function safeStart(name, extraArgs = [], options = {}) {
1727
+ return startClaude(name, extraArgs, {safe: true, ...options});
1579
1728
  }
1580
1729
 
1581
1730
  /**
@@ -1618,7 +1767,7 @@ _ccconfig_completions() {
1618
1767
  ;;
1619
1768
  2)
1620
1769
  case "\${prev}" in
1621
- use|start|safe-start|update|remove|rm)
1770
+ use|start|safe-start|update|fork|remove|rm)
1622
1771
  COMPREPLY=( $(compgen -W "\${profiles}" -- \${cur}) )
1623
1772
  ;;
1624
1773
  mode)
@@ -1627,6 +1776,9 @@ _ccconfig_completions() {
1627
1776
  env)
1628
1777
  COMPREPLY=( $(compgen -W "bash zsh fish sh powershell pwsh dotenv" -- \${cur}) )
1629
1778
  ;;
1779
+ completion)
1780
+ COMPREPLY=( $(compgen -W "bash zsh fish powershell pwsh" -- \${cur}) )
1781
+ ;;
1630
1782
  esac
1631
1783
  ;;
1632
1784
  3)
@@ -1655,6 +1807,7 @@ _ccconfig() {
1655
1807
  'ls:List all configurations'
1656
1808
  'add:Add new configuration'
1657
1809
  'update:Update existing configuration'
1810
+ 'fork:Copy existing configuration and update'
1658
1811
  'use:Switch to specified configuration'
1659
1812
  'start:Start Claude Code (auto-approve mode)'
1660
1813
  'safe-start:Start Claude Code (safe mode, requires confirmation)'
@@ -1663,7 +1816,6 @@ _ccconfig() {
1663
1816
  'current:Display current configuration'
1664
1817
  'mode:View or switch mode'
1665
1818
  'env:Output environment variables'
1666
- 'edit:Show configuration file location'
1667
1819
  )
1668
1820
 
1669
1821
  modes=('settings' 'env')
@@ -1680,7 +1832,7 @@ _ccconfig() {
1680
1832
  ;;
1681
1833
  3)
1682
1834
  case $words[2] in
1683
- use|start|safe-start|update|remove|rm)
1835
+ use|start|safe-start|update|fork|remove|rm)
1684
1836
  _describe 'profile' profiles
1685
1837
  ;;
1686
1838
  mode)
@@ -1689,6 +1841,11 @@ _ccconfig() {
1689
1841
  env)
1690
1842
  _describe 'format' formats
1691
1843
  ;;
1844
+ completion)
1845
+ local -a shells
1846
+ shells=('bash' 'zsh' 'fish' 'powershell' 'pwsh')
1847
+ _describe 'shell' shells
1848
+ ;;
1692
1849
  esac
1693
1850
  ;;
1694
1851
  4)
@@ -1716,6 +1873,7 @@ complete -c ccconfig -f -n "__fish_use_subcommand" -a "list" -d "List all config
1716
1873
  complete -c ccconfig -f -n "__fish_use_subcommand" -a "ls" -d "List all configurations"
1717
1874
  complete -c ccconfig -f -n "__fish_use_subcommand" -a "add" -d "Add new configuration"
1718
1875
  complete -c ccconfig -f -n "__fish_use_subcommand" -a "update" -d "Update existing configuration"
1876
+ complete -c ccconfig -f -n "__fish_use_subcommand" -a "fork" -d "Copy existing configuration and update"
1719
1877
  complete -c ccconfig -f -n "__fish_use_subcommand" -a "use" -d "Switch to specified configuration"
1720
1878
  complete -c ccconfig -f -n "__fish_use_subcommand" -a "start" -d "Start Claude Code (auto-approve mode)"
1721
1879
  complete -c ccconfig -f -n "__fish_use_subcommand" -a "safe-start" -d "Start Claude Code (safe mode, requires confirmation)"
@@ -1724,7 +1882,6 @@ complete -c ccconfig -f -n "__fish_use_subcommand" -a "rm" -d "Remove configurat
1724
1882
  complete -c ccconfig -f -n "__fish_use_subcommand" -a "current" -d "Display current configuration"
1725
1883
  complete -c ccconfig -f -n "__fish_use_subcommand" -a "mode" -d "View or switch mode"
1726
1884
  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
1885
 
1729
1886
  # Get profile names dynamically
1730
1887
  function __ccconfig_profiles
@@ -1733,8 +1890,8 @@ function __ccconfig_profiles
1733
1890
  end
1734
1891
  end
1735
1892
 
1736
- # Profile name completion for use, start, safe-start, update, remove
1737
- complete -c ccconfig -f -n "__fish_seen_subcommand_from use start safe-start update remove rm" -a "(__ccconfig_profiles)"
1893
+ # Profile name completion for use, start, safe-start, update, fork, remove
1894
+ complete -c ccconfig -f -n "__fish_seen_subcommand_from use start safe-start update fork remove rm" -a "(__ccconfig_profiles)"
1738
1895
 
1739
1896
  # Mode options
1740
1897
  complete -c ccconfig -f -n "__fish_seen_subcommand_from mode" -a "settings env"
@@ -1742,6 +1899,9 @@ complete -c ccconfig -f -n "__fish_seen_subcommand_from mode" -a "settings env"
1742
1899
  # Env format options
1743
1900
  complete -c ccconfig -f -n "__fish_seen_subcommand_from env" -a "bash zsh fish sh powershell pwsh dotenv"
1744
1901
 
1902
+ # Completion shell options
1903
+ complete -c ccconfig -f -n "__fish_seen_subcommand_from completion" -a "bash zsh fish powershell pwsh"
1904
+
1745
1905
  # Flags for use command
1746
1906
  complete -c ccconfig -f -n "__fish_seen_subcommand_from use" -s p -l permanent -d "Write permanently to shell config"
1747
1907
 
@@ -1776,7 +1936,7 @@ function Get-CconfigProfiles {
1776
1936
  Register-ArgumentCompleter -Native -CommandName ccconfig -ScriptBlock {
1777
1937
  param($wordToComplete, $commandAst, $cursorPosition)
1778
1938
 
1779
- $commands = @('list', 'ls', 'add', 'update', 'use', 'start', 'safe-start', 'remove', 'rm', 'current', 'mode', 'env', 'edit', 'completion')
1939
+ $commands = @('list', 'ls', 'add', 'update', 'fork', 'use', 'start', 'safe-start', 'remove', 'rm', 'current', 'mode', 'env', 'completion')
1780
1940
  $modes = @('settings', 'env')
1781
1941
  $formats = @('bash', 'zsh', 'fish', 'sh', 'powershell', 'pwsh', 'dotenv')
1782
1942
 
@@ -1798,7 +1958,7 @@ Register-ArgumentCompleter -Native -CommandName ccconfig -ScriptBlock {
1798
1958
  # Second argument completions based on command
1799
1959
  if ($position -eq 2 -or ($position -eq 3 -and $wordToComplete)) {
1800
1960
  switch ($command) {
1801
- { $_ -in 'use', 'start', 'safe-start', 'update', 'remove', 'rm' } {
1961
+ { $_ -in 'use', 'start', 'safe-start', 'update', 'fork', 'remove', 'rm' } {
1802
1962
  Get-CconfigProfiles | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
1803
1963
  [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
1804
1964
  }
@@ -1875,6 +2035,8 @@ function help() {
1875
2035
  ' add [name] Add new configuration (interactive)');
1876
2036
  console.log(
1877
2037
  ' update [name] Update existing configuration (interactive)');
2038
+ console.log(
2039
+ ' fork [source-name] Copy existing configuration and update (interactive)');
1878
2040
  console.log(
1879
2041
  ' use <name> [-p|--permanent] Switch to specified configuration');
1880
2042
  console.log(
@@ -1889,8 +2051,6 @@ function help() {
1889
2051
  ' mode [settings|env] View or switch mode');
1890
2052
  console.log(
1891
2053
  ' env [format] Output environment variables (env mode)');
1892
- console.log(
1893
- ' edit Show configuration file location');
1894
2054
  console.log(
1895
2055
  ' completion <bash|zsh|fish|pwsh> Generate shell completion script');
1896
2056
  console.log('');
@@ -1999,9 +2159,12 @@ async function main() {
1999
2159
  case 'update':
2000
2160
  await update(filteredArgs[1]);
2001
2161
  break;
2162
+ case 'fork':
2163
+ await fork(filteredArgs[1]);
2164
+ break;
2002
2165
  case 'remove':
2003
2166
  case 'rm':
2004
- remove(filteredArgs[1]);
2167
+ await remove(filteredArgs[1]);
2005
2168
  break;
2006
2169
  case 'current':
2007
2170
  current(showSecret);
@@ -2012,9 +2175,6 @@ async function main() {
2012
2175
  case 'env':
2013
2176
  env(filteredArgs[1] || 'bash');
2014
2177
  break;
2015
- case 'edit':
2016
- edit();
2017
- break;
2018
2178
  case 'start':
2019
2179
  if (!filteredArgs[1]) {
2020
2180
  console.error('Error: Missing configuration name');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccconfig",
3
- "version": "1.4.3",
3
+ "version": "1.5.1",
4
4
  "description": "Cross-platform Claude Code configuration switching tool",
5
5
  "main": "ccconfig.js",
6
6
  "bin": {