@champpaba/claude-agent-kit 1.4.0 → 1.4.2

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/bin/cli.js CHANGED
@@ -1,61 +1,59 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Claude Agent Kit - CLI Entry Point
5
- *
6
- * This is the main CLI file that handles all commands:
7
- * - cak init → Initialize template in current project
8
- * - cak update → Update template to latest version
9
- * - cak --version → Show version
10
- * - cak --help → Show help
11
- */
12
-
13
- const { program } = require('commander');
14
- const chalk = require('chalk');
15
- const pkg = require('../package.json');
16
-
17
- // Import command handlers
18
- const initCommand = require('../lib/init');
19
- const updateCommand = require('../lib/update');
20
-
21
- // Configure CLI
22
- program
23
- .name('cak')
24
- .description(chalk.cyan('🤖 Claude Agent Kit - Universal Multi-Agent Template'))
25
- .version(pkg.version, '-v, --version', 'Show version number');
26
-
27
- // Command: cak init
28
- program
29
- .command('init')
30
- .description('Initialize Claude Agent Kit template in current project')
31
- .option('-f, --force', 'Force initialization even if .claude/ exists')
32
- .action(async (options) => {
33
- try {
34
- await initCommand(options);
35
- } catch (error) {
36
- console.error(chalk.red('❌ Error:'), error.message);
37
- process.exit(1);
38
- }
39
- });
40
-
41
- // Command: cak update
42
- program
43
- .command('update')
44
- .description('Update template files to latest version')
45
- .option('-b, --backup', 'Create backup before updating')
46
- .action(async (options) => {
47
- try {
48
- await updateCommand(options);
49
- } catch (error) {
50
- console.error(chalk.red('❌ Error:'), error.message);
51
- process.exit(1);
52
- }
53
- });
54
-
55
- // Show help if no command provided
56
- if (!process.argv.slice(2).length) {
57
- program.outputHelp();
58
- }
59
-
60
- // Parse command line arguments
61
- program.parse(process.argv);
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Claude Agent Kit - CLI Entry Point
5
+ *
6
+ * This is the main CLI file that handles all commands:
7
+ * - cak init → Initialize template in current project
8
+ * - cak update → Update template to latest version
9
+ * - cak --version → Show version
10
+ * - cak --help → Show help
11
+ */
12
+
13
+ const { program } = require('commander');
14
+ const chalk = require('chalk');
15
+ const pkg = require('../package.json');
16
+
17
+ // Import command handlers
18
+ const initCommand = require('../lib/init');
19
+ const updateCommand = require('../lib/update');
20
+
21
+ // Configure CLI
22
+ program
23
+ .name('cak')
24
+ .description(chalk.cyan('🤖 Claude Agent Kit - Universal Multi-Agent Template'))
25
+ .version(pkg.version, '-v, --version', 'Show version number');
26
+
27
+ // Command: cak init
28
+ program
29
+ .command('init')
30
+ .description('Initialize Claude Agent Kit template in current project')
31
+ .action(async (options) => {
32
+ try {
33
+ await initCommand(options);
34
+ } catch (error) {
35
+ console.error(chalk.red('❌ Error:'), error.message);
36
+ process.exit(1);
37
+ }
38
+ });
39
+
40
+ // Command: cak update
41
+ program
42
+ .command('update')
43
+ .description('Update template files to latest version')
44
+ .action(async (options) => {
45
+ try {
46
+ await updateCommand(options);
47
+ } catch (error) {
48
+ console.error(chalk.red('❌ Error:'), error.message);
49
+ process.exit(1);
50
+ }
51
+ });
52
+
53
+ // Show help if no command provided
54
+ if (!process.argv.slice(2).length) {
55
+ program.outputHelp();
56
+ }
57
+
58
+ // Parse command line arguments
59
+ program.parse(process.argv);
package/lib/helpers.js ADDED
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Helpers - Shared utility functions for CLI commands
3
+ */
4
+
5
+ const fs = require('fs-extra');
6
+ const path = require('path');
7
+ const readline = require('readline');
8
+ const { execSync } = require('child_process');
9
+ const chalk = require('chalk');
10
+
11
+ /**
12
+ * Prompt user for yes/no question
13
+ * @param {string} question - Question to ask
14
+ * @returns {Promise<boolean>} - True if user answered yes
15
+ */
16
+ async function promptUser(question) {
17
+ const rl = readline.createInterface({
18
+ input: process.stdin,
19
+ output: process.stdout
20
+ });
21
+
22
+ return new Promise((resolve) => {
23
+ rl.question(question, (answer) => {
24
+ rl.close();
25
+ resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');
26
+ });
27
+ });
28
+ }
29
+
30
+ /**
31
+ * Merge template files into target directory with smart comparison
32
+ * - Only overwrites if content actually differs
33
+ * - Keeps existing files that don't exist in template
34
+ * - Skips identical files (prevents Git showing unnecessary changes)
35
+ * @param {string} templatePath - Source template directory
36
+ * @param {string} targetPath - Target directory
37
+ */
38
+ async function mergeTemplateFiles(templatePath, targetPath) {
39
+ const crypto = require('crypto');
40
+
41
+ // Helper: Calculate file hash
42
+ function getFileHash(filePath) {
43
+ try {
44
+ const content = fs.readFileSync(filePath);
45
+ return crypto.createHash('md5').update(content).digest('hex');
46
+ } catch (error) {
47
+ return null;
48
+ }
49
+ }
50
+
51
+ // Custom filter function
52
+ const filter = (src, dest) => {
53
+ const srcStat = fs.statSync(src);
54
+
55
+ // Always copy directories
56
+ if (srcStat.isDirectory()) {
57
+ return true;
58
+ }
59
+
60
+ // If destination doesn't exist, copy it
61
+ if (!fs.existsSync(dest)) {
62
+ return true;
63
+ }
64
+
65
+ // Compare file hashes (content-based comparison)
66
+ const srcHash = getFileHash(src);
67
+ const destHash = getFileHash(dest);
68
+
69
+ // Only copy if content differs
70
+ return srcHash !== destHash;
71
+ };
72
+
73
+ await fs.copy(templatePath, targetPath, {
74
+ overwrite: true,
75
+ errorOnExist: false,
76
+ filter: filter
77
+ });
78
+ }
79
+
80
+ /**
81
+ * Get latest version from npm registry
82
+ * @param {string} packageName - Package name
83
+ * @returns {Promise<string|null>} - Latest version or null if failed
84
+ */
85
+ async function getLatestVersion(packageName) {
86
+ try {
87
+ const result = execSync(`npm view ${packageName} version`, {
88
+ encoding: 'utf-8',
89
+ stdio: ['pipe', 'pipe', 'pipe']
90
+ });
91
+ return result.trim();
92
+ } catch (error) {
93
+ return null;
94
+ }
95
+ }
96
+
97
+ /**
98
+ * Get currently installed global package version
99
+ * @param {string} packageName - Package name
100
+ * @returns {string|null} - Current version or null if not installed
101
+ */
102
+ function getCurrentVersion(packageName) {
103
+ try {
104
+ const result = execSync(`npm list -g ${packageName} --depth=0`, {
105
+ encoding: 'utf-8',
106
+ stdio: ['pipe', 'pipe', 'pipe']
107
+ });
108
+ const match = result.match(new RegExp(`${packageName}@([\\d.]+)`));
109
+ return match ? match[1] : null;
110
+ } catch (error) {
111
+ return null;
112
+ }
113
+ }
114
+
115
+ /**
116
+ * Install package globally
117
+ * @param {string} packageName - Package name
118
+ * @param {string} version - Version to install (default: latest)
119
+ * @returns {Promise<boolean>} - True if successful
120
+ */
121
+ async function installGlobalPackage(packageName, version = 'latest') {
122
+ try {
123
+ console.log(chalk.gray(`\n📦 Installing ${packageName}@${version} globally...\n`));
124
+
125
+ execSync(`npm install -g ${packageName}@${version}`, {
126
+ encoding: 'utf-8',
127
+ stdio: 'inherit'
128
+ });
129
+
130
+ console.log(chalk.green(`\n✅ Package installed successfully!\n`));
131
+ return true;
132
+ } catch (error) {
133
+ console.error(chalk.red(`\n❌ Failed to install package: ${error.message}\n`));
134
+ return false;
135
+ }
136
+ }
137
+
138
+ module.exports = {
139
+ promptUser,
140
+ mergeTemplateFiles,
141
+ getLatestVersion,
142
+ getCurrentVersion,
143
+ installGlobalPackage
144
+ };
package/lib/init.js CHANGED
@@ -1,52 +1,57 @@
1
- /**
2
- * Init Command - Initialize Claude Agent Kit template
3
- *
4
- * This function copies the .claude/ template folder to the current project.
5
- */
6
-
7
- const fs = require('fs-extra');
8
- const path = require('path');
9
- const chalk = require('chalk');
10
-
11
- module.exports = async function init(options = {}) {
12
- const { force } = options;
13
-
14
- // Paths
15
- const templatePath = path.join(__dirname, '../.claude');
16
- const targetPath = path.join(process.cwd(), '.claude');
17
-
18
- console.log(chalk.cyan('\n🤖 Claude Agent Kit - Initializing...\n'));
19
-
20
- // Check if template exists
21
- if (!fs.existsSync(templatePath)) {
22
- throw new Error('Template folder not found. Please reinstall the package.');
23
- }
24
-
25
- // Check if .claude/ already exists
26
- if (fs.existsSync(targetPath)) {
27
- if (!force) {
28
- console.log(chalk.yellow('⚠️ .claude/ already exists in this project.'));
29
- console.log(chalk.gray(' Use --force to overwrite:\n'));
30
- console.log(chalk.cyan(' cak init --force\n'));
31
- return;
32
- }
33
-
34
- console.log(chalk.yellow('⚠️ Overwriting existing .claude/ folder...\n'));
35
- await fs.remove(targetPath);
36
- }
37
-
38
- // Copy template
39
- try {
40
- await fs.copy(templatePath, targetPath);
41
-
42
- console.log(chalk.green('✅ Successfully initialized Claude Agent Kit!\n'));
43
- console.log(chalk.white('📁 Files copied to: ') + chalk.cyan(targetPath));
44
- console.log(chalk.white('\n📚 Next steps:\n'));
45
- console.log(chalk.gray(' 1. Review the .claude/ folder'));
46
- console.log(chalk.gray(' 2. Run: ') + chalk.cyan('/psetup') + chalk.gray(' (one-time project setup)'));
47
- console.log(chalk.gray(' 3. Start using agents with Claude Code\n'));
48
-
49
- } catch (error) {
50
- throw new Error(`Failed to copy template: ${error.message}`);
51
- }
52
- };
1
+ /**
2
+ * Init Command - Initialize Claude Agent Kit template
3
+ *
4
+ * This function merges the .claude/ template folder into the current project.
5
+ * - Overwrites files with same name
6
+ * - Keeps existing files that don't exist in template
7
+ */
8
+
9
+ const fs = require('fs-extra');
10
+ const path = require('path');
11
+ const chalk = require('chalk');
12
+ const { promptUser, mergeTemplateFiles } = require('./helpers');
13
+
14
+ module.exports = async function init(options = {}) {
15
+ // Paths
16
+ const templatePath = path.join(__dirname, '../.claude');
17
+ const targetPath = path.join(process.cwd(), '.claude');
18
+
19
+ console.log(chalk.cyan('\n🤖 Claude Agent Kit - Initializing...\n'));
20
+
21
+ // Check if template exists
22
+ if (!fs.existsSync(templatePath)) {
23
+ throw new Error('Template folder not found. Please reinstall the package.');
24
+ }
25
+
26
+ // Check if .claude/ already exists
27
+ if (fs.existsSync(targetPath)) {
28
+ console.log(chalk.yellow('⚠️ .claude/ already exists in this project.'));
29
+ console.log(chalk.gray(' Existing files will be preserved, template files will be merged.\n'));
30
+
31
+ const shouldContinue = await promptUser(
32
+ chalk.cyan('❓ Merge with template files? (y/N): ')
33
+ );
34
+
35
+ if (!shouldContinue) {
36
+ console.log(chalk.gray('\n❌ Initialization cancelled.\n'));
37
+ return;
38
+ }
39
+
40
+ console.log(chalk.gray('\n📦 Merging template files...\n'));
41
+ }
42
+
43
+ // Merge template files
44
+ try {
45
+ await mergeTemplateFiles(templatePath, targetPath);
46
+
47
+ console.log(chalk.green(' Successfully initialized Claude Agent Kit!\n'));
48
+ console.log(chalk.white('📁 Files merged to: ') + chalk.cyan(targetPath));
49
+ console.log(chalk.white('\n📚 Next steps:\n'));
50
+ console.log(chalk.gray(' 1. Review the .claude/ folder'));
51
+ console.log(chalk.gray(' 2. Run: ') + chalk.cyan('/psetup') + chalk.gray(' (one-time project setup)'));
52
+ console.log(chalk.gray(' 3. Start using agents with Claude Code\n'));
53
+
54
+ } catch (error) {
55
+ throw new Error(`Failed to merge template: ${error.message}`);
56
+ }
57
+ };
package/lib/update.js CHANGED
@@ -1,73 +1,90 @@
1
- /**
2
- * Update Command - Update Claude Agent Kit template to latest version
3
- *
4
- * This function updates the .claude/ folder with the latest template files.
5
- */
6
-
7
- const fs = require('fs-extra');
8
- const path = require('path');
9
- const chalk = require('chalk');
10
-
11
- module.exports = async function update(options = {}) {
12
- const { backup } = options;
13
-
14
- // Paths
15
- const templatePath = path.join(__dirname, '../.claude');
16
- const targetPath = path.join(process.cwd(), '.claude');
17
- const backupPath = path.join(process.cwd(), '.claude.backup');
18
-
19
- console.log(chalk.cyan('\n🤖 Claude Agent Kit - Updating...\n'));
20
-
21
- // Check if .claude/ exists
22
- if (!fs.existsSync(targetPath)) {
23
- console.log(chalk.yellow('⚠️ .claude/ not found in this project.'));
24
- console.log(chalk.gray(' Run init first:\n'));
25
- console.log(chalk.cyan(' cak init\n'));
26
- return;
27
- }
28
-
29
- // Check if template exists
30
- if (!fs.existsSync(templatePath)) {
31
- throw new Error('Template folder not found. Please reinstall the package.');
32
- }
33
-
34
- // Create backup if requested
35
- if (backup) {
36
- console.log(chalk.gray('📦 Creating backup...\n'));
37
-
38
- // Remove old backup if exists
39
- if (fs.existsSync(backupPath)) {
40
- await fs.remove(backupPath);
41
- }
42
-
43
- // Copy current .claude/ to backup
44
- await fs.copy(targetPath, backupPath);
45
- console.log(chalk.green('✅ Backup created: ') + chalk.cyan('.claude.backup\n'));
46
- }
47
-
48
- // Update template
49
- try {
50
- // Strategy: Overwrite all files from template
51
- // User customizations in domain/ should be preserved if they don't conflict
52
- await fs.copy(templatePath, targetPath, {
53
- overwrite: true,
54
- errorOnExist: false
55
- });
56
-
57
- console.log(chalk.green('✅ Successfully updated Claude Agent Kit!\n'));
58
- console.log(chalk.white('📁 Updated files in: ') + chalk.cyan(targetPath));
59
-
60
- if (backup) {
61
- console.log(chalk.white('\n💾 Backup available at: ') + chalk.cyan(backupPath));
62
- console.log(chalk.gray(' You can restore it if needed:\n'));
63
- console.log(chalk.cyan(' rm -rf .claude && mv .claude.backup .claude\n'));
64
- }
65
-
66
- console.log(chalk.white('\n📚 What\'s new:\n'));
67
- console.log(chalk.gray(' Check CHANGELOG.md for latest changes'));
68
- console.log(chalk.gray(' Or visit: ') + chalk.cyan('https://github.com/your-username/claude-agent-kit\n'));
69
-
70
- } catch (error) {
71
- throw new Error(`Failed to update template: ${error.message}`);
72
- }
73
- };
1
+ /**
2
+ * Update Command - Update Claude Agent Kit template to latest version
3
+ *
4
+ * This function:
5
+ * 1. Checks for new version in npm registry
6
+ * 2. Optionally updates the global package
7
+ * 3. Merges latest template files into .claude/
8
+ */
9
+
10
+ const fs = require('fs-extra');
11
+ const path = require('path');
12
+ const chalk = require('chalk');
13
+ const pkg = require('../package.json');
14
+ const {
15
+ promptUser,
16
+ mergeTemplateFiles,
17
+ getLatestVersion,
18
+ getCurrentVersion,
19
+ installGlobalPackage
20
+ } = require('./helpers');
21
+
22
+ module.exports = async function update(options = {}) {
23
+ const packageName = pkg.name;
24
+
25
+ // Paths
26
+ const templatePath = path.join(__dirname, '../.claude');
27
+ const targetPath = path.join(process.cwd(), '.claude');
28
+
29
+ console.log(chalk.cyan('\n🤖 Claude Agent Kit - Updating...\n'));
30
+
31
+ // Check if .claude/ exists
32
+ if (!fs.existsSync(targetPath)) {
33
+ console.log(chalk.yellow('⚠️ .claude/ not found in this project.'));
34
+ console.log(chalk.gray(' Run init first:\n'));
35
+ console.log(chalk.cyan(' cak init\n'));
36
+ return;
37
+ }
38
+
39
+ // STEP 1: Check version
40
+ console.log(chalk.gray('🔍 Checking for updates...\n'));
41
+
42
+ const currentVersion = getCurrentVersion(packageName) || pkg.version;
43
+ const latestVersion = await getLatestVersion(packageName);
44
+
45
+ if (!latestVersion) {
46
+ console.log(chalk.yellow('⚠️ Unable to check npm registry. Continuing with local version.\n'));
47
+ } else if (currentVersion === latestVersion) {
48
+ console.log(chalk.green(`✅ Already on latest version (${latestVersion})\n`));
49
+ } else {
50
+ console.log(chalk.cyan(`📦 New version available: ${chalk.bold(latestVersion)} (current: ${currentVersion})\n`));
51
+
52
+ const shouldUpdatePackage = await promptUser(
53
+ chalk.cyan('❓ Update package globally first? (y/N): ')
54
+ );
55
+
56
+ // STEP 2: Update package globally
57
+ if (shouldUpdatePackage) {
58
+ const success = await installGlobalPackage(packageName, latestVersion);
59
+
60
+ if (!success) {
61
+ console.log(chalk.yellow('⚠️ Package update failed. Continuing with current version.\n'));
62
+ }
63
+ } else {
64
+ console.log(chalk.gray('\n⏭️ Skipping package update. Using current version.\n'));
65
+ }
66
+ }
67
+
68
+ // Check if template exists
69
+ if (!fs.existsSync(templatePath)) {
70
+ throw new Error('Template folder not found. Please reinstall the package.');
71
+ }
72
+
73
+ // STEP 3: Update files (merge mode)
74
+ console.log(chalk.gray('📦 Merging template files...\n'));
75
+
76
+ try {
77
+ await mergeTemplateFiles(templatePath, targetPath);
78
+
79
+ console.log(chalk.green('✅ Successfully updated Claude Agent Kit!\n'));
80
+ console.log(chalk.white('📁 Updated files in: ') + chalk.cyan(targetPath));
81
+ console.log(chalk.gray(' (Existing files preserved, template files merged)\n'));
82
+
83
+ console.log(chalk.white('📚 What\'s new:\n'));
84
+ console.log(chalk.gray(' Check CHANGELOG.md for latest changes'));
85
+ console.log(chalk.gray(' Or visit: ') + chalk.cyan('https://github.com/ChampPABA/claude-multi-agent-template\n'));
86
+
87
+ } catch (error) {
88
+ throw new Error(`Failed to update template: ${error.message}`);
89
+ }
90
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@champpaba/claude-agent-kit",
3
- "version": "1.4.0",
3
+ "version": "1.4.2",
4
4
  "description": "Universal multi-agent template for Claude Code - AI-assisted development with specialized agents",
5
5
  "main": "bin/cli.js",
6
6
  "bin": {