@kaitranntt/ccs 2.4.3 → 2.4.5

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
@@ -11,7 +11,7 @@ Switch between Claude Sonnet 4.5 and GLM 4.6 instantly. Stop hitting rate limits
11
11
 
12
12
  [![License](https://img.shields.io/badge/license-MIT-C15F3C?style=for-the-badge)](LICENSE)
13
13
  [![Platform](https://img.shields.io/badge/platform-macOS%20%7C%20Linux%20%7C%20Windows-lightgrey?style=for-the-badge)]()
14
- [![npm](https://img.shields.io/npm/v/@kai/ccs?style=for-the-badge&logo=npm)](https://www.npmjs.com/package/@kai/ccs)
14
+ [![npm](https://img.shields.io/npm/v/@kaitranntt/ccs?style=for-the-badge&logo=npm)](https://www.npmjs.com/package/@kaitranntt/ccs)
15
15
  [![PoweredBy](https://img.shields.io/badge/PoweredBy-ClaudeKit-C15F3C?style=for-the-badge)](https://claudekit.cc?ref=HMNKXOHN)
16
16
 
17
17
  **Languages**: [English](README.md) | [Tiếng Việt](README.vi.md)
@@ -35,7 +35,7 @@ claude /login
35
35
 
36
36
  **macOS / Linux / Windows**
37
37
  ```bash
38
- npm install -g @kai/ccs
38
+ npm install -g @kaitranntt/ccs
39
39
  ```
40
40
 
41
41
  Compatible with npm, yarn, pnpm, and bun package managers.
@@ -73,20 +73,22 @@ All major package managers are supported:
73
73
 
74
74
  ```bash
75
75
  # npm (default)
76
- npm install -g @kai/ccs
76
+ npm install -g @kaitranntt/ccs
77
77
 
78
78
  # yarn
79
- yarn global add @kai/ccs
79
+ yarn global add @kaitranntt/ccs
80
80
 
81
81
  # pnpm (70% less disk space)
82
- pnpm add -g @kai/ccs
82
+ pnpm add -g @kaitranntt/ccs
83
83
 
84
84
  # bun (30x faster)
85
- bun add -g @kai/ccs
85
+ bun add -g @kaitranntt/ccs
86
86
  ```
87
87
 
88
88
  ### Configuration (Auto-created)
89
89
 
90
+ **CCS automatically creates configuration during installation** (via npm postinstall script).
91
+
90
92
  **~/.ccs/config.json**:
91
93
  ```json
92
94
  {
@@ -106,7 +108,7 @@ export CCS_CLAUDE_PATH="/path/to/claude" # Unix
106
108
  $env:CCS_CLAUDE_PATH = "D:\Tools\Claude\claude.exe" # Windows
107
109
  ```
108
110
 
109
- **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.**
110
112
 
111
113
  ---
112
114
 
@@ -233,7 +235,9 @@ ccs --uninstall # Remove CCS commands and skills from ~/.claude/
233
235
 
234
236
  ---
235
237
 
236
- ### 🗑️ Uninstall
238
+ ### 🗑️ Official Uninstall
239
+
240
+ **The recommended way to completely remove CCS:**
237
241
 
238
242
  **macOS / Linux**:
239
243
  ```bash
@@ -245,6 +249,16 @@ curl -fsSL ccs.kaitran.ca/uninstall | bash
245
249
  irm ccs.kaitran.ca/uninstall | iex
246
250
  ```
247
251
 
252
+ > 💡 **Why use the official uninstaller?**
253
+ > - Removes all CCS files and configurations
254
+ > - Cleans up PATH modifications
255
+ > - Removes Claude CLI commands/skills
256
+ > - Handles edge cases we've tested
257
+
258
+ **Alternative methods** (if official uninstaller fails):
259
+ - **npm**: `npm uninstall -g @kaitranntt/ccs`
260
+ - **Manual**: See [troubleshooting guide](./docs/en/troubleshooting.md#manual-uninstall)
261
+
248
262
  ---
249
263
 
250
264
  ## 🎯 Philosophy
@@ -258,17 +272,17 @@ irm ccs.kaitran.ca/uninstall | iex
258
272
  ## 📖 Documentation
259
273
 
260
274
  **Complete documentation in [docs/](./docs/)**:
261
- - [Installation Guide](./docs/installation.md)
262
- - [Configuration](./docs/configuration.md)
263
- - [Usage Examples](./docs/usage.md)
264
- - [Troubleshooting](./docs/troubleshooting.md)
265
- - [Contributing](./docs/contributing.md)
275
+ - [Installation Guide](./docs/en/installation.md)
276
+ - [Configuration](./docs/en/configuration.md)
277
+ - [Usage Examples](./docs/en/usage.md)
278
+ - [Troubleshooting](./docs/en/troubleshooting.md)
279
+ - [Contributing](./docs/en/contributing.md)
266
280
 
267
281
  ---
268
282
 
269
283
  ## 🤝 Contributing
270
284
 
271
- We welcome contributions! Please see our [Contributing Guide](./docs/contributing.md) for details.
285
+ We welcome contributions! Please see our [Contributing Guide](./docs/en/contributing.md) for details.
272
286
 
273
287
  ---
274
288
 
@@ -282,6 +296,6 @@ CCS is licensed under the [MIT License](LICENSE).
282
296
 
283
297
  **Made with ❤️ for developers who hit rate limits too often**
284
298
 
285
- [⭐ Star this repo](https://github.com/kaitranntt/ccs) | [🐛 Report issues](https://github.com/kaitranntt/ccs/issues) | [📖 Read docs](./docs/)
299
+ [⭐ Star this repo](https://github.com/kaitranntt/ccs) | [🐛 Report issues](https://github.com/kaitranntt/ccs/issues) | [📖 Read docs](./docs/en/)
286
300
 
287
301
  </div>
package/README.vi.md CHANGED
@@ -30,6 +30,17 @@ claude /login
30
30
 
31
31
  ### Phương Pháp Cài Đặt Chính
32
32
 
33
+ #### Option 1: npm Package (Được khuyến nghị)
34
+
35
+ **macOS / Linux / Windows**
36
+ ```bash
37
+ npm install -g @kaitranntt/ccs
38
+ ```
39
+
40
+ Tương thích với các trình quản lý package npm, yarn, pnpm, và bun.
41
+
42
+ #### Option 2: Cài Đặt Trực Tiếp (Truyền thống)
43
+
33
44
  **macOS / Linux**
34
45
  ```bash
35
46
  curl -fsSL ccs.kaitran.ca/install | bash
@@ -55,8 +66,28 @@ ccs "Debug issue này"
55
66
  ccs "Viết unit tests"
56
67
  ```
57
68
 
69
+ #### Package Manager Options
70
+
71
+ Tất cả các trình quản lý package chính đều được hỗ trợ:
72
+
73
+ ```bash
74
+ # npm (mặc định)
75
+ npm install -g @kaitranntt/ccs
76
+
77
+ # yarn
78
+ yarn global add @kaitranntt/ccs
79
+
80
+ # pnpm (ít hơn 70% dung lượng đĩa)
81
+ pnpm add -g @kaitranntt/ccs
82
+
83
+ # bun (nhanh hơn 30x)
84
+ bun add -g @kaitranntt/ccs
85
+ ```
86
+
58
87
  ### Cấu Hình (Tự Tạo)
59
88
 
89
+ **CCS tự động tạo cấu hình trong quá trình cài đặt** (thông qua script postinstall của npm).
90
+
60
91
  **~/.ccs/config.json**:
61
92
  ```json
62
93
  {
@@ -203,7 +234,9 @@ ccs --uninstall # Gỡ bỏ lệnh và kỹ năng CCS khỏi ~/.claude/
203
234
 
204
235
  ---
205
236
 
206
- ### 🗑️ Gỡ Cài Đặt
237
+ ### 🗑️ Gỡ Cài Đặt Chính Thức
238
+
239
+ **Cách được khuyến nghị để gỡ bỏ hoàn toàn CCS:**
207
240
 
208
241
  **macOS / Linux**:
209
242
  ```bash
@@ -215,6 +248,16 @@ curl -fsSL ccs.kaitran.ca/uninstall | bash
215
248
  irm ccs.kaitran.ca/uninstall | iex
216
249
  ```
217
250
 
251
+ > 💡 **Tại sao dùng uninstaller chính thức?**
252
+ > - Gỡ bỏ tất cả file và cấu hình CCS
253
+ > - Dọn dẹp PATH modifications
254
+ > - Gỡ bỏ commands/skills Claude CLI
255
+ > - Xử lý các trường hợp đặc biệt đã test
256
+
257
+ **Phương pháp thay thế** (nếu uninstaller chính thức thất bại):
258
+ - **npm**: `npm uninstall -g @kaitranntt/ccs`
259
+ - **Thủ công**: Xem [hướng dẫn khắc phục](./docs/vi/troubleshooting.vi.md#gỡ-cài-đặt-thủ-công)
260
+
218
261
  ---
219
262
 
220
263
  ## 🎯 Triết Lý
@@ -228,17 +271,17 @@ irm ccs.kaitran.ca/uninstall | iex
228
271
  ## 📖 Tài Liệu
229
272
 
230
273
  **Tài liệu đầy đủ trong [docs/](./docs/)**:
231
- - [Hướng dẫn Cài đặt](./docs/vi/installation.vi.md)
232
- - [Cấu hình](./docs/vi/configuration.vi.md)
233
- - [Ví dụ Sử dụng](./docs/vi/usage.vi.md)
234
- - [Khắc phục Sự cố](./docs/vi/troubleshooting.vi.md)
235
- - [Đóng góp](./docs/vi/contributing.vi.md)
274
+ - [Hướng dẫn Cài đặt](./docs/installation.md)
275
+ - [Cấu hình](./docs/configuration.md)
276
+ - [Ví dụ Sử dụng](./docs/usage.md)
277
+ - [Khắc phục Sự cố](./docs/troubleshooting.md)
278
+ - [Đóng góp](./docs/contributing.md)
236
279
 
237
280
  ---
238
281
 
239
282
  ## 🤝 Đóng Góp
240
283
 
241
- Chúng tôi chào mừng đóng góp! Xem [Hướng dẫn Đóng góp](./docs/contributing.md) để biết chi tiết.
284
+ Chúng tôi chào mừng đóng góp! Vui lòng xem [Hướng dẫn Đóng góp](./docs/contributing.md) để biết chi tiết.
242
285
 
243
286
  ---
244
287
 
package/VERSION CHANGED
@@ -1 +1 @@
1
- 2.4.3
1
+ 2.4.5
package/bin/ccs.js CHANGED
@@ -4,35 +4,24 @@
4
4
  const { spawn } = require('child_process');
5
5
  const path = require('path');
6
6
  const fs = require('fs');
7
- const { showError, colors } = require('./helpers');
7
+ const { error } = require('./helpers');
8
8
  const { detectClaudeCli, showClaudeNotFoundError } = require('./claude-detector');
9
9
  const { getSettingsPath } = require('./config-manager');
10
10
 
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,
23
- windowsHide: true // Hide the console window on Windows
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
@@ -51,39 +40,12 @@ function handleVersionCommand() {
51
40
 
52
41
  function handleHelpCommand(remainingArgs) {
53
42
  const claudeCli = detectClaudeCli();
54
-
55
- // Check if claude was found
56
43
  if (!claudeCli) {
57
44
  showClaudeNotFoundError();
58
45
  process.exit(1);
59
46
  }
60
47
 
61
- // Execute claude --help
62
- const spawnOpts = getSpawnOptions(claudeCli);
63
- let claudeArgs, child;
64
-
65
- if (spawnOpts.shell) {
66
- // When shell is required, escape arguments properly
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
- }
74
-
75
- child.on('exit', (code, signal) => {
76
- if (signal) {
77
- process.kill(process.pid, signal);
78
- } else {
79
- process.exit(code || 0);
80
- }
81
- });
82
-
83
- child.on('error', (err) => {
84
- showClaudeNotFoundError();
85
- process.exit(1);
86
- });
48
+ execClaude(claudeCli, ['--help', ...remainingArgs]);
87
49
  }
88
50
 
89
51
  function handleInstallCommand() {
@@ -91,9 +53,7 @@ function handleInstallCommand() {
91
53
  console.log('[Installing CCS Commands and Skills]');
92
54
  console.log('Feature not yet implemented in Node.js standalone');
93
55
  console.log('Use traditional installer for now:');
94
- console.log(process.platform === 'win32'
95
- ? ' irm ccs.kaitran.ca/install | iex'
96
- : ' curl -fsSL ccs.kaitran.ca/install | bash');
56
+ console.log(' curl -fsSL ccs.kaitran.ca/install | bash');
97
57
  process.exit(0);
98
58
  }
99
59
 
@@ -151,40 +111,12 @@ function main() {
151
111
  // Special case: "default" profile just runs claude directly
152
112
  if (profile === 'default') {
153
113
  const claudeCli = detectClaudeCli();
154
-
155
- // Check if claude was found
156
114
  if (!claudeCli) {
157
115
  showClaudeNotFoundError();
158
116
  process.exit(1);
159
117
  }
160
118
 
161
- // Execute claude with args
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
-
119
+ execClaude(claudeCli, remainingArgs);
188
120
  return;
189
121
  }
190
122
 
@@ -201,32 +133,7 @@ function main() {
201
133
  }
202
134
 
203
135
  // Execute claude with --settings
204
- const claudeArgsList = ['--settings', settingsPath, ...remainingArgs];
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
- });
136
+ execClaude(claudeCli, ['--settings', settingsPath, ...remainingArgs]);
230
137
  }
231
138
 
232
139
  // Run main
@@ -2,7 +2,7 @@
2
2
 
3
3
  const fs = require('fs');
4
4
  const { execSync } = require('child_process');
5
- const { showError, expandPath } = require('./helpers');
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 with diagnostics
63
+ // Show Claude not found error
64
64
  function showClaudeNotFoundError() {
65
- const isWindows = process.platform === 'win32';
66
- const pathDirs = (process.env.PATH || '').split(isWindows ? ';' : ':');
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 = {
@@ -3,7 +3,7 @@
3
3
  const fs = require('fs');
4
4
  const path = require('path');
5
5
  const os = require('os');
6
- const { showError, expandPath, validateProfileName } = require('./helpers');
6
+ const { error, expandPath } = require('./helpers');
7
7
 
8
8
  // Get config file path
9
9
  function getConfigPath() {
@@ -16,24 +16,7 @@ function readConfig() {
16
16
 
17
17
  // Check config exists
18
18
  if (!fs.existsSync(configPath)) {
19
- const isWindows = process.platform === 'win32';
20
- showError(`Config file not found: ${configPath}
21
-
22
- Solutions:
23
- 1. Reinstall CCS:
24
- ${isWindows ? 'irm ccs.kaitran.ca/install | iex' : 'curl -fsSL ccs.kaitran.ca/install | bash'}
25
-
26
- 2. Or create config manually:
27
- mkdir -p ~/.ccs
28
- cat > ~/.ccs/config.json << 'EOF'
29
- {
30
- "profiles": {
31
- "glm": "~/.ccs/glm.settings.json",
32
- "default": "~/.claude/settings.json"
33
- }
34
- }
35
- EOF`);
36
- process.exit(1);
19
+ error(`Config file not found: ${configPath}`);
37
20
  }
38
21
 
39
22
  // Read and parse JSON
@@ -42,23 +25,12 @@ EOF`);
42
25
  const configContent = fs.readFileSync(configPath, 'utf8');
43
26
  config = JSON.parse(configContent);
44
27
  } catch (e) {
45
- const isWindows = process.platform === 'win32';
46
- showError(`Invalid JSON in ${configPath}
47
-
48
- Fix the JSON syntax or reinstall:
49
- ${isWindows ? 'irm ccs.kaitran.ca/install | iex' : 'curl -fsSL ccs.kaitran.ca/install | bash'}`);
50
- process.exit(1);
28
+ error(`Invalid JSON in ${configPath}: ${e.message}`);
51
29
  }
52
30
 
53
31
  // Validate config has profiles object
54
32
  if (!config.profiles || typeof config.profiles !== 'object') {
55
- const isWindows = process.platform === 'win32';
56
- showError(`Config must have 'profiles' object
57
-
58
- See config.example.json for correct format
59
- Or reinstall:
60
- ${isWindows ? 'irm ccs.kaitran.ca/install | iex' : 'curl -fsSL ccs.kaitran.ca/install | bash'}`);
61
- process.exit(1);
33
+ error(`Config must have 'profiles' object in ${configPath}`);
62
34
  }
63
35
 
64
36
  return config;
@@ -68,24 +40,12 @@ Or reinstall:
68
40
  function getSettingsPath(profile) {
69
41
  const config = readConfig();
70
42
 
71
- // Validate profile name
72
- if (!validateProfileName(profile)) {
73
- showError(`Invalid profile name: ${profile}
74
-
75
- Use only alphanumeric characters, dash, or underscore.`);
76
- process.exit(1);
77
- }
78
-
79
43
  // Get settings path
80
44
  const settingsPath = config.profiles[profile];
81
45
 
82
46
  if (!settingsPath) {
83
- const availableProfiles = Object.keys(config.profiles).map(p => ` - ${p}`).join('\n');
84
- showError(`Profile '${profile}' not found in ${getConfigPath()}
85
-
86
- Available profiles:
87
- ${availableProfiles}`);
88
- process.exit(1);
47
+ const availableProfiles = Object.keys(config.profiles).join(', ');
48
+ error(`Profile '${profile}' not found. Available: ${availableProfiles}`);
89
49
  }
90
50
 
91
51
  // Expand path
@@ -93,14 +53,7 @@ ${availableProfiles}`);
93
53
 
94
54
  // Validate settings file exists
95
55
  if (!fs.existsSync(expandedPath)) {
96
- const isWindows = process.platform === 'win32';
97
- showError(`Settings file not found: ${expandedPath}
98
-
99
- Solutions:
100
- 1. Create the settings file for profile '${profile}'
101
- 2. Update the path in ${getConfigPath()}
102
- 3. Or reinstall: ${isWindows ? 'irm ccs.kaitran.ca/install | iex' : 'curl -fsSL ccs.kaitran.ca/install | bash'}`);
103
- process.exit(1);
56
+ error(`Settings file not found: ${expandedPath}`);
104
57
  }
105
58
 
106
59
  // Validate settings file is valid JSON
@@ -108,15 +61,7 @@ Solutions:
108
61
  const settingsContent = fs.readFileSync(expandedPath, 'utf8');
109
62
  JSON.parse(settingsContent);
110
63
  } catch (e) {
111
- showError(`Invalid JSON in ${expandedPath}
112
-
113
- Details: ${e.message}
114
-
115
- Solutions:
116
- 1. Validate JSON at https://jsonlint.com
117
- 2. Or reset to template: echo '{"env":{}}' > ${expandedPath}
118
- 3. Or reinstall CCS`);
119
- process.exit(1);
64
+ error(`Invalid JSON in ${expandedPath}: ${e.message}`);
120
65
  }
121
66
 
122
67
  return expandedPath;
package/bin/helpers.js CHANGED
@@ -15,15 +15,11 @@ const colors = useColors ? {
15
15
  reset: '\x1b[0m'
16
16
  } : { red: '', yellow: '', cyan: '', green: '', bold: '', reset: '' };
17
17
 
18
- // Error formatting
19
- function showError(message) {
20
- console.error('');
21
- console.error(colors.red + colors.bold + '╔═════════════════════════════════════════════╗' + colors.reset);
22
- console.error(colors.red + colors.bold + '║ ERROR ║' + colors.reset);
23
- console.error(colors.red + colors.bold + '╚═════════════════════════════════════════════╝' + colors.reset);
24
- console.error('');
25
- console.error(colors.red + message + colors.reset);
26
- console.error('');
18
+ // Simple error formatting
19
+ function error(message) {
20
+ console.error(`ERROR: ${message}`);
21
+ console.error('Try: npm install -g @kaitranntt/ccs --force');
22
+ process.exit(1);
27
23
  }
28
24
 
29
25
  // Path expansion (~ and env vars)
@@ -45,21 +41,9 @@ function expandPath(pathStr) {
45
41
  return path.normalize(pathStr);
46
42
  }
47
43
 
48
- // Validate profile name (alphanumeric, dash, underscore only)
49
- function validateProfileName(profile) {
50
- return /^[a-zA-Z0-9_-]+$/.test(profile);
51
- }
52
-
53
- // Validate path safety (prevent injection)
54
- function isPathSafe(pathStr) {
55
- // Allow: alphanumeric, path separators, space, dash, underscore, dot, colon, tilde
56
- return !/[;|&<>`$*?\[\]'"()]/.test(pathStr);
57
- }
58
44
 
59
45
  module.exports = {
60
46
  colors,
61
- showError,
62
- expandPath,
63
- validateProfileName,
64
- isPathSafe
47
+ error,
48
+ expandPath
65
49
  };