-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathcli.js
More file actions
74 lines (62 loc) · 3.05 KB
/
cli.js
File metadata and controls
74 lines (62 loc) · 3.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#!/usr/bin/env node
const fs = require('fs');
const path = require('path');
const os = require('os');
const homeDir = process.env.HOME || process.env.USERPROFILE || os.homedir();
const destDir = path.join(homeDir, '.claude');
const srcDir = __dirname;
const isUpgrade = fs.existsSync(destDir);
console.log(isUpgrade ? 'Upgrading gm-cc...' : 'Installing gm-cc...');
try {
fs.mkdirSync(destDir, { recursive: true });
const filesToCopy = [];
function copyRecursive(src, dst) {
if (!fs.existsSync(src)) return;
if (fs.statSync(src).isDirectory()) {
fs.mkdirSync(dst, { recursive: true });
fs.readdirSync(src).forEach(f => copyRecursive(path.join(src, f), path.join(dst, f)));
} else {
fs.copyFileSync(src, dst);
}
}
filesToCopy.forEach(([src, dst]) => copyRecursive(path.join(srcDir, src), path.join(destDir, dst)));
const { execSync: exec } = require('child_process');
const sep = process.platform === 'win32' ? ';' : ':';
const sanitizedPath = (process.env.PATH || '').split(sep).filter(p => !/[\\/]node_modules[\\/]\.bin$/.test(p.replace(/[\\/]+$/, ''))).join(sep);
const run = (cmd) => { try { return exec(cmd, { stdio: 'inherit', env: { ...process.env, PATH: sanitizedPath, CLAUDECODE: '' } }); } catch (e) { console.warn('Warning:', e.message); } };
const gmccHookFiles = ['post-tool-use-hook.js','pre-tool-use-hook.js','prompt-submit-hook.js','session-start-hook.js','stop-hook-git.js','stop-hook.js'];
const gmccAgentFiles = ['gm.md'];
const staleLocations = [
...gmccHookFiles.map(f => path.join(homeDir, '.claude', 'hooks', f)),
...gmccAgentFiles.map(f => path.join(homeDir, '.claude', 'agents', f)),
...gmccHookFiles.map(f => path.join(homeDir, '.claude', 'skills', f)),
...gmccAgentFiles.map(f => path.join(homeDir, '.claude', 'skills', f)),
path.join(homeDir, '.claude', 'plugins', 'gm-cc'),
];
staleLocations.forEach(p => {
try {
const stat = fs.statSync(p);
if (stat.isDirectory()) fs.rmSync(p, { recursive: true, force: true });
else fs.unlinkSync(p);
} catch (e) {}
});
const pluginCacheDir = path.join(homeDir, '.claude', 'plugins', 'cache', 'gm-cc');
copyRecursive(srcDir, pluginCacheDir);
run('claude plugin marketplace add AnEntrypoint/gm-cc');
run('claude plugin install gm@gm-cc --scope user');
const knownMarketplacesPath = path.join(homeDir, '.claude', 'plugins', 'known_marketplaces.json');
try {
const km = JSON.parse(fs.readFileSync(knownMarketplacesPath, 'utf-8'));
if (km && km['gm-cc'] && km['gm-cc'].source && km['gm-cc'].installLocation) {
km['gm-cc'].autoUpdate = true;
km['gm-cc'].lastUpdated = new Date().toISOString();
fs.writeFileSync(knownMarketplacesPath, JSON.stringify(km, null, 2) + '\n');
}
} catch (e) {}
const destPath = process.platform === 'win32' ? destDir.replace(/\\/g, '/') : destDir;
console.log(`✓ gm-cc ${isUpgrade ? 'upgraded' : 'installed'} to ${destPath}`);
console.log('Restart Claude Code to activate.');
} catch (e) {
console.error('Installation failed:', e.message);
process.exit(1);
}