zuppaclaude 1.0.2 → 1.2.0
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/README.md +60 -16
- package/assets/commands/zc/README.md +31 -0
- package/assets/commands/zc/backup.md +62 -0
- package/assets/commands/zc/cloud.md +80 -0
- package/assets/commands/zc/help.md +81 -0
- package/assets/commands/zc/restore.md +65 -0
- package/assets/commands/zc/session.md +81 -0
- package/assets/commands/zc/settings.md +85 -0
- package/bin/zuppaclaude.js +124 -17
- package/lib/components/backup.js +235 -0
- package/lib/components/cloud.js +335 -0
- package/lib/components/commands.js +139 -0
- package/lib/components/index.js +7 -1
- package/lib/installer.js +23 -7
- package/lib/uninstaller.js +7 -3
- package/package.json +1 -1
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloud Backup Manager - rclone integration for cloud sync
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const { Logger } = require('../utils/logger');
|
|
8
|
+
const { Platform } = require('../utils/platform');
|
|
9
|
+
|
|
10
|
+
class CloudManager {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.platform = new Platform();
|
|
13
|
+
this.logger = new Logger();
|
|
14
|
+
this.backupDir = path.join(this.platform.zuppaconfigDir, 'backups');
|
|
15
|
+
this.cloudPath = 'zuppaclaude-backups';
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Check if rclone is installed
|
|
20
|
+
*/
|
|
21
|
+
isRcloneInstalled() {
|
|
22
|
+
return this.platform.commandExists('rclone');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Get available rclone remotes
|
|
27
|
+
*/
|
|
28
|
+
getRemotes() {
|
|
29
|
+
if (!this.isRcloneInstalled()) {
|
|
30
|
+
return [];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
const output = this.platform.exec('rclone listremotes', { silent: true });
|
|
35
|
+
if (!output) return [];
|
|
36
|
+
|
|
37
|
+
return output
|
|
38
|
+
.split('\n')
|
|
39
|
+
.map(r => r.trim().replace(/:$/, ''))
|
|
40
|
+
.filter(r => r.length > 0);
|
|
41
|
+
} catch (error) {
|
|
42
|
+
return [];
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Check remote exists
|
|
48
|
+
*/
|
|
49
|
+
remoteExists(remote) {
|
|
50
|
+
const remotes = this.getRemotes();
|
|
51
|
+
return remotes.includes(remote);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Show rclone setup instructions
|
|
56
|
+
*/
|
|
57
|
+
showSetupInstructions() {
|
|
58
|
+
console.log('');
|
|
59
|
+
console.log('\x1b[35m═══════════════════════════════════════════════════════════════════\x1b[0m');
|
|
60
|
+
console.log('\x1b[35m Cloud Backup Setup\x1b[0m');
|
|
61
|
+
console.log('\x1b[35m═══════════════════════════════════════════════════════════════════\x1b[0m');
|
|
62
|
+
console.log('');
|
|
63
|
+
|
|
64
|
+
if (!this.isRcloneInstalled()) {
|
|
65
|
+
console.log('\x1b[33m[!]\x1b[0m rclone is not installed.');
|
|
66
|
+
console.log('');
|
|
67
|
+
console.log('Install rclone:');
|
|
68
|
+
console.log('');
|
|
69
|
+
if (this.platform.isMac) {
|
|
70
|
+
console.log(' \x1b[36mbrew install rclone\x1b[0m');
|
|
71
|
+
} else if (this.platform.isLinux) {
|
|
72
|
+
console.log(' \x1b[36mcurl https://rclone.org/install.sh | sudo bash\x1b[0m');
|
|
73
|
+
} else {
|
|
74
|
+
console.log(' \x1b[36mwinget install Rclone.Rclone\x1b[0m');
|
|
75
|
+
}
|
|
76
|
+
console.log('');
|
|
77
|
+
console.log('Or visit: https://rclone.org/install/');
|
|
78
|
+
console.log('');
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
console.log('\x1b[32m[✓]\x1b[0m rclone is installed');
|
|
83
|
+
console.log('');
|
|
84
|
+
|
|
85
|
+
const remotes = this.getRemotes();
|
|
86
|
+
|
|
87
|
+
if (remotes.length === 0) {
|
|
88
|
+
console.log('\x1b[33m[!]\x1b[0m No cloud remotes configured.');
|
|
89
|
+
console.log('');
|
|
90
|
+
console.log('Configure a remote:');
|
|
91
|
+
console.log('');
|
|
92
|
+
console.log(' \x1b[36mrclone config\x1b[0m');
|
|
93
|
+
console.log('');
|
|
94
|
+
console.log('Popular options:');
|
|
95
|
+
console.log(' • Google Drive: Choose "drive"');
|
|
96
|
+
console.log(' • Dropbox: Choose "dropbox"');
|
|
97
|
+
console.log(' • OneDrive: Choose "onedrive"');
|
|
98
|
+
console.log(' • S3/Minio: Choose "s3"');
|
|
99
|
+
console.log(' • SFTP: Choose "sftp"');
|
|
100
|
+
console.log(' • FTP: Choose "ftp"');
|
|
101
|
+
console.log('');
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
console.log('Available remotes:');
|
|
106
|
+
console.log('');
|
|
107
|
+
for (const remote of remotes) {
|
|
108
|
+
console.log(` \x1b[36m${remote}\x1b[0m`);
|
|
109
|
+
}
|
|
110
|
+
console.log('');
|
|
111
|
+
console.log('Usage:');
|
|
112
|
+
console.log('');
|
|
113
|
+
console.log(` \x1b[36mnpx zuppaclaude backup --cloud ${remotes[0]}\x1b[0m`);
|
|
114
|
+
console.log(` \x1b[36mnpx zuppaclaude restore --cloud ${remotes[0]}\x1b[0m`);
|
|
115
|
+
console.log('');
|
|
116
|
+
|
|
117
|
+
return true;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* List remotes
|
|
122
|
+
*/
|
|
123
|
+
listRemotes() {
|
|
124
|
+
if (!this.isRcloneInstalled()) {
|
|
125
|
+
this.logger.error('rclone is not installed');
|
|
126
|
+
this.showSetupInstructions();
|
|
127
|
+
return [];
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const remotes = this.getRemotes();
|
|
131
|
+
|
|
132
|
+
if (remotes.length === 0) {
|
|
133
|
+
this.logger.warning('No remotes configured');
|
|
134
|
+
this.showSetupInstructions();
|
|
135
|
+
return [];
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
console.log('');
|
|
139
|
+
console.log('\x1b[35m═══════════════════════════════════════════════════════════════════\x1b[0m');
|
|
140
|
+
console.log('\x1b[35m Available Cloud Remotes\x1b[0m');
|
|
141
|
+
console.log('\x1b[35m═══════════════════════════════════════════════════════════════════\x1b[0m');
|
|
142
|
+
console.log('');
|
|
143
|
+
|
|
144
|
+
for (const remote of remotes) {
|
|
145
|
+
// Try to get remote type
|
|
146
|
+
let type = 'unknown';
|
|
147
|
+
try {
|
|
148
|
+
const config = this.platform.exec(`rclone config show ${remote}`, { silent: true });
|
|
149
|
+
const typeMatch = config?.match(/type\s*=\s*(\w+)/);
|
|
150
|
+
if (typeMatch) type = typeMatch[1];
|
|
151
|
+
} catch (e) {
|
|
152
|
+
// Ignore
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const icon = this.getRemoteIcon(type);
|
|
156
|
+
console.log(` ${icon} \x1b[36m${remote}\x1b[0m (${type})`);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
console.log('');
|
|
160
|
+
return remotes;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Get icon for remote type
|
|
165
|
+
*/
|
|
166
|
+
getRemoteIcon(type) {
|
|
167
|
+
const icons = {
|
|
168
|
+
'drive': '📁',
|
|
169
|
+
'dropbox': '📦',
|
|
170
|
+
'onedrive': '☁️',
|
|
171
|
+
's3': '🪣',
|
|
172
|
+
'sftp': '🔐',
|
|
173
|
+
'ftp': '📡',
|
|
174
|
+
'b2': '🅱️',
|
|
175
|
+
'box': '📥',
|
|
176
|
+
'mega': '🔷',
|
|
177
|
+
'pcloud': '☁️'
|
|
178
|
+
};
|
|
179
|
+
return icons[type] || '☁️';
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Upload backup to cloud
|
|
184
|
+
*/
|
|
185
|
+
async upload(remote, backupId = null) {
|
|
186
|
+
if (!this.isRcloneInstalled()) {
|
|
187
|
+
this.logger.error('rclone is not installed');
|
|
188
|
+
this.showSetupInstructions();
|
|
189
|
+
return false;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (!this.remoteExists(remote)) {
|
|
193
|
+
this.logger.error(`Remote not found: ${remote}`);
|
|
194
|
+
this.logger.info('Run "npx zuppaclaude cloud remotes" to see available remotes');
|
|
195
|
+
return false;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Determine what to upload
|
|
199
|
+
let sourcePath = this.backupDir;
|
|
200
|
+
let destPath = `${remote}:${this.cloudPath}`;
|
|
201
|
+
|
|
202
|
+
if (backupId) {
|
|
203
|
+
sourcePath = path.join(this.backupDir, backupId);
|
|
204
|
+
if (!fs.existsSync(sourcePath)) {
|
|
205
|
+
this.logger.error(`Backup not found: ${backupId}`);
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
destPath = `${remote}:${this.cloudPath}/${backupId}`;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if (!fs.existsSync(sourcePath)) {
|
|
212
|
+
this.logger.error('No backups to upload');
|
|
213
|
+
this.logger.info('Run "npx zuppaclaude backup" first');
|
|
214
|
+
return false;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
console.log('');
|
|
218
|
+
this.logger.step(`Uploading to ${remote}...`);
|
|
219
|
+
console.log('');
|
|
220
|
+
|
|
221
|
+
try {
|
|
222
|
+
// Use rclone sync for efficiency
|
|
223
|
+
const cmd = `rclone sync "${sourcePath}" "${destPath}" --progress`;
|
|
224
|
+
this.platform.exec(cmd, { silent: false, stdio: 'inherit' });
|
|
225
|
+
|
|
226
|
+
console.log('');
|
|
227
|
+
this.logger.success(`Backup uploaded to ${remote}:${this.cloudPath}`);
|
|
228
|
+
console.log('');
|
|
229
|
+
return true;
|
|
230
|
+
} catch (error) {
|
|
231
|
+
this.logger.error(`Upload failed: ${error.message}`);
|
|
232
|
+
return false;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Download backup from cloud
|
|
238
|
+
*/
|
|
239
|
+
async download(remote, backupId = null) {
|
|
240
|
+
if (!this.isRcloneInstalled()) {
|
|
241
|
+
this.logger.error('rclone is not installed');
|
|
242
|
+
this.showSetupInstructions();
|
|
243
|
+
return false;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if (!this.remoteExists(remote)) {
|
|
247
|
+
this.logger.error(`Remote not found: ${remote}`);
|
|
248
|
+
return false;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
let sourcePath = `${remote}:${this.cloudPath}`;
|
|
252
|
+
let destPath = this.backupDir;
|
|
253
|
+
|
|
254
|
+
if (backupId) {
|
|
255
|
+
sourcePath = `${remote}:${this.cloudPath}/${backupId}`;
|
|
256
|
+
destPath = path.join(this.backupDir, backupId);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
this.platform.ensureDir(destPath);
|
|
260
|
+
|
|
261
|
+
console.log('');
|
|
262
|
+
this.logger.step(`Downloading from ${remote}...`);
|
|
263
|
+
console.log('');
|
|
264
|
+
|
|
265
|
+
try {
|
|
266
|
+
const cmd = `rclone sync "${sourcePath}" "${destPath}" --progress`;
|
|
267
|
+
this.platform.exec(cmd, { silent: false, stdio: 'inherit' });
|
|
268
|
+
|
|
269
|
+
console.log('');
|
|
270
|
+
this.logger.success(`Backup downloaded from ${remote}`);
|
|
271
|
+
console.log('');
|
|
272
|
+
return true;
|
|
273
|
+
} catch (error) {
|
|
274
|
+
this.logger.error(`Download failed: ${error.message}`);
|
|
275
|
+
return false;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* List cloud backups
|
|
281
|
+
*/
|
|
282
|
+
async listCloudBackups(remote) {
|
|
283
|
+
if (!this.isRcloneInstalled()) {
|
|
284
|
+
this.logger.error('rclone is not installed');
|
|
285
|
+
return [];
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
if (!this.remoteExists(remote)) {
|
|
289
|
+
this.logger.error(`Remote not found: ${remote}`);
|
|
290
|
+
return [];
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
try {
|
|
294
|
+
const cmd = `rclone lsd "${remote}:${this.cloudPath}" 2>/dev/null`;
|
|
295
|
+
const output = this.platform.exec(cmd, { silent: true });
|
|
296
|
+
|
|
297
|
+
if (!output) {
|
|
298
|
+
this.logger.warning('No cloud backups found');
|
|
299
|
+
return [];
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
const backups = output
|
|
303
|
+
.split('\n')
|
|
304
|
+
.filter(line => line.trim())
|
|
305
|
+
.map(line => {
|
|
306
|
+
const parts = line.trim().split(/\s+/);
|
|
307
|
+
const name = parts[parts.length - 1];
|
|
308
|
+
return name;
|
|
309
|
+
})
|
|
310
|
+
.filter(name => name && name.match(/^\d{4}-\d{2}-\d{2}T/));
|
|
311
|
+
|
|
312
|
+
console.log('');
|
|
313
|
+
console.log('\x1b[35m═══════════════════════════════════════════════════════════════════\x1b[0m');
|
|
314
|
+
console.log(`\x1b[35m Cloud Backups (${remote})\x1b[0m`);
|
|
315
|
+
console.log('\x1b[35m═══════════════════════════════════════════════════════════════════\x1b[0m');
|
|
316
|
+
console.log('');
|
|
317
|
+
|
|
318
|
+
if (backups.length === 0) {
|
|
319
|
+
console.log(' No backups found');
|
|
320
|
+
} else {
|
|
321
|
+
for (const backup of backups) {
|
|
322
|
+
console.log(` 📦 ${backup}`);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
console.log('');
|
|
327
|
+
return backups;
|
|
328
|
+
} catch (error) {
|
|
329
|
+
this.logger.warning('Could not list cloud backups');
|
|
330
|
+
return [];
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
module.exports = { CloudManager };
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ZuppaClaude Commands Installer
|
|
3
|
+
* Installs /zc:* slash commands for Claude Code
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
const { Logger } = require('../utils/logger');
|
|
9
|
+
const { Platform } = require('../utils/platform');
|
|
10
|
+
|
|
11
|
+
class CommandsInstaller {
|
|
12
|
+
constructor() {
|
|
13
|
+
this.platform = new Platform();
|
|
14
|
+
this.logger = new Logger();
|
|
15
|
+
this.commandsDir = path.join(this.platform.claudeDir, 'commands', 'zc');
|
|
16
|
+
this.sourceDir = path.join(__dirname, '..', '..', 'assets', 'commands', 'zc');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Check if commands are installed
|
|
21
|
+
*/
|
|
22
|
+
isInstalled() {
|
|
23
|
+
return fs.existsSync(this.commandsDir) &&
|
|
24
|
+
fs.existsSync(path.join(this.commandsDir, 'help.md'));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Install ZuppaClaude commands
|
|
29
|
+
*/
|
|
30
|
+
async install() {
|
|
31
|
+
this.logger.step('Installing ZuppaClaude Slash Commands');
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
// Ensure commands directory exists
|
|
35
|
+
this.platform.ensureDir(this.commandsDir);
|
|
36
|
+
|
|
37
|
+
// Get list of command files
|
|
38
|
+
const files = fs.readdirSync(this.sourceDir);
|
|
39
|
+
|
|
40
|
+
let installed = 0;
|
|
41
|
+
for (const file of files) {
|
|
42
|
+
if (!file.endsWith('.md')) continue;
|
|
43
|
+
|
|
44
|
+
const srcPath = path.join(this.sourceDir, file);
|
|
45
|
+
const destPath = path.join(this.commandsDir, file);
|
|
46
|
+
|
|
47
|
+
try {
|
|
48
|
+
fs.copyFileSync(srcPath, destPath);
|
|
49
|
+
installed++;
|
|
50
|
+
} catch (error) {
|
|
51
|
+
this.logger.warning(`Failed to install ${file}: ${error.message}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
this.logger.success(`Installed ${installed} slash commands`);
|
|
56
|
+
this.logger.info('Commands available: /zc:backup, /zc:restore, /zc:cloud, /zc:session, /zc:settings, /zc:help');
|
|
57
|
+
|
|
58
|
+
return true;
|
|
59
|
+
} catch (error) {
|
|
60
|
+
this.logger.error(`Failed to install commands: ${error.message}`);
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Uninstall commands
|
|
67
|
+
*/
|
|
68
|
+
uninstall() {
|
|
69
|
+
if (!fs.existsSync(this.commandsDir)) {
|
|
70
|
+
this.logger.info('ZuppaClaude commands not found');
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
try {
|
|
75
|
+
fs.rmSync(this.commandsDir, { recursive: true });
|
|
76
|
+
this.logger.success('ZuppaClaude commands removed');
|
|
77
|
+
return true;
|
|
78
|
+
} catch (error) {
|
|
79
|
+
this.logger.error(`Failed to remove commands: ${error.message}`);
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Verify installation
|
|
86
|
+
*/
|
|
87
|
+
verify() {
|
|
88
|
+
if (this.isInstalled()) {
|
|
89
|
+
this.logger.success('ZuppaClaude Commands: Installed');
|
|
90
|
+
|
|
91
|
+
// Count installed commands
|
|
92
|
+
try {
|
|
93
|
+
const files = fs.readdirSync(this.commandsDir)
|
|
94
|
+
.filter(f => f.endsWith('.md') && f !== 'README.md');
|
|
95
|
+
this.logger.info(`Available: /zc:${files.map(f => f.replace('.md', '')).join(', /zc:')}`);
|
|
96
|
+
} catch (e) {
|
|
97
|
+
// Ignore
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return true;
|
|
101
|
+
} else {
|
|
102
|
+
this.logger.warning('ZuppaClaude Commands: Not installed');
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* List available commands
|
|
109
|
+
*/
|
|
110
|
+
list() {
|
|
111
|
+
console.log('');
|
|
112
|
+
console.log('\x1b[35m═══════════════════════════════════════════════════════════════════\x1b[0m');
|
|
113
|
+
console.log('\x1b[35m ZuppaClaude Commands\x1b[0m');
|
|
114
|
+
console.log('\x1b[35m═══════════════════════════════════════════════════════════════════\x1b[0m');
|
|
115
|
+
console.log('');
|
|
116
|
+
|
|
117
|
+
const commands = [
|
|
118
|
+
{ cmd: '/zc:backup', desc: 'Full backup (sessions + settings + cloud)' },
|
|
119
|
+
{ cmd: '/zc:restore', desc: 'Restore from backup' },
|
|
120
|
+
{ cmd: '/zc:cloud', desc: 'Cloud backup management' },
|
|
121
|
+
{ cmd: '/zc:session', desc: 'Session management' },
|
|
122
|
+
{ cmd: '/zc:settings', desc: 'Settings management' },
|
|
123
|
+
{ cmd: '/zc:help', desc: 'Show help' }
|
|
124
|
+
];
|
|
125
|
+
|
|
126
|
+
for (const { cmd, desc } of commands) {
|
|
127
|
+
console.log(` \x1b[36m${cmd.padEnd(18)}\x1b[0m ${desc}`);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
console.log('');
|
|
131
|
+
console.log('Usage:');
|
|
132
|
+
console.log(' Type the command in Claude Code chat, e.g., /zc:backup');
|
|
133
|
+
console.log('');
|
|
134
|
+
|
|
135
|
+
return commands;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
module.exports = { CommandsInstaller };
|
package/lib/components/index.js
CHANGED
|
@@ -8,6 +8,9 @@ const { ConfigInstaller } = require('./config');
|
|
|
8
8
|
const { ClaudeZInstaller } = require('./claudez');
|
|
9
9
|
const { ClaudeHUDInstaller } = require('./claudehud');
|
|
10
10
|
const { SessionManager } = require('./session');
|
|
11
|
+
const { CloudManager } = require('./cloud');
|
|
12
|
+
const { BackupManager } = require('./backup');
|
|
13
|
+
const { CommandsInstaller } = require('./commands');
|
|
11
14
|
|
|
12
15
|
module.exports = {
|
|
13
16
|
SuperClaudeInstaller,
|
|
@@ -15,5 +18,8 @@ module.exports = {
|
|
|
15
18
|
ConfigInstaller,
|
|
16
19
|
ClaudeZInstaller,
|
|
17
20
|
ClaudeHUDInstaller,
|
|
18
|
-
SessionManager
|
|
21
|
+
SessionManager,
|
|
22
|
+
CloudManager,
|
|
23
|
+
BackupManager,
|
|
24
|
+
CommandsInstaller
|
|
19
25
|
};
|
package/lib/installer.js
CHANGED
|
@@ -11,7 +11,8 @@ const {
|
|
|
11
11
|
SpecKitInstaller,
|
|
12
12
|
ConfigInstaller,
|
|
13
13
|
ClaudeZInstaller,
|
|
14
|
-
ClaudeHUDInstaller
|
|
14
|
+
ClaudeHUDInstaller,
|
|
15
|
+
CommandsInstaller
|
|
15
16
|
} = require('./components');
|
|
16
17
|
|
|
17
18
|
class Installer {
|
|
@@ -27,6 +28,7 @@ class Installer {
|
|
|
27
28
|
this.config = new ConfigInstaller();
|
|
28
29
|
this.claudeZ = new ClaudeZInstaller();
|
|
29
30
|
this.claudeHUD = new ClaudeHUDInstaller();
|
|
31
|
+
this.commands = new CommandsInstaller();
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
/**
|
|
@@ -36,7 +38,7 @@ class Installer {
|
|
|
36
38
|
this.logger.banner();
|
|
37
39
|
|
|
38
40
|
// Step 1: Check dependencies
|
|
39
|
-
this.logger.step('Step 1/
|
|
41
|
+
this.logger.step('Step 1/8: Checking Dependencies');
|
|
40
42
|
const depsOk = await this.checkDependencies();
|
|
41
43
|
if (!depsOk) {
|
|
42
44
|
this.logger.error('Dependency check failed. Please install required dependencies.');
|
|
@@ -110,8 +112,12 @@ class Installer {
|
|
|
110
112
|
this.logger.info('Skipping Claude HUD installation');
|
|
111
113
|
}
|
|
112
114
|
|
|
113
|
-
// Step 7:
|
|
114
|
-
this.logger.step('Step 7/
|
|
115
|
+
// Step 7: Install ZuppaClaude Commands
|
|
116
|
+
this.logger.step('Step 7/8: Installing ZuppaClaude Slash Commands');
|
|
117
|
+
const cmdsInstalled = await this.commands.install();
|
|
118
|
+
|
|
119
|
+
// Step 8: Verification
|
|
120
|
+
this.logger.step('Step 8/8: Verifying Installation');
|
|
115
121
|
console.log('');
|
|
116
122
|
|
|
117
123
|
this.superClaude.verify();
|
|
@@ -119,6 +125,7 @@ class Installer {
|
|
|
119
125
|
this.config.verify();
|
|
120
126
|
if (installClaudeZ) this.claudeZ.verify();
|
|
121
127
|
if (installClaudeHUD) this.claudeHUD.verify();
|
|
128
|
+
this.commands.verify();
|
|
122
129
|
|
|
123
130
|
// Save settings
|
|
124
131
|
const newSettings = {
|
|
@@ -139,7 +146,8 @@ class Installer {
|
|
|
139
146
|
specKit: skInstalled,
|
|
140
147
|
config: cfgInstalled,
|
|
141
148
|
claudeZ: czInstalled,
|
|
142
|
-
claudeHUD: hudInstalled
|
|
149
|
+
claudeHUD: hudInstalled,
|
|
150
|
+
commands: cmdsInstalled
|
|
143
151
|
});
|
|
144
152
|
|
|
145
153
|
return true;
|
|
@@ -205,7 +213,8 @@ class Installer {
|
|
|
205
213
|
{ name: 'Spec Kit', installed: results.specKit },
|
|
206
214
|
{ name: 'CLAUDE.md', installed: results.config },
|
|
207
215
|
{ name: 'Claude-Z', installed: results.claudeZ },
|
|
208
|
-
{ name: 'Claude HUD', installed: results.claudeHUD }
|
|
216
|
+
{ name: 'Claude HUD', installed: results.claudeHUD },
|
|
217
|
+
{ name: 'ZC Commands', installed: results.commands }
|
|
209
218
|
];
|
|
210
219
|
|
|
211
220
|
let installed = 0;
|
|
@@ -223,7 +232,14 @@ class Installer {
|
|
|
223
232
|
console.log(' Next steps:');
|
|
224
233
|
console.log(' 1. Restart your terminal or run: source ~/.bashrc');
|
|
225
234
|
console.log(' 2. Start Claude Code: claude');
|
|
226
|
-
console.log(' 3. Try: /sc:help');
|
|
235
|
+
console.log(' 3. Try: /sc:help or /zc:help');
|
|
236
|
+
console.log('');
|
|
237
|
+
|
|
238
|
+
console.log(' ZuppaClaude commands:');
|
|
239
|
+
console.log(' /zc:backup - Full backup (sessions + settings)');
|
|
240
|
+
console.log(' /zc:restore - Restore from backup');
|
|
241
|
+
console.log(' /zc:cloud - Cloud backup management');
|
|
242
|
+
console.log(' /zc:help - Show all commands');
|
|
227
243
|
console.log('');
|
|
228
244
|
|
|
229
245
|
if (results.claudeZ) {
|
package/lib/uninstaller.js
CHANGED
|
@@ -10,7 +10,8 @@ const {
|
|
|
10
10
|
SpecKitInstaller,
|
|
11
11
|
ConfigInstaller,
|
|
12
12
|
ClaudeZInstaller,
|
|
13
|
-
ClaudeHUDInstaller
|
|
13
|
+
ClaudeHUDInstaller,
|
|
14
|
+
CommandsInstaller
|
|
14
15
|
} = require('./components');
|
|
15
16
|
|
|
16
17
|
class Uninstaller {
|
|
@@ -25,6 +26,7 @@ class Uninstaller {
|
|
|
25
26
|
this.config = new ConfigInstaller();
|
|
26
27
|
this.claudeZ = new ClaudeZInstaller();
|
|
27
28
|
this.claudeHUD = new ClaudeHUDInstaller();
|
|
29
|
+
this.commands = new CommandsInstaller();
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
/**
|
|
@@ -57,7 +59,8 @@ class Uninstaller {
|
|
|
57
59
|
specKit: this.specKit.uninstall(),
|
|
58
60
|
config: this.config.uninstall(),
|
|
59
61
|
claudeZ: this.claudeZ.uninstall(),
|
|
60
|
-
claudeHUD: this.claudeHUD.uninstall()
|
|
62
|
+
claudeHUD: this.claudeHUD.uninstall(),
|
|
63
|
+
commands: this.commands.uninstall()
|
|
61
64
|
};
|
|
62
65
|
|
|
63
66
|
// Handle settings
|
|
@@ -89,7 +92,8 @@ class Uninstaller {
|
|
|
89
92
|
{ name: 'Spec Kit', removed: results.specKit },
|
|
90
93
|
{ name: 'CLAUDE.md', removed: results.config },
|
|
91
94
|
{ name: 'Claude-Z', removed: results.claudeZ },
|
|
92
|
-
{ name: 'Claude HUD', removed: results.claudeHUD }
|
|
95
|
+
{ name: 'Claude HUD', removed: results.claudeHUD },
|
|
96
|
+
{ name: 'ZC Commands', removed: results.commands }
|
|
93
97
|
];
|
|
94
98
|
|
|
95
99
|
let removed = 0;
|