@kaitranntt/ccs 2.4.0 → 2.4.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/VERSION CHANGED
@@ -1 +1 @@
1
- 2.4.0
1
+ 2.4.1
package/bin/ccs.js CHANGED
@@ -5,7 +5,7 @@ const { spawn } = require('child_process');
5
5
  const path = require('path');
6
6
  const fs = require('fs');
7
7
  const { showError, colors } = require('./helpers');
8
- const { detectClaudeCli, validateClaudeCli, showClaudeNotFoundError } = require('./claude-detector');
8
+ const { detectClaudeCli, showClaudeNotFoundError } = require('./claude-detector');
9
9
  const { getSettingsPath } = require('./config-manager');
10
10
 
11
11
  // Version (sync with package.json)
@@ -26,21 +26,8 @@ function handleVersionCommand() {
26
26
  }
27
27
 
28
28
  function handleHelpCommand(remainingArgs) {
29
- // Detect and validate Claude CLI
30
29
  const claudeCli = detectClaudeCli();
31
30
 
32
- if (!claudeCli) {
33
- showClaudeNotFoundError();
34
- process.exit(1);
35
- }
36
-
37
- try {
38
- validateClaudeCli(claudeCli);
39
- } catch (e) {
40
- showError(e.message);
41
- process.exit(1);
42
- }
43
-
44
31
  // Execute claude --help
45
32
  const child = spawn(claudeCli, ['--help', ...remainingArgs], { stdio: 'inherit' });
46
33
 
@@ -53,7 +40,7 @@ function handleHelpCommand(remainingArgs) {
53
40
  });
54
41
 
55
42
  child.on('error', (err) => {
56
- console.error(`Error executing claude --help: ${err.message}`);
43
+ showClaudeNotFoundError();
57
44
  process.exit(1);
58
45
  });
59
46
  }
@@ -124,18 +111,6 @@ function main() {
124
111
  if (profile === 'default') {
125
112
  const claudeCli = detectClaudeCli();
126
113
 
127
- if (!claudeCli) {
128
- showClaudeNotFoundError();
129
- process.exit(1);
130
- }
131
-
132
- try {
133
- validateClaudeCli(claudeCli);
134
- } catch (e) {
135
- showError(e.message);
136
- process.exit(1);
137
- }
138
-
139
114
  // Execute claude with args
140
115
  const child = spawn(claudeCli, remainingArgs, { stdio: 'inherit' });
141
116
 
@@ -148,7 +123,7 @@ function main() {
148
123
  });
149
124
 
150
125
  child.on('error', (err) => {
151
- console.error(`Error executing claude: ${err.message}`);
126
+ showClaudeNotFoundError();
152
127
  process.exit(1);
153
128
  });
154
129
 
@@ -161,19 +136,6 @@ function main() {
161
136
  // Detect Claude CLI
162
137
  const claudeCli = detectClaudeCli();
163
138
 
164
- if (!claudeCli) {
165
- showClaudeNotFoundError();
166
- process.exit(1);
167
- }
168
-
169
- // Validate Claude CLI path
170
- try {
171
- validateClaudeCli(claudeCli);
172
- } catch (e) {
173
- showError(e.message);
174
- process.exit(1);
175
- }
176
-
177
139
  // Execute claude with --settings
178
140
  const claudeArgs = ['--settings', settingsPath, ...remainingArgs];
179
141
  const child = spawn(claudeCli, claudeArgs, { stdio: 'inherit' });
@@ -187,7 +149,7 @@ function main() {
187
149
  });
188
150
 
189
151
  child.on('error', (err) => {
190
- console.error(`Error executing claude: ${err.message}`);
152
+ showClaudeNotFoundError();
191
153
  process.exit(1);
192
154
  });
193
155
  }
@@ -1,156 +1,58 @@
1
1
  'use strict';
2
2
 
3
3
  const fs = require('fs');
4
- const path = require('path');
5
- const { execSync } = require('child_process');
6
- const { showError, expandPath, isPathSafe } = require('./helpers');
4
+ const { showError, expandPath } = require('./helpers');
7
5
 
8
6
  // Detect Claude CLI executable
9
7
  function detectClaudeCli() {
10
- // Priority 1: CCS_CLAUDE_PATH environment variable
8
+ // Priority 1: CCS_CLAUDE_PATH environment variable (if user wants custom path)
11
9
  if (process.env.CCS_CLAUDE_PATH) {
12
10
  const ccsPath = expandPath(process.env.CCS_CLAUDE_PATH);
13
- if (fs.existsSync(ccsPath) && isExecutable(ccsPath)) {
11
+ // Basic validation: file exists
12
+ if (fs.existsSync(ccsPath)) {
14
13
  return ccsPath;
15
14
  }
16
- // Invalid CCS_CLAUDE_PATH - continue to fallbacks
15
+ // Invalid CCS_CLAUDE_PATH - show warning and fall back to PATH
16
+ console.warn('[!] Warning: CCS_CLAUDE_PATH is set but file not found:', ccsPath);
17
+ console.warn(' Falling back to system PATH lookup...');
17
18
  }
18
19
 
19
- // Priority 2: Check if claude in PATH
20
- try {
21
- const claudePath = execSync(
22
- process.platform === 'win32' ? 'where claude' : 'which claude',
23
- { encoding: 'utf8', stdio: ['pipe', 'pipe', 'ignore'] }
24
- ).trim().split('\n')[0];
25
-
26
- if (claudePath && fs.existsSync(claudePath)) {
27
- return claudePath;
28
- }
29
- } catch (e) {
30
- // Not in PATH, continue to common locations
31
- }
32
-
33
- // Priority 3: Check common installation locations
34
- const commonLocations = getCommonLocations();
35
-
36
- for (const location of commonLocations) {
37
- const expandedPath = expandPath(location);
38
- if (fs.existsSync(expandedPath) && isExecutable(expandedPath)) {
39
- return expandedPath;
40
- }
41
- }
42
-
43
- // Not found
44
- return null;
45
- }
46
-
47
- // Get platform-specific common locations
48
- function getCommonLocations() {
49
- const home = require('os').homedir();
50
-
51
- if (process.platform === 'win32') {
52
- return [
53
- path.join(process.env.LOCALAPPDATA || '', 'Claude', 'claude.exe'),
54
- path.join(process.env.PROGRAMFILES || '', 'Claude', 'claude.exe'),
55
- 'C:\\Program Files\\Claude\\claude.exe',
56
- 'D:\\Program Files\\Claude\\claude.exe',
57
- path.join(home, '.local', 'bin', 'claude.exe')
58
- ];
59
- } else if (process.platform === 'darwin') {
60
- return [
61
- '/usr/local/bin/claude',
62
- path.join(home, '.local/bin/claude'),
63
- '/opt/homebrew/bin/claude'
64
- ];
65
- } else {
66
- return [
67
- '/usr/local/bin/claude',
68
- path.join(home, '.local/bin/claude'),
69
- '/usr/bin/claude'
70
- ];
71
- }
72
- }
73
-
74
- // Check if file is executable
75
- function isExecutable(filePath) {
76
- try {
77
- fs.accessSync(filePath, fs.constants.X_OK);
78
- return true;
79
- } catch (e) {
80
- return false;
81
- }
82
- }
83
-
84
- // Validate Claude CLI path
85
- function validateClaudeCli(claudePath) {
86
- // Check 1: Empty path
87
- if (!claudePath) {
88
- throw new Error('No path provided');
89
- }
90
-
91
- // Check 2: File exists
92
- if (!fs.existsSync(claudePath)) {
93
- throw new Error(`File not found: ${claudePath}`);
94
- }
95
-
96
- // Check 3: Is regular file (not directory)
97
- const stats = fs.statSync(claudePath);
98
- if (!stats.isFile()) {
99
- throw new Error(`Path is a directory: ${claudePath}`);
100
- }
101
-
102
- // Check 4: Is executable
103
- if (!isExecutable(claudePath)) {
104
- throw new Error(`File is not executable: ${claudePath}\n\nTry: chmod +x ${claudePath}`);
105
- }
106
-
107
- // Check 5: Path safety (prevent injection)
108
- if (!isPathSafe(claudePath)) {
109
- throw new Error(`Path contains unsafe characters: ${claudePath}\n\nAllowed: alphanumeric, path separators, spaces, hyphens, underscores, dots`);
110
- }
111
-
112
- return true;
20
+ // Priority 2: Use 'claude' from PATH (trust the system)
21
+ // This is the standard case - if user installed Claude CLI, it's in their PATH
22
+ return 'claude';
113
23
  }
114
24
 
115
25
  // Show Claude not found error
116
26
  function showClaudeNotFoundError() {
117
- const envVarStatus = process.env.CCS_CLAUDE_PATH || '(not set)';
118
27
  const isWindows = process.platform === 'win32';
119
28
 
120
- const errorMsg = `Claude CLI not found
29
+ const errorMsg = `Claude CLI not found in PATH
121
30
 
122
- Searched:
123
- - CCS_CLAUDE_PATH: ${envVarStatus}
124
- - System PATH: not found
125
- - Common locations: not found
31
+ CCS requires Claude CLI to be installed and available in your PATH.
126
32
 
127
33
  Solutions:
128
- 1. Add Claude CLI to PATH:
34
+ 1. Install Claude CLI:
35
+ https://docs.claude.com/en/docs/claude-code/installation
129
36
 
130
- ${isWindows
131
- ? '# Find where Claude is installed\n Get-ChildItem -Path C:\\,D:\\ -Filter claude.exe -Recurse\n\n # Add to PATH\n $env:Path += \';D:\\path\\to\\claude\\directory\'\n [Environment]::SetEnvironmentVariable(\'Path\', $env:Path, \'User\')'
132
- : '# Find where Claude is installed\n sudo find / -name claude 2>/dev/null\n\n # Add to PATH\n export PATH="/path/to/claude/bin:$PATH"\n echo \'export PATH="/path/to/claude/bin:$PATH"\' >> ~/.bashrc\n source ~/.bashrc'
133
- }
37
+ 2. Verify installation:
38
+ ${isWindows ? 'Get-Command claude' : 'command -v claude'}
134
39
 
135
- 2. Or set custom path:
40
+ 3. If installed but not in PATH, add it:
41
+ # Find Claude installation
42
+ ${isWindows ? 'where.exe claude' : 'which claude'}
136
43
 
44
+ # Or set custom path
137
45
  ${isWindows
138
- ? '$env:CCS_CLAUDE_PATH = \'D:\\full\\path\\to\\claude.exe\'\n [Environment]::SetEnvironmentVariable(\'CCS_CLAUDE_PATH\', \'D:\\full\\path\\to\\claude.exe\', \'User\')'
139
- : 'export CCS_CLAUDE_PATH="/full/path/to/claude"\n echo \'export CCS_CLAUDE_PATH="/full/path/to/claude"\' >> ~/.bashrc\n source ~/.bashrc'
46
+ ? '$env:CCS_CLAUDE_PATH = \'C:\\path\\to\\claude.exe\''
47
+ : 'export CCS_CLAUDE_PATH=\'/path/to/claude\''
140
48
  }
141
49
 
142
- 3. Or install Claude CLI:
143
-
144
- https://docs.claude.com/en/docs/claude-code/installation
145
-
146
- Verify installation:
147
- ccs --version`;
50
+ Restart your terminal after installation.`;
148
51
 
149
52
  showError(errorMsg);
150
53
  }
151
54
 
152
55
  module.exports = {
153
56
  detectClaudeCli,
154
- validateClaudeCli,
155
57
  showClaudeNotFoundError
156
58
  };
package/lib/ccs CHANGED
@@ -2,7 +2,7 @@
2
2
  set -euo pipefail
3
3
 
4
4
  # Version (updated by scripts/bump-version.sh)
5
- CCS_VERSION="2.4.0"
5
+ CCS_VERSION="2.4.1"
6
6
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7
7
 
8
8
  # --- Color/Format Functions ---
package/lib/ccs.ps1 CHANGED
@@ -72,7 +72,7 @@ Restart your terminal after installation.
72
72
  }
73
73
 
74
74
  # Version (updated by scripts/bump-version.sh)
75
- $CcsVersion = "2.4.0"
75
+ $CcsVersion = "2.4.1"
76
76
  $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
77
77
 
78
78
  # Installation function for commands and skills
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaitranntt/ccs",
3
- "version": "2.4.0",
3
+ "version": "2.4.1",
4
4
  "description": "Claude Code Switch - Instant profile switching between Claude Sonnet 4.5 and GLM 4.6",
5
5
  "keywords": [
6
6
  "cli",