cskit-cli 1.0.2 → 1.0.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cskit-cli",
3
- "version": "1.0.2",
3
+ "version": "1.0.5",
4
4
  "description": "Content Suite Kit CLI - Download and manage CSK skills from private repository",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -66,36 +66,121 @@ async function setupPythonEnv(projectDir, spinner) {
66
66
  const venvPath = path.join(libPythonDir, '.venv');
67
67
 
68
68
  try {
69
- // Check if Python 3 is available
69
+ // Check if Python 3 is available and get version
70
+ let pythonVersion;
70
71
  try {
71
- execSync('python3 --version', { stdio: 'pipe' });
72
+ pythonVersion = execSync('python3 --version', { stdio: 'pipe' }).toString().trim();
73
+ spinner.text = `Found ${pythonVersion}`;
72
74
  } catch {
73
75
  spinner.warn('Python 3 not found, skipping venv setup');
74
76
  return { success: true, skipped: true, reason: 'python3 not found' };
75
77
  }
76
78
 
79
+ // Check minimum version (3.9+)
80
+ const versionMatch = pythonVersion.match(/Python (\d+)\.(\d+)/);
81
+ if (versionMatch) {
82
+ const [, major, minor] = versionMatch.map(Number);
83
+ if (major < 3 || (major === 3 && minor < 9)) {
84
+ spinner.warn(`Python ${major}.${minor} found, requires 3.9+`);
85
+ return { success: true, skipped: true, reason: `Python ${major}.${minor} requires 3.9+` };
86
+ }
87
+ }
88
+
77
89
  // Create venv if not exists
78
90
  if (!fs.existsSync(venvPath)) {
79
91
  spinner.text = 'Creating virtual environment...';
80
92
  execSync(`python3 -m venv "${venvPath}"`, { stdio: 'pipe', cwd: libPythonDir });
81
93
  }
82
94
 
83
- // Install requirements
95
+ // Install requirements with error handling
84
96
  spinner.text = 'Installing Python packages...';
85
97
  const pipPath = path.join(venvPath, 'bin', 'pip');
86
- execSync(`"${pipPath}" install -r requirements.txt -q`, {
87
- stdio: 'pipe',
88
- cwd: libPythonDir
89
- });
90
98
 
91
- spinner.succeed('Python environment ready');
92
- return { success: true };
99
+ try {
100
+ execSync(`"${pipPath}" install -r requirements.txt -q`, {
101
+ stdio: 'pipe',
102
+ cwd: libPythonDir
103
+ });
104
+ spinner.succeed(`Python environment ready (${pythonVersion})`);
105
+ return { success: true, version: pythonVersion };
106
+ } catch (pipError) {
107
+ // Try installing without optional packages
108
+ spinner.text = 'Retrying with core packages...';
109
+ try {
110
+ execSync(`"${pipPath}" install numpy pandas scipy pydantic rich click -q`, {
111
+ stdio: 'pipe',
112
+ cwd: libPythonDir
113
+ });
114
+ spinner.warn('Partial install - some optional packages failed');
115
+ return { success: true, partial: true, version: pythonVersion };
116
+ } catch {
117
+ throw pipError;
118
+ }
119
+ }
93
120
  } catch (error) {
94
121
  spinner.warn(`Python setup failed: ${error.message}`);
95
122
  return { success: false, error: error.message };
96
123
  }
97
124
  }
98
125
 
126
+ /**
127
+ * Setup CSK in Claude Code directories
128
+ */
129
+ async function setupCommands(projectDir, spinner) {
130
+ spinner.start('Setting up CSK for Claude Code...');
131
+
132
+ try {
133
+ const claudeDir = path.join(projectDir, '.claude');
134
+ ensureDir(claudeDir);
135
+
136
+ // Map: source → destination
137
+ const mappings = [
138
+ { src: 'src/commands', dest: '.claude/commands' },
139
+ { src: 'core', dest: '.claude/skills/csk/core' },
140
+ { src: 'domains', dest: '.claude/skills/csk/domains' },
141
+ { src: 'industries', dest: '.claude/skills/csk/industries' },
142
+ { src: 'lib', dest: '.claude/skills/csk/lib' }
143
+ ];
144
+
145
+ let copied = 0;
146
+ for (const { src, dest } of mappings) {
147
+ const srcPath = path.join(projectDir, src);
148
+ const destPath = path.join(projectDir, dest);
149
+
150
+ if (fs.existsSync(srcPath)) {
151
+ ensureDir(destPath);
152
+ copyDirRecursive(srcPath, destPath);
153
+ copied++;
154
+ }
155
+ }
156
+
157
+ spinner.succeed(`CSK installed to .claude/ (${copied} modules)`);
158
+ return { success: true };
159
+ } catch (error) {
160
+ spinner.warn(`CSK setup failed: ${error.message}`);
161
+ return { success: false, error: error.message };
162
+ }
163
+ }
164
+
165
+ /**
166
+ * Recursively copy directory
167
+ */
168
+ function copyDirRecursive(src, dest) {
169
+ const entries = fs.readdirSync(src, { withFileTypes: true });
170
+
171
+ for (const entry of entries) {
172
+ const srcPath = path.join(src, entry.name);
173
+ const destPath = path.join(dest, entry.name);
174
+
175
+ if (entry.isDirectory()) {
176
+ ensureDir(destPath);
177
+ copyDirRecursive(srcPath, destPath);
178
+ } else {
179
+ fs.copyFileSync(srcPath, destPath);
180
+ }
181
+ }
182
+ }
183
+
99
184
  /**
100
185
  * Main init command handler
101
186
  */
@@ -254,6 +339,9 @@ async function initCommand(options) {
254
339
  console.log('');
255
340
  const pythonResult = await setupPythonEnv(projectDir, spinner);
256
341
 
342
+ // Copy commands to .claude/commands/
343
+ await setupCommands(projectDir, spinner);
344
+
257
345
  // Success message
258
346
  const ver = selectedVersion.replace(/^v/, '');
259
347
  console.log(chalk.green(`\n ✓ CSK v${ver} ${isUpdate ? 'updated' : 'installed'} successfully!\n`));