zuppaclaude 1.3.3 → 1.3.4
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/zuppaclaude.js +71 -0
- package/lib/components/index.js +3 -1
- package/lib/components/updater.js +216 -0
- package/package.json +1 -1
package/bin/zuppaclaude.js
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
const { Installer } = require('../lib/installer');
|
|
9
9
|
const { Settings } = require('../lib/settings');
|
|
10
10
|
const { Logger } = require('../lib/utils/logger');
|
|
11
|
+
const { UpdateManager } = require('../lib/components/updater');
|
|
11
12
|
|
|
12
13
|
const args = process.argv.slice(2);
|
|
13
14
|
const command = args[0] || 'install';
|
|
@@ -23,11 +24,26 @@ function getCloudArg(args) {
|
|
|
23
24
|
return null;
|
|
24
25
|
}
|
|
25
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Check for updates at startup (non-blocking for some commands)
|
|
29
|
+
*/
|
|
30
|
+
async function checkUpdates(skipCommands = ['version', 'v', '-v', '--version', 'help', 'h', '-h', '--help', 'update']) {
|
|
31
|
+
if (skipCommands.includes(command)) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const updater = new UpdateManager();
|
|
36
|
+
await updater.checkAndUpdate();
|
|
37
|
+
}
|
|
38
|
+
|
|
26
39
|
async function main() {
|
|
27
40
|
const logger = new Logger();
|
|
28
41
|
|
|
29
42
|
logger.banner();
|
|
30
43
|
|
|
44
|
+
// Check for updates at startup
|
|
45
|
+
await checkUpdates();
|
|
46
|
+
|
|
31
47
|
try {
|
|
32
48
|
switch (command) {
|
|
33
49
|
case 'install':
|
|
@@ -192,6 +208,37 @@ async function main() {
|
|
|
192
208
|
}
|
|
193
209
|
break;
|
|
194
210
|
|
|
211
|
+
case 'update':
|
|
212
|
+
const updateMgr = new UpdateManager();
|
|
213
|
+
const updateCmd = args[1] || 'check';
|
|
214
|
+
|
|
215
|
+
switch (updateCmd) {
|
|
216
|
+
case 'check':
|
|
217
|
+
await updateMgr.status();
|
|
218
|
+
break;
|
|
219
|
+
case 'now':
|
|
220
|
+
case 'install':
|
|
221
|
+
const result = await updateMgr.checkForUpdates();
|
|
222
|
+
if (result.hasUpdate) {
|
|
223
|
+
await updateMgr.update();
|
|
224
|
+
} else {
|
|
225
|
+
logger.success('You are already on the latest version');
|
|
226
|
+
}
|
|
227
|
+
break;
|
|
228
|
+
case 'enable':
|
|
229
|
+
case 'on':
|
|
230
|
+
updateMgr.enableAutoUpdate();
|
|
231
|
+
break;
|
|
232
|
+
case 'disable':
|
|
233
|
+
case 'off':
|
|
234
|
+
updateMgr.disableAutoUpdate();
|
|
235
|
+
break;
|
|
236
|
+
default:
|
|
237
|
+
logger.error(`Unknown update command: ${updateCmd}`);
|
|
238
|
+
showUpdateHelp();
|
|
239
|
+
}
|
|
240
|
+
break;
|
|
241
|
+
|
|
195
242
|
case 'version':
|
|
196
243
|
case 'v':
|
|
197
244
|
case '-v':
|
|
@@ -233,6 +280,7 @@ Commands:
|
|
|
233
280
|
settings, s Manage settings
|
|
234
281
|
session Manage Claude Code sessions
|
|
235
282
|
cloud Manage cloud remotes (rclone)
|
|
283
|
+
update Check for updates and manage auto-update
|
|
236
284
|
version, v Show version
|
|
237
285
|
help, h Show this help
|
|
238
286
|
|
|
@@ -249,6 +297,12 @@ Cloud Commands:
|
|
|
249
297
|
cloud download <r> Download backups from remote
|
|
250
298
|
cloud backups <r> List cloud backups
|
|
251
299
|
|
|
300
|
+
Update Commands:
|
|
301
|
+
update Check for updates
|
|
302
|
+
update now Update to latest version
|
|
303
|
+
update enable Enable auto-update (default)
|
|
304
|
+
update disable Disable auto-update
|
|
305
|
+
|
|
252
306
|
Session Commands:
|
|
253
307
|
session list List all sessions
|
|
254
308
|
session backup Backup sessions only
|
|
@@ -262,6 +316,7 @@ Examples:
|
|
|
262
316
|
npx zuppaclaude backup --cloud gdrive # Backup to Google Drive
|
|
263
317
|
npx zuppaclaude restore 2026-01-05T12-00-00 # Restore from backup
|
|
264
318
|
npx zuppaclaude cloud setup # Configure cloud
|
|
319
|
+
npx zuppaclaude update # Check for updates
|
|
265
320
|
`);
|
|
266
321
|
}
|
|
267
322
|
|
|
@@ -321,4 +376,20 @@ Supported providers (via rclone):
|
|
|
321
376
|
`);
|
|
322
377
|
}
|
|
323
378
|
|
|
379
|
+
function showUpdateHelp() {
|
|
380
|
+
console.log(`
|
|
381
|
+
Update Commands:
|
|
382
|
+
check Check for updates (default)
|
|
383
|
+
now Update to latest version immediately
|
|
384
|
+
enable Enable auto-update at startup
|
|
385
|
+
disable Disable auto-update
|
|
386
|
+
|
|
387
|
+
Examples:
|
|
388
|
+
zuppaclaude update # Check for updates
|
|
389
|
+
zuppaclaude update now # Update immediately
|
|
390
|
+
zuppaclaude update enable # Enable auto-update
|
|
391
|
+
zuppaclaude update disable # Disable auto-update
|
|
392
|
+
`);
|
|
393
|
+
}
|
|
394
|
+
|
|
324
395
|
main();
|
package/lib/components/index.js
CHANGED
|
@@ -11,6 +11,7 @@ const { SessionManager } = require('./session');
|
|
|
11
11
|
const { CloudManager } = require('./cloud');
|
|
12
12
|
const { BackupManager } = require('./backup');
|
|
13
13
|
const { CommandsInstaller } = require('./commands');
|
|
14
|
+
const { UpdateManager } = require('./updater');
|
|
14
15
|
|
|
15
16
|
module.exports = {
|
|
16
17
|
SuperClaudeInstaller,
|
|
@@ -21,5 +22,6 @@ module.exports = {
|
|
|
21
22
|
SessionManager,
|
|
22
23
|
CloudManager,
|
|
23
24
|
BackupManager,
|
|
24
|
-
CommandsInstaller
|
|
25
|
+
CommandsInstaller,
|
|
26
|
+
UpdateManager
|
|
25
27
|
};
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-Update Manager
|
|
3
|
+
* Checks for updates and auto-updates if enabled
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const { execSync } = require('child_process');
|
|
7
|
+
const https = require('https');
|
|
8
|
+
const { Logger } = require('../utils/logger');
|
|
9
|
+
const { Settings } = require('../settings');
|
|
10
|
+
|
|
11
|
+
class UpdateManager {
|
|
12
|
+
constructor() {
|
|
13
|
+
this.logger = new Logger();
|
|
14
|
+
this.settings = new Settings();
|
|
15
|
+
this.packageName = 'zuppaclaude';
|
|
16
|
+
this.currentVersion = require('../../package.json').version;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Get latest version from npm
|
|
21
|
+
*/
|
|
22
|
+
async getLatestVersion() {
|
|
23
|
+
return new Promise((resolve, reject) => {
|
|
24
|
+
const url = `https://registry.npmjs.org/${this.packageName}/latest`;
|
|
25
|
+
|
|
26
|
+
https.get(url, (res) => {
|
|
27
|
+
let data = '';
|
|
28
|
+
|
|
29
|
+
res.on('data', (chunk) => {
|
|
30
|
+
data += chunk;
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
res.on('end', () => {
|
|
34
|
+
try {
|
|
35
|
+
const json = JSON.parse(data);
|
|
36
|
+
resolve(json.version);
|
|
37
|
+
} catch (e) {
|
|
38
|
+
reject(e);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
}).on('error', (err) => {
|
|
42
|
+
reject(err);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Compare versions (returns true if latest > current)
|
|
49
|
+
*/
|
|
50
|
+
isNewerVersion(latest, current) {
|
|
51
|
+
const latestParts = latest.split('.').map(Number);
|
|
52
|
+
const currentParts = current.split('.').map(Number);
|
|
53
|
+
|
|
54
|
+
for (let i = 0; i < 3; i++) {
|
|
55
|
+
if (latestParts[i] > currentParts[i]) return true;
|
|
56
|
+
if (latestParts[i] < currentParts[i]) return false;
|
|
57
|
+
}
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Check for updates
|
|
63
|
+
*/
|
|
64
|
+
async checkForUpdates(silent = false) {
|
|
65
|
+
try {
|
|
66
|
+
const latestVersion = await this.getLatestVersion();
|
|
67
|
+
const hasUpdate = this.isNewerVersion(latestVersion, this.currentVersion);
|
|
68
|
+
|
|
69
|
+
if (hasUpdate && !silent) {
|
|
70
|
+
console.log('');
|
|
71
|
+
console.log('\x1b[33m╔═══════════════════════════════════════════════════════════════════╗\x1b[0m');
|
|
72
|
+
console.log('\x1b[33m║ Update Available! ║\x1b[0m');
|
|
73
|
+
console.log('\x1b[33m╚═══════════════════════════════════════════════════════════════════╝\x1b[0m');
|
|
74
|
+
console.log('');
|
|
75
|
+
console.log(` Current version: \x1b[31m${this.currentVersion}\x1b[0m`);
|
|
76
|
+
console.log(` Latest version: \x1b[32m${latestVersion}\x1b[0m`);
|
|
77
|
+
console.log('');
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
hasUpdate,
|
|
82
|
+
currentVersion: this.currentVersion,
|
|
83
|
+
latestVersion
|
|
84
|
+
};
|
|
85
|
+
} catch (error) {
|
|
86
|
+
// Silently fail - don't interrupt user workflow
|
|
87
|
+
return {
|
|
88
|
+
hasUpdate: false,
|
|
89
|
+
currentVersion: this.currentVersion,
|
|
90
|
+
latestVersion: null,
|
|
91
|
+
error: error.message
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Update to latest version
|
|
98
|
+
*/
|
|
99
|
+
async update() {
|
|
100
|
+
try {
|
|
101
|
+
this.logger.step('Updating ZuppaClaude...');
|
|
102
|
+
|
|
103
|
+
// Use npm to update globally
|
|
104
|
+
execSync(`npm install -g ${this.packageName}@latest`, {
|
|
105
|
+
stdio: 'inherit'
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// Verify update
|
|
109
|
+
const newVersion = await this.getLatestVersion();
|
|
110
|
+
this.logger.success(`Updated to v${newVersion}`);
|
|
111
|
+
|
|
112
|
+
return true;
|
|
113
|
+
} catch (error) {
|
|
114
|
+
this.logger.error(`Update failed: ${error.message}`);
|
|
115
|
+
this.logger.info(`Manual update: npm install -g ${this.packageName}@latest`);
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Check and auto-update if enabled
|
|
122
|
+
* Called at startup
|
|
123
|
+
*/
|
|
124
|
+
async checkAndUpdate() {
|
|
125
|
+
const userSettings = this.settings.load() || {};
|
|
126
|
+
const autoUpdate = userSettings.autoUpdate !== false; // Default true
|
|
127
|
+
|
|
128
|
+
const result = await this.checkForUpdates(true);
|
|
129
|
+
|
|
130
|
+
if (result.hasUpdate) {
|
|
131
|
+
if (autoUpdate) {
|
|
132
|
+
console.log('');
|
|
133
|
+
console.log(`\x1b[36m[i]\x1b[0m New version available: v${result.latestVersion}`);
|
|
134
|
+
console.log('\x1b[36m[i]\x1b[0m Auto-updating...');
|
|
135
|
+
console.log('');
|
|
136
|
+
|
|
137
|
+
const updated = await this.update();
|
|
138
|
+
|
|
139
|
+
if (updated) {
|
|
140
|
+
console.log('');
|
|
141
|
+
console.log('\x1b[32m[✓]\x1b[0m Update complete! Please restart to use the new version.');
|
|
142
|
+
console.log('');
|
|
143
|
+
return { updated: true, version: result.latestVersion };
|
|
144
|
+
}
|
|
145
|
+
} else {
|
|
146
|
+
// Just notify
|
|
147
|
+
console.log('');
|
|
148
|
+
console.log(`\x1b[33m[!]\x1b[0m Update available: v${this.currentVersion} → v${result.latestVersion}`);
|
|
149
|
+
console.log(`\x1b[33m[!]\x1b[0m Run: npm install -g ${this.packageName}@latest`);
|
|
150
|
+
console.log('');
|
|
151
|
+
return { updated: false, version: result.latestVersion };
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return { updated: false, version: this.currentVersion };
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Enable auto-update
|
|
160
|
+
*/
|
|
161
|
+
enableAutoUpdate() {
|
|
162
|
+
const userSettings = this.settings.load() || {};
|
|
163
|
+
userSettings.autoUpdate = true;
|
|
164
|
+
this.settings.save(userSettings);
|
|
165
|
+
this.logger.success('Auto-update enabled');
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Disable auto-update
|
|
170
|
+
*/
|
|
171
|
+
disableAutoUpdate() {
|
|
172
|
+
const userSettings = this.settings.load() || {};
|
|
173
|
+
userSettings.autoUpdate = false;
|
|
174
|
+
this.settings.save(userSettings);
|
|
175
|
+
this.logger.success('Auto-update disabled');
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Show update status
|
|
180
|
+
*/
|
|
181
|
+
async status() {
|
|
182
|
+
const userSettings = this.settings.load() || {};
|
|
183
|
+
const autoUpdate = userSettings.autoUpdate !== false;
|
|
184
|
+
|
|
185
|
+
console.log('');
|
|
186
|
+
console.log('\x1b[35m═══════════════════════════════════════════════════════════════════\x1b[0m');
|
|
187
|
+
console.log('\x1b[35m Update Status\x1b[0m');
|
|
188
|
+
console.log('\x1b[35m═══════════════════════════════════════════════════════════════════\x1b[0m');
|
|
189
|
+
console.log('');
|
|
190
|
+
console.log(` Current version: \x1b[36m${this.currentVersion}\x1b[0m`);
|
|
191
|
+
console.log(` Auto-update: ${autoUpdate ? '\x1b[32menabled\x1b[0m' : '\x1b[31mdisabled\x1b[0m'}`);
|
|
192
|
+
console.log('');
|
|
193
|
+
|
|
194
|
+
this.logger.info('Checking for updates...');
|
|
195
|
+
const result = await this.checkForUpdates(true);
|
|
196
|
+
|
|
197
|
+
if (result.latestVersion) {
|
|
198
|
+
console.log(` Latest version: \x1b[36m${result.latestVersion}\x1b[0m`);
|
|
199
|
+
|
|
200
|
+
if (result.hasUpdate) {
|
|
201
|
+
console.log('');
|
|
202
|
+
console.log(' \x1b[33mUpdate available!\x1b[0m');
|
|
203
|
+
console.log(` Run: \x1b[36mnpm install -g ${this.packageName}@latest\x1b[0m`);
|
|
204
|
+
} else {
|
|
205
|
+
console.log('');
|
|
206
|
+
console.log(' \x1b[32mYou are up to date!\x1b[0m');
|
|
207
|
+
}
|
|
208
|
+
} else {
|
|
209
|
+
console.log(' \x1b[31mCould not check for updates\x1b[0m');
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
console.log('');
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
module.exports = { UpdateManager };
|