Files
ccs/bin/ccs.js
T
kaitranntt 80a5200cae fix: terminal termination & simplified detection (v2.4.1)
Critical Fixes:
- Fixed PowerShell terminal closing when using `irm | iex` installation
  * Changed `exit 1` to `return` in install.ps1 (line 229)
  * Terminal now stays open on errors, showing full error messages
  * Affects: Windows PowerShell 5.1+, PowerShell 7+

- Fixed installation download path
  * Changed `/ccs.ps1` to `/lib/ccs.ps1` in install.ps1 (line 223)
  * Resolves standalone installation failures from GitHub

- Simplified Claude CLI detection logic across all platforms
  * Removed complex validation that failed with npm-installed Claude
  * Now trusts system PATH (standard case for users)
  * Falls back to CCS_CLAUDE_PATH for custom installations
  * Fixes: `where.exe claude` shows installed but CCS reports "not found"

Improvements:
- Simplified error messages (removed lengthy search location details)
- Reduced codebase by 332 lines (454 deleted, 122 added)
- npm package size reduced: 17.2 KB → 15.9 KB (7.6% smaller)

Cross-Platform Parity:
- bash (lib/ccs): Simplified detection, removed validate_claude_cli
- PowerShell (lib/ccs.ps1): Simplified detection, removed Test-ClaudeCli
- Node.js (bin/*.js): Simplified detection, removed validateClaudeCli
- All versions now use identical trust-the-PATH approach

Files Modified:
- installers/install.ps1: exit→return, download path fix
- lib/ccs.ps1: simplified detection (165 lines removed)
- lib/ccs: simplified detection (172 lines removed)
- bin/claude-detector.js: simplified detection (86 lines removed)
- bin/ccs.js: removed validation calls (31 lines removed)
- .github/workflows/publish-npm.yml: fixed package name
- CHANGELOG.md: comprehensive v2.4.1 release notes
- VERSION, package.json: bumped to 2.4.1

Testing: bash validated, npm syntax checked, manual Windows testing recommended
2025-11-04 21:54:05 -05:00

158 lines
4.2 KiB
JavaScript
Executable File

#!/usr/bin/env node
'use strict';
const { spawn } = require('child_process');
const path = require('path');
const fs = require('fs');
const { showError, colors } = require('./helpers');
const { detectClaudeCli, showClaudeNotFoundError } = require('./claude-detector');
const { getSettingsPath } = require('./config-manager');
// Version (sync with package.json)
const CCS_VERSION = require('../package.json').version;
// Special command handlers
function handleVersionCommand() {
console.log(`CCS (Claude Code Switch) version ${CCS_VERSION}`);
// Show install location
const installLocation = process.argv[1];
if (installLocation) {
console.log(`Installed at: ${installLocation}`);
}
console.log('https://github.com/kaitranntt/ccs');
process.exit(0);
}
function handleHelpCommand(remainingArgs) {
const claudeCli = detectClaudeCli();
// Execute claude --help
const child = spawn(claudeCli, ['--help', ...remainingArgs], { stdio: 'inherit' });
child.on('exit', (code, signal) => {
if (signal) {
process.kill(process.pid, signal);
} else {
process.exit(code || 0);
}
});
child.on('error', (err) => {
showClaudeNotFoundError();
process.exit(1);
});
}
function handleInstallCommand() {
// Implementation for --install (copy commands/skills to ~/.claude)
console.log('[Installing CCS Commands and Skills]');
console.log('Feature not yet implemented in Node.js standalone');
console.log('Use traditional installer for now:');
console.log(process.platform === 'win32'
? ' irm ccs.kaitran.ca/install | iex'
: ' curl -fsSL ccs.kaitran.ca/install | bash');
process.exit(0);
}
function handleUninstallCommand() {
// Implementation for --uninstall (remove commands/skills from ~/.claude)
console.log('[Uninstalling CCS Commands and Skills]');
console.log('Feature not yet implemented in Node.js standalone');
console.log('Use traditional uninstaller for now');
process.exit(0);
}
// Smart profile detection
function detectProfile(args) {
if (args.length === 0 || args[0].startsWith('-')) {
// No args or first arg is a flag → use default profile
return { profile: 'default', remainingArgs: args };
} else {
// First arg doesn't start with '-' → treat as profile name
return { profile: args[0], remainingArgs: args.slice(1) };
}
}
// Main execution
function main() {
const args = process.argv.slice(2);
// Special case: version command (check BEFORE profile detection)
const firstArg = args[0];
if (firstArg === 'version' || firstArg === '--version' || firstArg === '-v') {
handleVersionCommand();
}
// Special case: help command
if (firstArg === '--help' || firstArg === '-h' || firstArg === 'help') {
const remainingArgs = args.slice(1);
handleHelpCommand(remainingArgs);
return;
}
// Special case: install command
if (firstArg === '--install') {
handleInstallCommand();
return;
}
// Special case: uninstall command
if (firstArg === '--uninstall') {
handleUninstallCommand();
return;
}
// Detect profile
const { profile, remainingArgs } = detectProfile(args);
// Special case: "default" profile just runs claude directly
if (profile === 'default') {
const claudeCli = detectClaudeCli();
// Execute claude with args
const child = spawn(claudeCli, remainingArgs, { stdio: 'inherit' });
child.on('exit', (code, signal) => {
if (signal) {
process.kill(process.pid, signal);
} else {
process.exit(code || 0);
}
});
child.on('error', (err) => {
showClaudeNotFoundError();
process.exit(1);
});
return;
}
// Get settings path for profile
const settingsPath = getSettingsPath(profile);
// Detect Claude CLI
const claudeCli = detectClaudeCli();
// Execute claude with --settings
const claudeArgs = ['--settings', settingsPath, ...remainingArgs];
const child = spawn(claudeCli, claudeArgs, { stdio: 'inherit' });
child.on('exit', (code, signal) => {
if (signal) {
process.kill(process.pid, signal);
} else {
process.exit(code || 0);
}
});
child.on('error', (err) => {
showClaudeNotFoundError();
process.exit(1);
});
}
// Run main
main();