@kaitranntt/ccs 2.4.1 → 2.4.2
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 +1 -1
- package/bin/ccs.js +36 -3
- package/bin/claude-detector.js +48 -4
- package/package.json +1 -1
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.4.
|
|
1
|
+
2.4.2
|
package/bin/ccs.js
CHANGED
|
@@ -11,6 +11,18 @@ const { getSettingsPath } = require('./config-manager');
|
|
|
11
11
|
// Version (sync with package.json)
|
|
12
12
|
const CCS_VERSION = require('../package.json').version;
|
|
13
13
|
|
|
14
|
+
// Helper: Get spawn options for claude execution
|
|
15
|
+
// On Windows, .cmd/.bat/.ps1 files need shell: true
|
|
16
|
+
function getSpawnOptions(claudePath) {
|
|
17
|
+
const isWindows = process.platform === 'win32';
|
|
18
|
+
const needsShell = isWindows && /\.(cmd|bat|ps1)$/i.test(claudePath);
|
|
19
|
+
|
|
20
|
+
return {
|
|
21
|
+
stdio: 'inherit',
|
|
22
|
+
shell: needsShell // Required for .cmd files on Windows
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
14
26
|
// Special command handlers
|
|
15
27
|
function handleVersionCommand() {
|
|
16
28
|
console.log(`CCS (Claude Code Switch) version ${CCS_VERSION}`);
|
|
@@ -28,8 +40,15 @@ function handleVersionCommand() {
|
|
|
28
40
|
function handleHelpCommand(remainingArgs) {
|
|
29
41
|
const claudeCli = detectClaudeCli();
|
|
30
42
|
|
|
43
|
+
// Check if claude was found
|
|
44
|
+
if (!claudeCli) {
|
|
45
|
+
showClaudeNotFoundError();
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
|
|
31
49
|
// Execute claude --help
|
|
32
|
-
const
|
|
50
|
+
const spawnOpts = getSpawnOptions(claudeCli);
|
|
51
|
+
const child = spawn(claudeCli, ['--help', ...remainingArgs], spawnOpts);
|
|
33
52
|
|
|
34
53
|
child.on('exit', (code, signal) => {
|
|
35
54
|
if (signal) {
|
|
@@ -111,8 +130,15 @@ function main() {
|
|
|
111
130
|
if (profile === 'default') {
|
|
112
131
|
const claudeCli = detectClaudeCli();
|
|
113
132
|
|
|
133
|
+
// Check if claude was found
|
|
134
|
+
if (!claudeCli) {
|
|
135
|
+
showClaudeNotFoundError();
|
|
136
|
+
process.exit(1);
|
|
137
|
+
}
|
|
138
|
+
|
|
114
139
|
// Execute claude with args
|
|
115
|
-
const
|
|
140
|
+
const spawnOpts = getSpawnOptions(claudeCli);
|
|
141
|
+
const child = spawn(claudeCli, remainingArgs, spawnOpts);
|
|
116
142
|
|
|
117
143
|
child.on('exit', (code, signal) => {
|
|
118
144
|
if (signal) {
|
|
@@ -136,9 +162,16 @@ function main() {
|
|
|
136
162
|
// Detect Claude CLI
|
|
137
163
|
const claudeCli = detectClaudeCli();
|
|
138
164
|
|
|
165
|
+
// Check if claude was found
|
|
166
|
+
if (!claudeCli) {
|
|
167
|
+
showClaudeNotFoundError();
|
|
168
|
+
process.exit(1);
|
|
169
|
+
}
|
|
170
|
+
|
|
139
171
|
// Execute claude with --settings
|
|
140
172
|
const claudeArgs = ['--settings', settingsPath, ...remainingArgs];
|
|
141
|
-
const
|
|
173
|
+
const spawnOpts = getSpawnOptions(claudeCli);
|
|
174
|
+
const child = spawn(claudeCli, claudeArgs, spawnOpts);
|
|
142
175
|
|
|
143
176
|
child.on('exit', (code, signal) => {
|
|
144
177
|
if (signal) {
|
package/bin/claude-detector.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const fs = require('fs');
|
|
4
|
+
const { execSync } = require('child_process');
|
|
4
5
|
const { showError, expandPath } = require('./helpers');
|
|
5
6
|
|
|
6
7
|
// Detect Claude CLI executable
|
|
@@ -17,19 +18,62 @@ function detectClaudeCli() {
|
|
|
17
18
|
console.warn(' Falling back to system PATH lookup...');
|
|
18
19
|
}
|
|
19
20
|
|
|
20
|
-
// Priority 2:
|
|
21
|
-
// This
|
|
22
|
-
|
|
21
|
+
// Priority 2: Resolve 'claude' from PATH using which/where.exe
|
|
22
|
+
// This fixes Windows npm installation where spawn() can't resolve bare command names
|
|
23
|
+
// SECURITY: Commands are hardcoded literals with no user input - safe from injection
|
|
24
|
+
const isWindows = process.platform === 'win32';
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
const cmd = isWindows ? 'where.exe claude' : 'which claude';
|
|
28
|
+
const result = execSync(cmd, {
|
|
29
|
+
encoding: 'utf8',
|
|
30
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
31
|
+
timeout: 5000 // 5 second timeout to prevent hangs
|
|
32
|
+
}).trim();
|
|
33
|
+
|
|
34
|
+
// where.exe may return multiple lines (all matches in PATH order)
|
|
35
|
+
const matches = result.split('\n').map(p => p.trim()).filter(p => p);
|
|
36
|
+
|
|
37
|
+
if (isWindows) {
|
|
38
|
+
// On Windows, prefer executables with extensions (.exe, .cmd, .bat)
|
|
39
|
+
// where.exe often returns file without extension first, then the actual .cmd wrapper
|
|
40
|
+
const withExtension = matches.find(p => /\.(exe|cmd|bat|ps1)$/i.test(p));
|
|
41
|
+
const claudePath = withExtension || matches[0];
|
|
42
|
+
|
|
43
|
+
if (claudePath && fs.existsSync(claudePath)) {
|
|
44
|
+
return claudePath;
|
|
45
|
+
}
|
|
46
|
+
} else {
|
|
47
|
+
// On Unix, first match is fine
|
|
48
|
+
const claudePath = matches[0];
|
|
49
|
+
|
|
50
|
+
if (claudePath && fs.existsSync(claudePath)) {
|
|
51
|
+
return claudePath;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
} catch (err) {
|
|
55
|
+
// Command failed - claude not in PATH
|
|
56
|
+
// Fall through to return null
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Priority 3: Claude not found
|
|
60
|
+
return null;
|
|
23
61
|
}
|
|
24
62
|
|
|
25
|
-
// Show Claude not found error
|
|
63
|
+
// Show Claude not found error with diagnostics
|
|
26
64
|
function showClaudeNotFoundError() {
|
|
27
65
|
const isWindows = process.platform === 'win32';
|
|
66
|
+
const pathDirs = (process.env.PATH || '').split(isWindows ? ';' : ':');
|
|
28
67
|
|
|
29
68
|
const errorMsg = `Claude CLI not found in PATH
|
|
30
69
|
|
|
31
70
|
CCS requires Claude CLI to be installed and available in your PATH.
|
|
32
71
|
|
|
72
|
+
[i] Diagnostic Info:
|
|
73
|
+
Platform: ${process.platform}
|
|
74
|
+
PATH directories: ${pathDirs.length}
|
|
75
|
+
Looking for: claude${isWindows ? '.exe' : ''}
|
|
76
|
+
|
|
33
77
|
Solutions:
|
|
34
78
|
1. Install Claude CLI:
|
|
35
79
|
https://docs.claude.com/en/docs/claude-code/installation
|