mirror of
https://github.com/tiennm99/ccs.git
synced 2026-08-05 22:24:04 +00:00
fix(.claude/): resolve npm install failure for claude-dir-installer
Fixes issue where npm install -g or ccs update would fail to copy .claude/ directory to ~/.ccs/.claude/, causing symlink installation errors. ClaudeDirInstaller now ensures source exists before ClaudeSymlinkManager attempts linking.
This commit is contained in:
@@ -255,6 +255,12 @@ async function handleDoctorCommand() {
|
||||
}
|
||||
|
||||
async function handleUpdateCommand() {
|
||||
// First, copy .claude/ directory from package to ~/.ccs/.claude/
|
||||
const ClaudeDirInstaller = require('./utils/claude-dir-installer');
|
||||
const installer = new ClaudeDirInstaller();
|
||||
installer.install();
|
||||
|
||||
// Then, create symlinks from ~/.ccs/.claude/ to ~/.claude/
|
||||
const ClaudeSymlinkManager = require('./utils/claude-symlink-manager');
|
||||
const manager = new ClaudeSymlinkManager();
|
||||
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
#!/usr/bin/env node
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const os = require('os');
|
||||
|
||||
/**
|
||||
* ClaudeDirInstaller - Manages copying .claude/ directory from package to ~/.ccs/.claude/
|
||||
* v4.1.1: Fix for npm install not copying .claude/ directory
|
||||
*/
|
||||
class ClaudeDirInstaller {
|
||||
constructor() {
|
||||
this.homeDir = os.homedir();
|
||||
this.ccsClaudeDir = path.join(this.homeDir, '.ccs', '.claude');
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy .claude/ directory from package to ~/.ccs/.claude/
|
||||
* @param {string} packageDir - Package installation directory (default: auto-detect)
|
||||
*/
|
||||
install(packageDir) {
|
||||
try {
|
||||
// Auto-detect package directory if not provided
|
||||
if (!packageDir) {
|
||||
// Try to find package root by going up from this file
|
||||
packageDir = path.join(__dirname, '..', '..');
|
||||
}
|
||||
|
||||
const packageClaudeDir = path.join(packageDir, '.claude');
|
||||
|
||||
if (!fs.existsSync(packageClaudeDir)) {
|
||||
console.log('[!] Package .claude/ directory not found');
|
||||
console.log(` Searched in: ${packageClaudeDir}`);
|
||||
console.log(' This may be a development installation');
|
||||
return false;
|
||||
}
|
||||
|
||||
console.log('[i] Installing CCS .claude/ items...');
|
||||
|
||||
// Remove old version before copying new one
|
||||
if (fs.existsSync(this.ccsClaudeDir)) {
|
||||
fs.rmSync(this.ccsClaudeDir, { recursive: true, force: true });
|
||||
}
|
||||
|
||||
// Use fs.cpSync for recursive copy (Node.js 16.7.0+)
|
||||
// Fallback to manual copy for older Node.js versions
|
||||
if (fs.cpSync) {
|
||||
fs.cpSync(packageClaudeDir, this.ccsClaudeDir, { recursive: true });
|
||||
} else {
|
||||
// Fallback for Node.js < 16.7.0
|
||||
this._copyDirRecursive(packageClaudeDir, this.ccsClaudeDir);
|
||||
}
|
||||
|
||||
console.log('[OK] Copied .claude/ items to ~/.ccs/.claude/');
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.warn('[!] Failed to copy .claude/ directory:', err.message);
|
||||
console.warn(' CCS items may not be available');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively copy directory (fallback for Node.js < 16.7.0)
|
||||
* @param {string} src - Source directory
|
||||
* @param {string} dest - Destination directory
|
||||
* @private
|
||||
*/
|
||||
_copyDirRecursive(src, dest) {
|
||||
// Create destination directory
|
||||
if (!fs.existsSync(dest)) {
|
||||
fs.mkdirSync(dest, { recursive: true });
|
||||
}
|
||||
|
||||
// Read source directory
|
||||
const entries = fs.readdirSync(src, { withFileTypes: true });
|
||||
|
||||
for (const entry of entries) {
|
||||
const srcPath = path.join(src, entry.name);
|
||||
const destPath = path.join(dest, entry.name);
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
// Recursively copy subdirectory
|
||||
this._copyDirRecursive(srcPath, destPath);
|
||||
} else {
|
||||
// Copy file
|
||||
fs.copyFileSync(srcPath, destPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if ~/.ccs/.claude/ exists and is valid
|
||||
* @returns {boolean} True if directory exists
|
||||
*/
|
||||
isInstalled() {
|
||||
return fs.existsSync(this.ccsClaudeDir);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ClaudeDirInstaller;
|
||||
@@ -31,7 +31,7 @@ $InstallMethod = if ($ScriptDir -and ((Test-Path "$ScriptDir\lib\ccs.ps1") -or (
|
||||
# IMPORTANT: Update this version when releasing new versions!
|
||||
# This hardcoded version is used for standalone installations (irm | iex)
|
||||
# For git installations, VERSION file is read if available
|
||||
$CcsVersion = "4.1.0"
|
||||
$CcsVersion = "4.1.1"
|
||||
|
||||
# Try to read VERSION file for git installations
|
||||
if ($ScriptDir) {
|
||||
|
||||
@@ -32,7 +32,7 @@ fi
|
||||
# IMPORTANT: Update this version when releasing new versions!
|
||||
# This hardcoded version is used for standalone installations (curl | bash)
|
||||
# For git installations, VERSION file is read if available
|
||||
CCS_VERSION="4.1.0"
|
||||
CCS_VERSION="4.1.1"
|
||||
|
||||
# Try to read VERSION file for git installations
|
||||
if [[ -f "$SCRIPT_DIR/VERSION" ]]; then
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
set -euo pipefail
|
||||
|
||||
# Version (updated by scripts/bump-version.sh)
|
||||
CCS_VERSION="4.1.0"
|
||||
CCS_VERSION="4.1.1"
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
readonly CONFIG_FILE="${CCS_CONFIG:-$HOME/.ccs/config.json}"
|
||||
readonly PROFILES_JSON="$HOME/.ccs/profiles.json"
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ param(
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
# Version (updated by scripts/bump-version.sh)
|
||||
$CcsVersion = "4.1.0"
|
||||
$CcsVersion = "4.1.1"
|
||||
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
$ConfigFile = if ($env:CCS_CONFIG) { $env:CCS_CONFIG } else { "$env:USERPROFILE\.ccs\config.json" }
|
||||
$ProfilesJson = "$env:USERPROFILE\.ccs\profiles.json"
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@kaitranntt/ccs",
|
||||
"version": "4.1.0",
|
||||
"version": "4.1.1",
|
||||
"description": "Claude Code Switch - Instant profile switching between Claude Sonnet 4.5 and GLM 4.6",
|
||||
"keywords": [
|
||||
"cli",
|
||||
|
||||
@@ -103,6 +103,17 @@ function createConfigFiles() {
|
||||
}
|
||||
console.log('');
|
||||
|
||||
// Copy .claude/ directory from package to ~/.ccs/.claude/ (v4.1.1)
|
||||
try {
|
||||
const ClaudeDirInstaller = require('../bin/utils/claude-dir-installer');
|
||||
const installer = new ClaudeDirInstaller();
|
||||
const packageDir = path.join(__dirname, '..');
|
||||
installer.install(packageDir);
|
||||
} catch (err) {
|
||||
console.warn('[!] Failed to install .claude/ directory:', err.message);
|
||||
console.warn(' CCS items may not be available');
|
||||
}
|
||||
|
||||
// Install CCS items to ~/.claude/ (v4.1.0)
|
||||
try {
|
||||
const ClaudeSymlinkManager = require('../bin/utils/claude-symlink-manager');
|
||||
|
||||
Reference in New Issue
Block a user