@kaitranntt/ccs 2.4.4 → 2.4.6
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 +21 -40
- package/README.vi.md +13 -32
- package/VERSION +1 -1
- package/bin/ccs.js +122 -131
- package/bin/claude-detector.js +5 -34
- package/bin/config-manager.js +8 -69
- package/bin/helpers.js +40 -33
- package/lib/ccs +131 -80
- package/lib/ccs.ps1 +219 -364
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -108,7 +108,7 @@ export CCS_CLAUDE_PATH="/path/to/claude" # Unix
|
|
|
108
108
|
$env:CCS_CLAUDE_PATH = "D:\Tools\Claude\claude.exe" # Windows
|
|
109
109
|
```
|
|
110
110
|
|
|
111
|
-
**See [Troubleshooting Guide](./docs/troubleshooting.md#claude-cli-in-non-standard-location) for detailed setup instructions.**
|
|
111
|
+
**See [Troubleshooting Guide](./docs/en/troubleshooting.md#claude-cli-in-non-standard-location) for detailed setup instructions.**
|
|
112
112
|
|
|
113
113
|
---
|
|
114
114
|
|
|
@@ -191,35 +191,6 @@ graph LR
|
|
|
191
191
|
- **Context Preservation**: Your workflow remains uninterrupted
|
|
192
192
|
- **Seamless Integration**: Works exactly like native Claude CLI
|
|
193
193
|
|
|
194
|
-
### Task Delegation
|
|
195
|
-
|
|
196
|
-
> **🚧 Work in Progress**: This feature is experimental and not fully tested. Use with caution.
|
|
197
|
-
|
|
198
|
-
CCS includes intelligent task delegation via the `/ccs` meta-command:
|
|
199
|
-
|
|
200
|
-
**Install CCS commands:**
|
|
201
|
-
```bash
|
|
202
|
-
ccs --install # Install /ccs command to Claude CLI
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
**Use task delegation:**
|
|
206
|
-
```bash
|
|
207
|
-
# After running ccs --install, you can use:
|
|
208
|
-
/ccs glm /plan "add user authentication"
|
|
209
|
-
/ccs glm /code "implement auth endpoints"
|
|
210
|
-
/ccs glm /ask "explain this error"
|
|
211
|
-
```
|
|
212
|
-
|
|
213
|
-
**Remove when not needed:**
|
|
214
|
-
```bash
|
|
215
|
-
ccs --uninstall # Remove /ccs command from Claude CLI
|
|
216
|
-
```
|
|
217
|
-
|
|
218
|
-
**Benefits**:
|
|
219
|
-
- ✅ Save tokens by delegating simple tasks to cheaper models
|
|
220
|
-
- ✅ Use right model for each task automatically
|
|
221
|
-
- ✅ Seamless integration with existing workflows
|
|
222
|
-
- ✅ Clean installation and removal when needed
|
|
223
194
|
|
|
224
195
|
---
|
|
225
196
|
|
|
@@ -229,13 +200,13 @@ ccs --uninstall # Remove /ccs command from Claude CLI
|
|
|
229
200
|
ccs # Use Claude subscription (default)
|
|
230
201
|
ccs glm # Use GLM fallback
|
|
231
202
|
ccs --version # Show CCS version and install location
|
|
232
|
-
ccs --install # Install CCS commands and skills to ~/.claude/
|
|
233
|
-
ccs --uninstall # Remove CCS commands and skills from ~/.claude/
|
|
234
203
|
```
|
|
235
204
|
|
|
236
205
|
---
|
|
237
206
|
|
|
238
|
-
### 🗑️ Uninstall
|
|
207
|
+
### 🗑️ Official Uninstall
|
|
208
|
+
|
|
209
|
+
**The recommended way to completely remove CCS:**
|
|
239
210
|
|
|
240
211
|
**macOS / Linux**:
|
|
241
212
|
```bash
|
|
@@ -247,6 +218,16 @@ curl -fsSL ccs.kaitran.ca/uninstall | bash
|
|
|
247
218
|
irm ccs.kaitran.ca/uninstall | iex
|
|
248
219
|
```
|
|
249
220
|
|
|
221
|
+
> 💡 **Why use the official uninstaller?**
|
|
222
|
+
> - Removes all CCS files and configurations
|
|
223
|
+
> - Cleans up PATH modifications
|
|
224
|
+
> - Removes Claude CLI commands/skills
|
|
225
|
+
> - Handles edge cases we've tested
|
|
226
|
+
|
|
227
|
+
**Alternative methods** (if official uninstaller fails):
|
|
228
|
+
- **npm**: `npm uninstall -g @kaitranntt/ccs`
|
|
229
|
+
- **Manual**: See [troubleshooting guide](./docs/en/troubleshooting.md#manual-uninstall)
|
|
230
|
+
|
|
250
231
|
---
|
|
251
232
|
|
|
252
233
|
## 🎯 Philosophy
|
|
@@ -260,17 +241,17 @@ irm ccs.kaitran.ca/uninstall | iex
|
|
|
260
241
|
## 📖 Documentation
|
|
261
242
|
|
|
262
243
|
**Complete documentation in [docs/](./docs/)**:
|
|
263
|
-
- [Installation Guide](./docs/installation.md)
|
|
264
|
-
- [Configuration](./docs/configuration.md)
|
|
265
|
-
- [Usage Examples](./docs/usage.md)
|
|
266
|
-
- [Troubleshooting](./docs/troubleshooting.md)
|
|
267
|
-
- [Contributing](./docs/contributing.md)
|
|
244
|
+
- [Installation Guide](./docs/en/installation.md)
|
|
245
|
+
- [Configuration](./docs/en/configuration.md)
|
|
246
|
+
- [Usage Examples](./docs/en/usage.md)
|
|
247
|
+
- [Troubleshooting](./docs/en/troubleshooting.md)
|
|
248
|
+
- [Contributing](./docs/en/contributing.md)
|
|
268
249
|
|
|
269
250
|
---
|
|
270
251
|
|
|
271
252
|
## 🤝 Contributing
|
|
272
253
|
|
|
273
|
-
We welcome contributions! Please see our [Contributing Guide](./docs/contributing.md) for details.
|
|
254
|
+
We welcome contributions! Please see our [Contributing Guide](./docs/en/contributing.md) for details.
|
|
274
255
|
|
|
275
256
|
---
|
|
276
257
|
|
|
@@ -284,6 +265,6 @@ CCS is licensed under the [MIT License](LICENSE).
|
|
|
284
265
|
|
|
285
266
|
**Made with ❤️ for developers who hit rate limits too often**
|
|
286
267
|
|
|
287
|
-
[⭐ Star this repo](https://github.com/kaitranntt/ccs) | [🐛 Report issues](https://github.com/kaitranntt/ccs/issues) | [📖 Read docs](./docs/)
|
|
268
|
+
[⭐ Star this repo](https://github.com/kaitranntt/ccs) | [🐛 Report issues](https://github.com/kaitranntt/ccs/issues) | [📖 Read docs](./docs/en/)
|
|
288
269
|
|
|
289
270
|
</div>
|
package/README.vi.md
CHANGED
|
@@ -190,35 +190,6 @@ graph LR
|
|
|
190
190
|
- **Bảo Toàn Context**: Workflow của bạn không bị gián đoạn
|
|
191
191
|
- **Tích Hợp Liền Mạch**: Hoạt động chính xác như Claude CLI native
|
|
192
192
|
|
|
193
|
-
### Delegation Tác Vụ
|
|
194
|
-
|
|
195
|
-
> **🚧 Đang phát triển**: Tính năng này đang trong giai đoạn thử nghiệm và chưa được kiểm tra đầy đủ. Sử dụng với cẩn thận.
|
|
196
|
-
|
|
197
|
-
CCS bao gồm delegation tác vụ thông minh qua meta-command `/ccs`:
|
|
198
|
-
|
|
199
|
-
**Cài đặt lệnh CCS:**
|
|
200
|
-
```bash
|
|
201
|
-
ccs --install # Cài đặt lệnh /ccs vào Claude CLI
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
**Sử dụng delegation tác vụ:**
|
|
205
|
-
```bash
|
|
206
|
-
# Sau khi chạy ccs --install, bạn có thể dùng:
|
|
207
|
-
/ccs glm /plan "add user authentication"
|
|
208
|
-
/ccs glm /code "implement auth endpoints"
|
|
209
|
-
/ccs glm /ask "explain this error"
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
**Gỡ bỏ khi không cần:**
|
|
213
|
-
```bash
|
|
214
|
-
ccs --uninstall # Gỡ bỏ lệnh /ccs khỏi Claude CLI
|
|
215
|
-
```
|
|
216
|
-
|
|
217
|
-
**Lợi ích**:
|
|
218
|
-
- ✅ Tiết kiệm tokens bằng cách delegation tác vụ đơn giản cho model rẻ hơn
|
|
219
|
-
- ✅ Dùng đúng model cho từng tác vụ tự động
|
|
220
|
-
- ✅ Tích hợp liền mạch với workflows hiện có
|
|
221
|
-
- ✅ Cài đặt và gỡ bỏ sạch sẽ khi cần
|
|
222
193
|
|
|
223
194
|
---
|
|
224
195
|
|
|
@@ -228,13 +199,13 @@ ccs --uninstall # Gỡ bỏ lệnh /ccs khỏi Claude CLI
|
|
|
228
199
|
ccs # Dùng Claude subscription (mặc định)
|
|
229
200
|
ccs glm # Dùng GLM fallback
|
|
230
201
|
ccs --version # Hiển thị phiên bản CCS và vị trí cài đặt
|
|
231
|
-
ccs --install # Cài đặt lệnh và kỹ năng CCS vào ~/.claude/
|
|
232
|
-
ccs --uninstall # Gỡ bỏ lệnh và kỹ năng CCS khỏi ~/.claude/
|
|
233
202
|
```
|
|
234
203
|
|
|
235
204
|
---
|
|
236
205
|
|
|
237
|
-
### 🗑️ Gỡ Cài Đặt
|
|
206
|
+
### 🗑️ Gỡ Cài Đặt Chính Thức
|
|
207
|
+
|
|
208
|
+
**Cách được khuyến nghị để gỡ bỏ hoàn toàn CCS:**
|
|
238
209
|
|
|
239
210
|
**macOS / Linux**:
|
|
240
211
|
```bash
|
|
@@ -246,6 +217,16 @@ curl -fsSL ccs.kaitran.ca/uninstall | bash
|
|
|
246
217
|
irm ccs.kaitran.ca/uninstall | iex
|
|
247
218
|
```
|
|
248
219
|
|
|
220
|
+
> 💡 **Tại sao dùng uninstaller chính thức?**
|
|
221
|
+
> - Gỡ bỏ tất cả file và cấu hình CCS
|
|
222
|
+
> - Dọn dẹp PATH modifications
|
|
223
|
+
> - Gỡ bỏ commands/skills Claude CLI
|
|
224
|
+
> - Xử lý các trường hợp đặc biệt đã test
|
|
225
|
+
|
|
226
|
+
**Phương pháp thay thế** (nếu uninstaller chính thức thất bại):
|
|
227
|
+
- **npm**: `npm uninstall -g @kaitranntt/ccs`
|
|
228
|
+
- **Thủ công**: Xem [hướng dẫn khắc phục](./docs/vi/troubleshooting.vi.md#gỡ-cài-đặt-thủ-công)
|
|
229
|
+
|
|
249
230
|
---
|
|
250
231
|
|
|
251
232
|
## 🎯 Triết Lý
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.4.
|
|
1
|
+
2.4.6
|
package/bin/ccs.js
CHANGED
|
@@ -4,104 +4,149 @@
|
|
|
4
4
|
const { spawn } = require('child_process');
|
|
5
5
|
const path = require('path');
|
|
6
6
|
const fs = require('fs');
|
|
7
|
-
const {
|
|
7
|
+
const { error, colored } = require('./helpers');
|
|
8
8
|
const { detectClaudeCli, showClaudeNotFoundError } = require('./claude-detector');
|
|
9
|
-
const { getSettingsPath } = require('./config-manager');
|
|
9
|
+
const { getSettingsPath, getConfigPath } = require('./config-manager');
|
|
10
10
|
|
|
11
11
|
// Version (sync with package.json)
|
|
12
12
|
const CCS_VERSION = require('../package.json').version;
|
|
13
13
|
|
|
14
|
-
//
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Helper: Escape arguments for shell execution to prevent security vulnerabilities
|
|
28
|
-
function escapeShellArg(arg) {
|
|
29
|
-
if (process.platform !== 'win32') {
|
|
30
|
-
// Unix-like systems: escape single quotes and wrap in single quotes
|
|
31
|
-
return "'" + arg.replace(/'/g, "'\"'\"'") + "'";
|
|
32
|
-
} else {
|
|
33
|
-
// Windows: escape double quotes and wrap in double quotes
|
|
34
|
-
return '"' + arg.replace(/"/g, '""') + '"';
|
|
35
|
-
}
|
|
14
|
+
// Execute Claude CLI with unified spawn logic
|
|
15
|
+
function execClaude(claudeCli, args) {
|
|
16
|
+
const child = spawn(claudeCli, args, { stdio: 'inherit', windowsHide: true });
|
|
17
|
+
child.on('exit', (code, signal) => {
|
|
18
|
+
if (signal) process.kill(process.pid, signal);
|
|
19
|
+
else process.exit(code || 0);
|
|
20
|
+
});
|
|
21
|
+
child.on('error', () => {
|
|
22
|
+
showClaudeNotFoundError();
|
|
23
|
+
process.exit(1);
|
|
24
|
+
});
|
|
36
25
|
}
|
|
37
26
|
|
|
38
27
|
// Special command handlers
|
|
39
28
|
function handleVersionCommand() {
|
|
40
|
-
|
|
29
|
+
// Title
|
|
30
|
+
console.log(colored(`CCS (Claude Code Switch) v${CCS_VERSION}`, 'bold'));
|
|
31
|
+
console.log('');
|
|
41
32
|
|
|
42
|
-
//
|
|
43
|
-
|
|
44
|
-
if (installLocation) {
|
|
45
|
-
console.log(`Installed at: ${installLocation}`);
|
|
46
|
-
}
|
|
33
|
+
// Installation section
|
|
34
|
+
console.log(colored('Installation:', 'cyan'));
|
|
47
35
|
|
|
48
|
-
|
|
49
|
-
process.
|
|
50
|
-
}
|
|
36
|
+
// Location
|
|
37
|
+
const installLocation = process.argv[1] || '(not found)';
|
|
38
|
+
console.log(` ${colored('Location:', 'cyan')} ${installLocation}`);
|
|
51
39
|
|
|
52
|
-
|
|
53
|
-
const
|
|
40
|
+
// Config path
|
|
41
|
+
const configPath = getConfigPath();
|
|
42
|
+
console.log(` ${colored('Config:', 'cyan')} ${configPath}`);
|
|
43
|
+
console.log('');
|
|
54
44
|
|
|
55
|
-
//
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
45
|
+
// Documentation
|
|
46
|
+
console.log(`${colored('Documentation:', 'cyan')} https://github.com/kaitranntt/ccs`);
|
|
47
|
+
console.log(`${colored('License:', 'cyan')} MIT`);
|
|
48
|
+
console.log('');
|
|
60
49
|
|
|
61
|
-
//
|
|
62
|
-
|
|
63
|
-
let claudeArgs, child;
|
|
50
|
+
// Help hint
|
|
51
|
+
console.log(colored('Run \'ccs --help\' for usage information', 'yellow'));
|
|
64
52
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
claudeArgs = [claudeCli, '--help', ...remainingArgs].map(escapeShellArg).join(' ');
|
|
68
|
-
child = spawn(claudeArgs, spawnOpts);
|
|
69
|
-
} else {
|
|
70
|
-
// When no shell needed, use arguments array directly
|
|
71
|
-
claudeArgs = ['--help', ...remainingArgs];
|
|
72
|
-
child = spawn(claudeCli, claudeArgs, spawnOpts);
|
|
73
|
-
}
|
|
53
|
+
process.exit(0);
|
|
54
|
+
}
|
|
74
55
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
56
|
+
function handleHelpCommand() {
|
|
57
|
+
// Title
|
|
58
|
+
console.log(colored('CCS (Claude Code Switch) - Instant profile switching for Claude CLI', 'bold'));
|
|
59
|
+
console.log('');
|
|
60
|
+
|
|
61
|
+
// Usage
|
|
62
|
+
console.log(colored('Usage:', 'cyan'));
|
|
63
|
+
console.log(` ${colored('ccs', 'yellow')} [profile] [claude-args...]`);
|
|
64
|
+
console.log(` ${colored('ccs', 'yellow')} [flags]`);
|
|
65
|
+
console.log('');
|
|
66
|
+
|
|
67
|
+
// Description
|
|
68
|
+
console.log(colored('Description:', 'cyan'));
|
|
69
|
+
console.log(' Switch between Claude models instantly. Stop hitting rate limits.');
|
|
70
|
+
console.log(' Maps profile names to Claude settings files via ~/.ccs/config.json');
|
|
71
|
+
console.log('');
|
|
72
|
+
|
|
73
|
+
// Profile Switching
|
|
74
|
+
console.log(colored('Profile Switching:', 'cyan'));
|
|
75
|
+
console.log(` ${colored('ccs', 'yellow')} Use default profile`);
|
|
76
|
+
console.log(` ${colored('ccs glm', 'yellow')} Switch to GLM profile`);
|
|
77
|
+
console.log(` ${colored('ccs glm', 'yellow')} "debug this code" Switch to GLM and run command`);
|
|
78
|
+
console.log(` ${colored('ccs glm', 'yellow')} --verbose Switch to GLM with Claude flags`);
|
|
79
|
+
console.log('');
|
|
80
|
+
|
|
81
|
+
// Flags
|
|
82
|
+
console.log(colored('Flags:', 'cyan'));
|
|
83
|
+
console.log(` ${colored('-h, --help', 'yellow')} Show this help message`);
|
|
84
|
+
console.log(` ${colored('-v, --version', 'yellow')} Show version and installation info`);
|
|
85
|
+
console.log('');
|
|
86
|
+
|
|
87
|
+
// Configuration
|
|
88
|
+
console.log(colored('Configuration:', 'cyan'));
|
|
89
|
+
console.log(' Config File: ~/.ccs/config.json');
|
|
90
|
+
console.log(' Settings: ~/.ccs/*.settings.json');
|
|
91
|
+
console.log(' Environment: CCS_CONFIG (override config path)');
|
|
92
|
+
console.log('');
|
|
93
|
+
|
|
94
|
+
// Examples
|
|
95
|
+
console.log(colored('Examples:', 'cyan'));
|
|
96
|
+
console.log(' # Try without installing');
|
|
97
|
+
console.log(` ${colored('npx @kaitranntt/ccs glm', 'yellow')} "write tests"`);
|
|
98
|
+
console.log('');
|
|
99
|
+
console.log(' # Use default Claude subscription');
|
|
100
|
+
console.log(` ${colored('ccs', 'yellow')} "Review this architecture"`);
|
|
101
|
+
console.log('');
|
|
102
|
+
console.log(' # Switch to GLM for cost-effective tasks');
|
|
103
|
+
console.log(` ${colored('ccs glm', 'yellow')} "Write unit tests"`);
|
|
104
|
+
console.log('');
|
|
105
|
+
console.log(' # Use GLM with verbose output');
|
|
106
|
+
console.log(` ${colored('ccs glm', 'yellow')} --verbose "Debug error"`);
|
|
107
|
+
console.log('');
|
|
108
|
+
|
|
109
|
+
// Uninstall
|
|
110
|
+
console.log(colored('Uninstall:', 'yellow'));
|
|
111
|
+
console.log(' npm: npm uninstall -g @kaitranntt/ccs');
|
|
112
|
+
console.log(' macOS/Linux: curl -fsSL ccs.kaitran.ca/uninstall | bash');
|
|
113
|
+
console.log(' Windows: irm ccs.kaitran.ca/uninstall | iex');
|
|
114
|
+
console.log('');
|
|
115
|
+
|
|
116
|
+
// Documentation
|
|
117
|
+
console.log(colored('Documentation:', 'cyan'));
|
|
118
|
+
console.log(` GitHub: ${colored('https://github.com/kaitranntt/ccs', 'cyan')}`);
|
|
119
|
+
console.log(' Docs: https://github.com/kaitranntt/ccs/blob/main/README.md');
|
|
120
|
+
console.log(' Issues: https://github.com/kaitranntt/ccs/issues');
|
|
121
|
+
console.log('');
|
|
122
|
+
|
|
123
|
+
// License
|
|
124
|
+
console.log(`${colored('License:', 'cyan')} MIT`);
|
|
82
125
|
|
|
83
|
-
|
|
84
|
-
showClaudeNotFoundError();
|
|
85
|
-
process.exit(1);
|
|
86
|
-
});
|
|
126
|
+
process.exit(0);
|
|
87
127
|
}
|
|
88
128
|
|
|
89
129
|
function handleInstallCommand() {
|
|
90
|
-
|
|
91
|
-
console.log('
|
|
92
|
-
console.log('
|
|
93
|
-
console.log('
|
|
94
|
-
console.log(
|
|
95
|
-
|
|
96
|
-
|
|
130
|
+
console.log('');
|
|
131
|
+
console.log('Feature not available');
|
|
132
|
+
console.log('');
|
|
133
|
+
console.log('The --install flag is currently under development.');
|
|
134
|
+
console.log('.claude/ integration testing is not complete.');
|
|
135
|
+
console.log('');
|
|
136
|
+
console.log('For updates: https://github.com/kaitranntt/ccs/issues');
|
|
137
|
+
console.log('');
|
|
97
138
|
process.exit(0);
|
|
98
139
|
}
|
|
99
140
|
|
|
100
141
|
function handleUninstallCommand() {
|
|
101
|
-
|
|
102
|
-
console.log('
|
|
103
|
-
console.log('
|
|
104
|
-
console.log('
|
|
142
|
+
console.log('');
|
|
143
|
+
console.log('Feature not available');
|
|
144
|
+
console.log('');
|
|
145
|
+
console.log('The --uninstall flag is currently under development.');
|
|
146
|
+
console.log('.claude/ integration testing is not complete.');
|
|
147
|
+
console.log('');
|
|
148
|
+
console.log('For updates: https://github.com/kaitranntt/ccs/issues');
|
|
149
|
+
console.log('');
|
|
105
150
|
process.exit(0);
|
|
106
151
|
}
|
|
107
152
|
|
|
@@ -128,8 +173,7 @@ function main() {
|
|
|
128
173
|
|
|
129
174
|
// Special case: help command
|
|
130
175
|
if (firstArg === '--help' || firstArg === '-h' || firstArg === 'help') {
|
|
131
|
-
|
|
132
|
-
handleHelpCommand(remainingArgs);
|
|
176
|
+
handleHelpCommand();
|
|
133
177
|
return;
|
|
134
178
|
}
|
|
135
179
|
|
|
@@ -151,40 +195,12 @@ function main() {
|
|
|
151
195
|
// Special case: "default" profile just runs claude directly
|
|
152
196
|
if (profile === 'default') {
|
|
153
197
|
const claudeCli = detectClaudeCli();
|
|
154
|
-
|
|
155
|
-
// Check if claude was found
|
|
156
198
|
if (!claudeCli) {
|
|
157
199
|
showClaudeNotFoundError();
|
|
158
200
|
process.exit(1);
|
|
159
201
|
}
|
|
160
202
|
|
|
161
|
-
|
|
162
|
-
const spawnOpts = getSpawnOptions(claudeCli);
|
|
163
|
-
let claudeArgs, child;
|
|
164
|
-
|
|
165
|
-
if (spawnOpts.shell) {
|
|
166
|
-
// When shell is required, escape arguments properly
|
|
167
|
-
claudeArgs = [claudeCli, ...remainingArgs].map(escapeShellArg).join(' ');
|
|
168
|
-
child = spawn(claudeArgs, spawnOpts);
|
|
169
|
-
} else {
|
|
170
|
-
// When no shell needed, use arguments array directly
|
|
171
|
-
claudeArgs = remainingArgs;
|
|
172
|
-
child = spawn(claudeCli, claudeArgs, spawnOpts);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
child.on('exit', (code, signal) => {
|
|
176
|
-
if (signal) {
|
|
177
|
-
process.kill(process.pid, signal);
|
|
178
|
-
} else {
|
|
179
|
-
process.exit(code || 0);
|
|
180
|
-
}
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
child.on('error', (err) => {
|
|
184
|
-
showClaudeNotFoundError();
|
|
185
|
-
process.exit(1);
|
|
186
|
-
});
|
|
187
|
-
|
|
203
|
+
execClaude(claudeCli, remainingArgs);
|
|
188
204
|
return;
|
|
189
205
|
}
|
|
190
206
|
|
|
@@ -201,32 +217,7 @@ function main() {
|
|
|
201
217
|
}
|
|
202
218
|
|
|
203
219
|
// Execute claude with --settings
|
|
204
|
-
|
|
205
|
-
const spawnOpts = getSpawnOptions(claudeCli);
|
|
206
|
-
let claudeArgs, child;
|
|
207
|
-
|
|
208
|
-
if (spawnOpts.shell) {
|
|
209
|
-
// When shell is required, escape arguments properly
|
|
210
|
-
claudeArgs = [claudeCli, ...claudeArgsList].map(escapeShellArg).join(' ');
|
|
211
|
-
child = spawn(claudeArgs, spawnOpts);
|
|
212
|
-
} else {
|
|
213
|
-
// When no shell needed, use arguments array directly
|
|
214
|
-
claudeArgs = claudeArgsList;
|
|
215
|
-
child = spawn(claudeCli, claudeArgs, spawnOpts);
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
child.on('exit', (code, signal) => {
|
|
219
|
-
if (signal) {
|
|
220
|
-
process.kill(process.pid, signal);
|
|
221
|
-
} else {
|
|
222
|
-
process.exit(code || 0);
|
|
223
|
-
}
|
|
224
|
-
});
|
|
225
|
-
|
|
226
|
-
child.on('error', (err) => {
|
|
227
|
-
showClaudeNotFoundError();
|
|
228
|
-
process.exit(1);
|
|
229
|
-
});
|
|
220
|
+
execClaude(claudeCli, ['--settings', settingsPath, ...remainingArgs]);
|
|
230
221
|
}
|
|
231
222
|
|
|
232
223
|
// Run main
|
package/bin/claude-detector.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const { execSync } = require('child_process');
|
|
5
|
-
const {
|
|
5
|
+
const { expandPath } = require('./helpers');
|
|
6
6
|
|
|
7
7
|
// Detect Claude CLI executable
|
|
8
8
|
function detectClaudeCli() {
|
|
@@ -60,40 +60,11 @@ function detectClaudeCli() {
|
|
|
60
60
|
return null;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
// Show Claude not found error
|
|
63
|
+
// Show Claude not found error
|
|
64
64
|
function showClaudeNotFoundError() {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
const errorMsg = `Claude CLI not found in PATH
|
|
69
|
-
|
|
70
|
-
CCS requires Claude CLI to be installed and available in your PATH.
|
|
71
|
-
|
|
72
|
-
[i] Diagnostic Info:
|
|
73
|
-
Platform: ${process.platform}
|
|
74
|
-
PATH directories: ${pathDirs.length}
|
|
75
|
-
Looking for: claude${isWindows ? '.exe' : ''}
|
|
76
|
-
|
|
77
|
-
Solutions:
|
|
78
|
-
1. Install Claude CLI:
|
|
79
|
-
https://docs.claude.com/en/docs/claude-code/installation
|
|
80
|
-
|
|
81
|
-
2. Verify installation:
|
|
82
|
-
${isWindows ? 'Get-Command claude' : 'command -v claude'}
|
|
83
|
-
|
|
84
|
-
3. If installed but not in PATH, add it:
|
|
85
|
-
# Find Claude installation
|
|
86
|
-
${isWindows ? 'where.exe claude' : 'which claude'}
|
|
87
|
-
|
|
88
|
-
# Or set custom path
|
|
89
|
-
${isWindows
|
|
90
|
-
? '$env:CCS_CLAUDE_PATH = \'C:\\path\\to\\claude.exe\''
|
|
91
|
-
: 'export CCS_CLAUDE_PATH=\'/path/to/claude\''
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
Restart your terminal after installation.`;
|
|
95
|
-
|
|
96
|
-
showError(errorMsg);
|
|
65
|
+
console.error('ERROR: Claude CLI not found in PATH');
|
|
66
|
+
console.error('Install from: https://docs.claude.com/en/docs/claude-code/installation');
|
|
67
|
+
process.exit(1);
|
|
97
68
|
}
|
|
98
69
|
|
|
99
70
|
module.exports = {
|
package/bin/config-manager.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const os = require('os');
|
|
6
|
-
const {
|
|
6
|
+
const { error, expandPath } = require('./helpers');
|
|
7
7
|
|
|
8
8
|
// Get config file path
|
|
9
9
|
function getConfigPath() {
|
|
@@ -16,30 +16,7 @@ function readConfig() {
|
|
|
16
16
|
|
|
17
17
|
// Check config exists
|
|
18
18
|
if (!fs.existsSync(configPath)) {
|
|
19
|
-
|
|
20
|
-
showError(`Config file not found: ${configPath}
|
|
21
|
-
|
|
22
|
-
Solutions:
|
|
23
|
-
1. Reinstall CCS (auto-creates config):
|
|
24
|
-
npm install -g @kaitranntt/ccs --force
|
|
25
|
-
|
|
26
|
-
2. Or use traditional installer:
|
|
27
|
-
${isWindows ? 'irm ccs.kaitran.ca/install | iex' : 'curl -fsSL ccs.kaitran.ca/install | bash'}
|
|
28
|
-
|
|
29
|
-
3. Or create manually:
|
|
30
|
-
mkdir -p ~/.ccs
|
|
31
|
-
cat > ~/.ccs/config.json << 'EOF'
|
|
32
|
-
{
|
|
33
|
-
"profiles": {
|
|
34
|
-
"glm": "~/.ccs/glm.settings.json",
|
|
35
|
-
"default": "~/.claude/settings.json"
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
EOF
|
|
39
|
-
|
|
40
|
-
Note: If you installed with npm --ignore-scripts, configs weren't created.
|
|
41
|
-
Reinstall without that flag: npm install -g @kaitranntt/ccs --force`);
|
|
42
|
-
process.exit(1);
|
|
19
|
+
error(`Config file not found: ${configPath}`);
|
|
43
20
|
}
|
|
44
21
|
|
|
45
22
|
// Read and parse JSON
|
|
@@ -48,23 +25,12 @@ EOF
|
|
|
48
25
|
const configContent = fs.readFileSync(configPath, 'utf8');
|
|
49
26
|
config = JSON.parse(configContent);
|
|
50
27
|
} catch (e) {
|
|
51
|
-
|
|
52
|
-
showError(`Invalid JSON in ${configPath}
|
|
53
|
-
|
|
54
|
-
Fix the JSON syntax or reinstall:
|
|
55
|
-
${isWindows ? 'irm ccs.kaitran.ca/install | iex' : 'curl -fsSL ccs.kaitran.ca/install | bash'}`);
|
|
56
|
-
process.exit(1);
|
|
28
|
+
error(`Invalid JSON in ${configPath}: ${e.message}`);
|
|
57
29
|
}
|
|
58
30
|
|
|
59
31
|
// Validate config has profiles object
|
|
60
32
|
if (!config.profiles || typeof config.profiles !== 'object') {
|
|
61
|
-
|
|
62
|
-
showError(`Config must have 'profiles' object
|
|
63
|
-
|
|
64
|
-
See config.example.json for correct format
|
|
65
|
-
Or reinstall:
|
|
66
|
-
${isWindows ? 'irm ccs.kaitran.ca/install | iex' : 'curl -fsSL ccs.kaitran.ca/install | bash'}`);
|
|
67
|
-
process.exit(1);
|
|
33
|
+
error(`Config must have 'profiles' object in ${configPath}`);
|
|
68
34
|
}
|
|
69
35
|
|
|
70
36
|
return config;
|
|
@@ -74,24 +40,12 @@ Or reinstall:
|
|
|
74
40
|
function getSettingsPath(profile) {
|
|
75
41
|
const config = readConfig();
|
|
76
42
|
|
|
77
|
-
// Validate profile name
|
|
78
|
-
if (!validateProfileName(profile)) {
|
|
79
|
-
showError(`Invalid profile name: ${profile}
|
|
80
|
-
|
|
81
|
-
Use only alphanumeric characters, dash, or underscore.`);
|
|
82
|
-
process.exit(1);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
43
|
// Get settings path
|
|
86
44
|
const settingsPath = config.profiles[profile];
|
|
87
45
|
|
|
88
46
|
if (!settingsPath) {
|
|
89
|
-
const availableProfiles = Object.keys(config.profiles).
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
Available profiles:
|
|
93
|
-
${availableProfiles}`);
|
|
94
|
-
process.exit(1);
|
|
47
|
+
const availableProfiles = Object.keys(config.profiles).join(', ');
|
|
48
|
+
error(`Profile '${profile}' not found. Available: ${availableProfiles}`);
|
|
95
49
|
}
|
|
96
50
|
|
|
97
51
|
// Expand path
|
|
@@ -99,14 +53,7 @@ ${availableProfiles}`);
|
|
|
99
53
|
|
|
100
54
|
// Validate settings file exists
|
|
101
55
|
if (!fs.existsSync(expandedPath)) {
|
|
102
|
-
|
|
103
|
-
showError(`Settings file not found: ${expandedPath}
|
|
104
|
-
|
|
105
|
-
Solutions:
|
|
106
|
-
1. Create the settings file for profile '${profile}'
|
|
107
|
-
2. Update the path in ${getConfigPath()}
|
|
108
|
-
3. Or reinstall: ${isWindows ? 'irm ccs.kaitran.ca/install | iex' : 'curl -fsSL ccs.kaitran.ca/install | bash'}`);
|
|
109
|
-
process.exit(1);
|
|
56
|
+
error(`Settings file not found: ${expandedPath}`);
|
|
110
57
|
}
|
|
111
58
|
|
|
112
59
|
// Validate settings file is valid JSON
|
|
@@ -114,15 +61,7 @@ Solutions:
|
|
|
114
61
|
const settingsContent = fs.readFileSync(expandedPath, 'utf8');
|
|
115
62
|
JSON.parse(settingsContent);
|
|
116
63
|
} catch (e) {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
Details: ${e.message}
|
|
120
|
-
|
|
121
|
-
Solutions:
|
|
122
|
-
1. Validate JSON at https://jsonlint.com
|
|
123
|
-
2. Or reset to template: echo '{"env":{}}' > ${expandedPath}
|
|
124
|
-
3. Or reinstall CCS`);
|
|
125
|
-
process.exit(1);
|
|
64
|
+
error(`Invalid JSON in ${expandedPath}: ${e.message}`);
|
|
126
65
|
}
|
|
127
66
|
|
|
128
67
|
return expandedPath;
|