@kaitranntt/ccs 4.3.4 → 4.3.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 +4 -5
- package/VERSION +1 -1
- package/bin/ccs.js +5 -0
- package/bin/utils/claude-dir-installer.js +102 -0
- package/bin/utils/claude-symlink-manager.js +1 -2
- package/lib/ccs +1 -1
- package/lib/ccs.ps1 +1 -1
- package/package.json +2 -2
- package/scripts/postinstall.js +3 -0
package/README.md
CHANGED
|
@@ -323,8 +323,7 @@ graph LR
|
|
|
323
323
|
~/.ccs/
|
|
324
324
|
├── .claude/ # CCS items (ships with package, v4.1)
|
|
325
325
|
│ ├── commands/ccs/ # Delegation commands (/ccs, /ccs:continue)
|
|
326
|
-
│
|
|
327
|
-
│ └── agents/ccs-delegator.md # Proactive delegation agent
|
|
326
|
+
│ └── skills/ccs-delegation/ # AI decision framework (replaces deprecated agents)
|
|
328
327
|
├── shared/ # Symlinks to ~/.claude/ (for profiles)
|
|
329
328
|
│ ├── agents@ → ~/.claude/agents/
|
|
330
329
|
│ ├── commands@ → ~/.claude/commands/
|
|
@@ -341,7 +340,7 @@ graph LR
|
|
|
341
340
|
~/.claude/ # User's Claude directory
|
|
342
341
|
├── commands/ccs@ → ~/.ccs/.claude/commands/ccs/ # Selective symlink
|
|
343
342
|
├── skills/ccs-delegation@ → ~/.ccs/.claude/skills/ccs-delegation/
|
|
344
|
-
|
|
343
|
+
# agents/ccs-delegator.md@ → ~/.ccs/.claude/agents/ccs-delegator.md # Deprecated in v4.3.2
|
|
345
344
|
```
|
|
346
345
|
|
|
347
346
|
**Symlink Chain**: `work profile → ~/.ccs/shared/ → ~/.claude/ → ~/.ccs/.claude/` (CCS items)
|
|
@@ -507,8 +506,8 @@ Savings: $0.0275 (86% reduction)
|
|
|
507
506
|
### Documentation
|
|
508
507
|
|
|
509
508
|
- **Workflow Diagrams**: See [docs/ccs-delegation-diagrams.md](docs/ccs-delegation-diagrams.md) for visual architecture
|
|
510
|
-
- **Skill Reference**: `.claude/skills/ccs-delegation/` for AI decision framework
|
|
511
|
-
- **Agent Docs**: `.claude/agents/ccs-delegator.md`
|
|
509
|
+
- **Skill Reference**: `.claude/skills/ccs-delegation/` for AI decision framework (replaces deprecated agents)
|
|
510
|
+
- **Agent Docs**: `.claude/agents/ccs-delegator.md` was deprecated in v4.3.2, functionality moved to ccs-delegation skill
|
|
512
511
|
|
|
513
512
|
<br>
|
|
514
513
|
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
4.3.
|
|
1
|
+
4.3.5
|
package/bin/ccs.js
CHANGED
|
@@ -286,6 +286,11 @@ async function handleSyncCommand() {
|
|
|
286
286
|
|
|
287
287
|
console.log('');
|
|
288
288
|
|
|
289
|
+
const cleanupResult = installer.cleanupDeprecated();
|
|
290
|
+
if (cleanupResult.success && cleanupResult.cleanedFiles.length > 0) {
|
|
291
|
+
console.log('');
|
|
292
|
+
}
|
|
293
|
+
|
|
289
294
|
// Then, create symlinks from ~/.ccs/.claude/ to ~/.claude/
|
|
290
295
|
const ClaudeSymlinkManager = require('./utils/claude-symlink-manager');
|
|
291
296
|
const manager = new ClaudeSymlinkManager();
|
|
@@ -148,6 +148,108 @@ class ClaudeDirInstaller {
|
|
|
148
148
|
return { files, dirs };
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
+
/**
|
|
152
|
+
* Clean up deprecated files from previous installations
|
|
153
|
+
* Removes ccs-delegator.md that was deprecated in v4.3.2
|
|
154
|
+
* @param {boolean} silent - Suppress console output
|
|
155
|
+
*/
|
|
156
|
+
cleanupDeprecated(silent = false) {
|
|
157
|
+
const deprecatedFile = path.join(this.ccsClaudeDir, 'agents', 'ccs-delegator.md');
|
|
158
|
+
const userSymlinkFile = path.join(this.homeDir, '.claude', 'agents', 'ccs-delegator.md');
|
|
159
|
+
const migrationMarker = path.join(this.homeDir, '.ccs', '.migrations', 'v435-delegator-cleanup');
|
|
160
|
+
|
|
161
|
+
let cleanedFiles = [];
|
|
162
|
+
|
|
163
|
+
try {
|
|
164
|
+
// Check if cleanup already done
|
|
165
|
+
if (fs.existsSync(migrationMarker)) {
|
|
166
|
+
return { success: true, cleanedFiles: [] }; // Already cleaned
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Clean up user symlink in ~/.claude/agents/ccs-delegator.md FIRST
|
|
170
|
+
// This ensures we can detect broken symlinks before deleting the target
|
|
171
|
+
try {
|
|
172
|
+
const userStats = fs.lstatSync(userSymlinkFile);
|
|
173
|
+
if (userStats.isSymbolicLink()) {
|
|
174
|
+
fs.unlinkSync(userSymlinkFile);
|
|
175
|
+
cleanedFiles.push('user symlink');
|
|
176
|
+
} else {
|
|
177
|
+
// It's not a symlink (user created their own file), backup it
|
|
178
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-').split('T')[0];
|
|
179
|
+
const backupPath = `${userSymlinkFile}.backup-${timestamp}`;
|
|
180
|
+
fs.renameSync(userSymlinkFile, backupPath);
|
|
181
|
+
if (!silent) console.log(`[i] Backed up user file to ${path.basename(backupPath)}`);
|
|
182
|
+
cleanedFiles.push('user file (backed up)');
|
|
183
|
+
}
|
|
184
|
+
} catch (err) {
|
|
185
|
+
// File doesn't exist or other error - that's okay
|
|
186
|
+
if (err.code !== 'ENOENT' && !silent) {
|
|
187
|
+
console.log(`[!] Failed to remove user symlink: ${err.message}`);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Clean up package copy in ~/.ccs/.claude/agents/ccs-delegator.md
|
|
192
|
+
if (fs.existsSync(deprecatedFile)) {
|
|
193
|
+
try {
|
|
194
|
+
// Check if file was modified by user (compare with expected content)
|
|
195
|
+
const shouldBackup = this._shouldBackupDeprecatedFile(deprecatedFile);
|
|
196
|
+
|
|
197
|
+
if (shouldBackup) {
|
|
198
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-').split('T')[0];
|
|
199
|
+
const backupPath = `${deprecatedFile}.backup-${timestamp}`;
|
|
200
|
+
fs.renameSync(deprecatedFile, backupPath);
|
|
201
|
+
if (!silent) console.log(`[i] Backed up modified deprecated file to ${path.basename(backupPath)}`);
|
|
202
|
+
} else {
|
|
203
|
+
fs.rmSync(deprecatedFile, { force: true });
|
|
204
|
+
}
|
|
205
|
+
cleanedFiles.push('package copy');
|
|
206
|
+
} catch (err) {
|
|
207
|
+
if (!silent) console.log(`[!] Failed to remove package copy: ${err.message}`);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Create migration marker
|
|
212
|
+
if (cleanedFiles.length > 0) {
|
|
213
|
+
const migrationsDir = path.dirname(migrationMarker);
|
|
214
|
+
if (!fs.existsSync(migrationsDir)) {
|
|
215
|
+
fs.mkdirSync(migrationsDir, { recursive: true, mode: 0o700 });
|
|
216
|
+
}
|
|
217
|
+
fs.writeFileSync(migrationMarker, new Date().toISOString());
|
|
218
|
+
|
|
219
|
+
if (!silent) {
|
|
220
|
+
console.log(`[OK] Cleaned up deprecated agent files: ${cleanedFiles.join(', ')}`);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return { success: true, cleanedFiles };
|
|
225
|
+
} catch (err) {
|
|
226
|
+
if (!silent) console.log(`[!] Cleanup failed: ${err.message}`);
|
|
227
|
+
return { success: false, error: err.message, cleanedFiles };
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Check if deprecated file should be backed up (user modified)
|
|
233
|
+
* @param {string} filePath - Path to check
|
|
234
|
+
* @returns {boolean} True if file should be backed up
|
|
235
|
+
* @private
|
|
236
|
+
*/
|
|
237
|
+
_shouldBackupDeprecatedFile(filePath) {
|
|
238
|
+
try {
|
|
239
|
+
// Simple heuristic: if file size differs significantly from expected, assume user modified
|
|
240
|
+
// Expected size for ccs-delegator.md was around 2-3KB
|
|
241
|
+
const stats = fs.statSync(filePath);
|
|
242
|
+
const expectedMinSize = 1000; // 1KB minimum
|
|
243
|
+
const expectedMaxSize = 10000; // 10KB maximum
|
|
244
|
+
|
|
245
|
+
// If size is outside expected range, likely user modified
|
|
246
|
+
return stats.size < expectedMinSize || stats.size > expectedMaxSize;
|
|
247
|
+
} catch (err) {
|
|
248
|
+
// If we can't determine, err on side of caution and backup
|
|
249
|
+
return true;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
151
253
|
/**
|
|
152
254
|
* Check if ~/.ccs/.claude/ exists and is valid
|
|
153
255
|
* @returns {boolean} True if directory exists
|
|
@@ -28,8 +28,7 @@ class ClaudeSymlinkManager {
|
|
|
28
28
|
// CCS items to symlink (selective, item-level)
|
|
29
29
|
this.ccsItems = [
|
|
30
30
|
{ source: 'commands/ccs', target: 'commands/ccs', type: 'directory' },
|
|
31
|
-
{ source: 'skills/ccs-delegation', target: 'skills/ccs-delegation', type: 'directory' }
|
|
32
|
-
{ source: 'agents/ccs-delegator.md', target: 'agents/ccs-delegator.md', type: 'file' }
|
|
31
|
+
{ source: 'skills/ccs-delegation', target: 'skills/ccs-delegation', type: 'directory' }
|
|
33
32
|
];
|
|
34
33
|
}
|
|
35
34
|
|
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="4.3.
|
|
5
|
+
CCS_VERSION="4.3.5"
|
|
6
6
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
7
7
|
readonly CONFIG_FILE="${CCS_CONFIG:-$HOME/.ccs/config.json}"
|
|
8
8
|
readonly PROFILES_JSON="$HOME/.ccs/profiles.json"
|
package/lib/ccs.ps1
CHANGED
|
@@ -12,7 +12,7 @@ param(
|
|
|
12
12
|
$ErrorActionPreference = "Stop"
|
|
13
13
|
|
|
14
14
|
# Version (updated by scripts/bump-version.sh)
|
|
15
|
-
$CcsVersion = "4.3.
|
|
15
|
+
$CcsVersion = "4.3.5"
|
|
16
16
|
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
17
17
|
$ConfigFile = if ($env:CCS_CONFIG) { $env:CCS_CONFIG } else { "$env:USERPROFILE\.ccs\config.json" }
|
|
18
18
|
$ProfilesJson = "$env:USERPROFILE\.ccs\profiles.json"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kaitranntt/ccs",
|
|
3
|
-
"version": "4.3.
|
|
3
|
+
"version": "4.3.5",
|
|
4
4
|
"description": "Claude Code Switch - Instant profile switching between Claude Sonnet 4.5 and GLM 4.6",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
61
|
"cli-table3": "^0.6.5",
|
|
62
|
-
"ora": "^
|
|
62
|
+
"ora": "^9.0.0"
|
|
63
63
|
},
|
|
64
64
|
"devDependencies": {
|
|
65
65
|
"mocha": "^11.7.5"
|
package/scripts/postinstall.js
CHANGED
|
@@ -109,6 +109,9 @@ function createConfigFiles() {
|
|
|
109
109
|
const installer = new ClaudeDirInstaller();
|
|
110
110
|
const packageDir = path.join(__dirname, '..');
|
|
111
111
|
installer.install(packageDir);
|
|
112
|
+
|
|
113
|
+
// Clean up deprecated files (v4.3.2)
|
|
114
|
+
installer.cleanupDeprecated();
|
|
112
115
|
} catch (err) {
|
|
113
116
|
console.warn('[!] Failed to install .claude/ directory:', err.message);
|
|
114
117
|
console.warn(' CCS items may not be available');
|