@plexor-dev/claude-code-plugin-staging 0.1.0-beta.23 → 0.1.0-beta.25
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/commands/plexor-setup.js +51 -10
- package/commands/plexor-status.js +80 -10
- package/commands/plexor-uninstall.js +74 -22
- package/hooks/session-sync.js +194 -0
- package/hooks/statusline.js +130 -0
- package/lib/config-utils.js +25 -0
- package/lib/hooks-manager.js +209 -0
- package/lib/plexor-client.js +1 -1
- package/lib/settings-manager.js +5 -1
- package/lib/statusline-manager.js +135 -0
- package/package.json +1 -1
- package/scripts/postinstall.js +73 -14
- package/scripts/uninstall.js +80 -29
package/scripts/postinstall.js
CHANGED
|
@@ -11,6 +11,8 @@ const fs = require('fs');
|
|
|
11
11
|
const path = require('path');
|
|
12
12
|
const os = require('os');
|
|
13
13
|
const { execSync } = require('child_process');
|
|
14
|
+
const { upsertManagedStatusLine } = require('../lib/statusline-manager');
|
|
15
|
+
const { upsertManagedHooks, cleanupLegacyManagedHooksFile } = require('../lib/hooks-manager');
|
|
14
16
|
|
|
15
17
|
/**
|
|
16
18
|
* Resolve the home directory for a given username by querying /etc/passwd.
|
|
@@ -137,12 +139,16 @@ function chownRecursive(dirPath, uid, gid) {
|
|
|
137
139
|
|
|
138
140
|
const HOME_DIR = getHomeDir();
|
|
139
141
|
const COMMANDS_SOURCE = path.join(__dirname, '..', 'commands');
|
|
142
|
+
const HOOKS_SOURCE = path.join(__dirname, '..', 'hooks');
|
|
140
143
|
const LIB_SOURCE = path.join(__dirname, '..', 'lib');
|
|
141
144
|
const CLAUDE_COMMANDS_DIR = path.join(HOME_DIR, '.claude', 'commands');
|
|
142
145
|
const PLEXOR_PLUGINS_DIR = path.join(HOME_DIR, '.claude', 'plugins', 'plexor', 'commands');
|
|
146
|
+
const PLEXOR_HOOKS_DIR = path.join(HOME_DIR, '.claude', 'plugins', 'plexor', 'hooks');
|
|
143
147
|
const PLEXOR_LIB_DIR = path.join(HOME_DIR, '.claude', 'plugins', 'plexor', 'lib');
|
|
144
148
|
const PLEXOR_CONFIG_DIR = path.join(HOME_DIR, '.plexor');
|
|
145
149
|
const PLEXOR_CONFIG_FILE = path.join(PLEXOR_CONFIG_DIR, 'config.json');
|
|
150
|
+
const CLAUDE_SETTINGS_FILE = path.join(HOME_DIR, '.claude', 'settings.json');
|
|
151
|
+
const CLAUDE_LEGACY_HOOKS_FILE = path.join(HOME_DIR, '.claude', 'hooks.json');
|
|
146
152
|
|
|
147
153
|
/**
|
|
148
154
|
* Check if a base URL is a Plexor-managed gateway URL.
|
|
@@ -199,33 +205,41 @@ function syncManagedAuthEnv(env, managedAuthKey) {
|
|
|
199
205
|
env.ANTHROPIC_AUTH_TOKEN = managedAuthKey;
|
|
200
206
|
}
|
|
201
207
|
|
|
208
|
+
function writeJsonAtomically(filePath, value) {
|
|
209
|
+
const tempPath = `${filePath}.tmp.${Date.now()}`;
|
|
210
|
+
fs.writeFileSync(tempPath, JSON.stringify(value, null, 2), { mode: 0o600 });
|
|
211
|
+
fs.renameSync(tempPath, filePath);
|
|
212
|
+
}
|
|
213
|
+
|
|
202
214
|
function syncManagedPrimaryApiKey(env, managedAuthKey) {
|
|
203
215
|
const statePath = path.join(HOME_DIR, '.claude.json');
|
|
204
216
|
try {
|
|
205
217
|
if (!fs.existsSync(statePath)) {
|
|
206
|
-
return false;
|
|
218
|
+
return { changed: false };
|
|
207
219
|
}
|
|
208
220
|
|
|
209
221
|
const data = fs.readFileSync(statePath, 'utf8');
|
|
210
222
|
if (!data || !data.trim()) {
|
|
211
|
-
return false;
|
|
223
|
+
return { changed: false };
|
|
212
224
|
}
|
|
213
225
|
|
|
214
226
|
const claudeState = JSON.parse(data);
|
|
215
227
|
const primaryApiKey = claudeState.primaryApiKey || '';
|
|
216
228
|
if (!primaryApiKey || primaryApiKey.startsWith('plx_') || primaryApiKey === managedAuthKey) {
|
|
217
|
-
return false;
|
|
229
|
+
return { changed: false };
|
|
218
230
|
}
|
|
219
231
|
|
|
220
232
|
env[PREVIOUS_PRIMARY_API_KEY_ENV] = primaryApiKey;
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
233
|
+
const nextClaudeState = { ...claudeState };
|
|
234
|
+
delete nextClaudeState.primaryApiKey;
|
|
235
|
+
|
|
236
|
+
return {
|
|
237
|
+
changed: true,
|
|
238
|
+
statePath,
|
|
239
|
+
claudeState: nextClaudeState
|
|
240
|
+
};
|
|
227
241
|
} catch {
|
|
228
|
-
return false;
|
|
242
|
+
return { changed: false };
|
|
229
243
|
}
|
|
230
244
|
}
|
|
231
245
|
|
|
@@ -240,6 +254,7 @@ function checkOrphanedRouting() {
|
|
|
240
254
|
const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8'));
|
|
241
255
|
const env = settings.env || {};
|
|
242
256
|
let settingsChanged = false;
|
|
257
|
+
let managedPrimaryApiKeySync = null;
|
|
243
258
|
|
|
244
259
|
const hasPlexorUrl = isManagedGatewayUrl(env.ANTHROPIC_BASE_URL);
|
|
245
260
|
|
|
@@ -254,10 +269,11 @@ function checkOrphanedRouting() {
|
|
|
254
269
|
settingsChanged = true;
|
|
255
270
|
console.log('\n Synced Plexor auth into ANTHROPIC_API_KEY and ANTHROPIC_AUTH_TOKEN');
|
|
256
271
|
}
|
|
257
|
-
|
|
272
|
+
const primaryApiKeySync = managedAuthKey ? syncManagedPrimaryApiKey(env, managedAuthKey) : { changed: false };
|
|
273
|
+
if (primaryApiKeySync.changed) {
|
|
258
274
|
settings.env = env;
|
|
259
275
|
settingsChanged = true;
|
|
260
|
-
|
|
276
|
+
managedPrimaryApiKeySync = primaryApiKeySync;
|
|
261
277
|
}
|
|
262
278
|
// Check if there's a valid Plexor config
|
|
263
279
|
let hasValidConfig = false;
|
|
@@ -299,6 +315,16 @@ function checkOrphanedRouting() {
|
|
|
299
315
|
fs.writeFileSync(tempPath, JSON.stringify(settings, null, 2), { mode: 0o600 });
|
|
300
316
|
fs.renameSync(tempPath, settingsPath);
|
|
301
317
|
}
|
|
318
|
+
|
|
319
|
+
if (managedPrimaryApiKeySync?.changed) {
|
|
320
|
+
try {
|
|
321
|
+
writeJsonAtomically(managedPrimaryApiKeySync.statePath, managedPrimaryApiKeySync.claudeState);
|
|
322
|
+
console.log('\n Suspended Claude managed API key while Plexor is active');
|
|
323
|
+
} catch (e) {
|
|
324
|
+
console.log('\n Warning: Saved Claude key backup but could not suspend Claude managed API key');
|
|
325
|
+
console.log(` ${e.message}`);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
302
328
|
} catch (e) {
|
|
303
329
|
// Ignore errors in detection - don't break install
|
|
304
330
|
}
|
|
@@ -334,6 +360,9 @@ function main() {
|
|
|
334
360
|
// Create ~/.claude/plugins/plexor/commands/ for JS executors
|
|
335
361
|
fs.mkdirSync(PLEXOR_PLUGINS_DIR, { recursive: true });
|
|
336
362
|
|
|
363
|
+
// Create ~/.claude/plugins/plexor/hooks/ for hook scripts
|
|
364
|
+
fs.mkdirSync(PLEXOR_HOOKS_DIR, { recursive: true });
|
|
365
|
+
|
|
337
366
|
// Create ~/.claude/plugins/plexor/lib/ for shared modules
|
|
338
367
|
fs.mkdirSync(PLEXOR_LIB_DIR, { recursive: true });
|
|
339
368
|
|
|
@@ -356,6 +385,9 @@ function main() {
|
|
|
356
385
|
.filter(f => f.endsWith('.md'));
|
|
357
386
|
const jsFiles = fs.readdirSync(COMMANDS_SOURCE)
|
|
358
387
|
.filter(f => f.endsWith('.js'));
|
|
388
|
+
const hookFiles = fs.existsSync(HOOKS_SOURCE)
|
|
389
|
+
? fs.readdirSync(HOOKS_SOURCE).filter(f => f.endsWith('.js'))
|
|
390
|
+
: [];
|
|
359
391
|
|
|
360
392
|
if (mdFiles.length === 0) {
|
|
361
393
|
console.error('No command files found in package. Installation may be corrupt.');
|
|
@@ -397,6 +429,16 @@ function main() {
|
|
|
397
429
|
jsInstalled.push(file);
|
|
398
430
|
}
|
|
399
431
|
|
|
432
|
+
// Copy hook files to ~/.claude/plugins/plexor/hooks/
|
|
433
|
+
const hooksInstalled = [];
|
|
434
|
+
for (const file of hookFiles) {
|
|
435
|
+
const src = path.join(HOOKS_SOURCE, file);
|
|
436
|
+
const dest = path.join(PLEXOR_HOOKS_DIR, file);
|
|
437
|
+
fs.copyFileSync(src, dest);
|
|
438
|
+
fs.chmodSync(dest, 0o755);
|
|
439
|
+
hooksInstalled.push(file);
|
|
440
|
+
}
|
|
441
|
+
|
|
400
442
|
// Copy lib files to ~/.claude/plugins/plexor/lib/
|
|
401
443
|
// CRITICAL: These are required for commands to work
|
|
402
444
|
const libInstalled = [];
|
|
@@ -431,6 +473,10 @@ function main() {
|
|
|
431
473
|
console.error('');
|
|
432
474
|
}
|
|
433
475
|
|
|
476
|
+
const statusLineRegistration = upsertManagedStatusLine(CLAUDE_SETTINGS_FILE, HOME_DIR);
|
|
477
|
+
const hooksRegistration = upsertManagedHooks(CLAUDE_SETTINGS_FILE, HOME_DIR);
|
|
478
|
+
const legacyHooksCleanup = cleanupLegacyManagedHooksFile(CLAUDE_LEGACY_HOOKS_FILE);
|
|
479
|
+
|
|
434
480
|
// Fix file ownership when running with sudo
|
|
435
481
|
// Files are created as root but should be owned by the original user
|
|
436
482
|
if (targetUser) {
|
|
@@ -457,9 +503,21 @@ function main() {
|
|
|
457
503
|
if (jsInstalled.length > 0) {
|
|
458
504
|
console.log(` ✓ Installed ${jsInstalled.length} executors to ~/.claude/plugins/plexor/commands/`);
|
|
459
505
|
}
|
|
506
|
+
if (hooksInstalled.length > 0) {
|
|
507
|
+
console.log(` ✓ Installed ${hooksInstalled.length} hook scripts to ~/.claude/plugins/plexor/hooks/`);
|
|
508
|
+
}
|
|
460
509
|
if (libInstalled.length > 0) {
|
|
461
510
|
console.log(` ✓ Installed ${libInstalled.length} lib modules to ~/.claude/plugins/plexor/lib/`);
|
|
462
511
|
}
|
|
512
|
+
if (statusLineRegistration.changed || statusLineRegistration.existed) {
|
|
513
|
+
console.log(' ✓ Registered Plexor status line in ~/.claude/settings.json');
|
|
514
|
+
}
|
|
515
|
+
if (hooksRegistration.changed || hooksRegistration.existed) {
|
|
516
|
+
console.log(' ✓ Registered Plexor hooks in ~/.claude/settings.json');
|
|
517
|
+
}
|
|
518
|
+
if (legacyHooksCleanup.changed) {
|
|
519
|
+
console.log(' ✓ Cleaned up legacy ~/.claude/hooks.json entries');
|
|
520
|
+
}
|
|
463
521
|
if (targetUser) {
|
|
464
522
|
console.log(` ✓ Set file ownership to ${targetUser.user}`);
|
|
465
523
|
}
|
|
@@ -474,10 +532,11 @@ function main() {
|
|
|
474
532
|
console.log(' 2. Write ~/.plexor/config.json');
|
|
475
533
|
console.log(' 3. Point Claude at the Plexor staging gateway');
|
|
476
534
|
console.log(' 4. Preserve prior Claude auth for restore on logout');
|
|
477
|
-
console.log(' 5.
|
|
535
|
+
console.log(' 5. Show Plexor state in Claude footer via status line');
|
|
536
|
+
console.log(' 6. Update session savings in real time via Claude hooks');
|
|
478
537
|
console.log('');
|
|
479
538
|
console.log(' ┌─────────────────────────────────────────────────────────────────┐');
|
|
480
|
-
console.log(' │
|
|
539
|
+
console.log(' │ After /plexor-setup, restart Claude before first prompt │');
|
|
481
540
|
console.log(' └─────────────────────────────────────────────────────────────────┘');
|
|
482
541
|
console.log('');
|
|
483
542
|
console.log(' Available commands:');
|
package/scripts/uninstall.js
CHANGED
|
@@ -17,6 +17,9 @@ const fs = require('fs');
|
|
|
17
17
|
const path = require('path');
|
|
18
18
|
const os = require('os');
|
|
19
19
|
const { execSync } = require('child_process');
|
|
20
|
+
const { removeManagedStatusLine } = require('../lib/statusline-manager');
|
|
21
|
+
const { removeManagedHooks, cleanupLegacyManagedHooksFile } = require('../lib/hooks-manager');
|
|
22
|
+
const { removeManagedClaudeCustomHeadersFromEnv } = require('../lib/config-utils');
|
|
20
23
|
|
|
21
24
|
/**
|
|
22
25
|
* Get the correct home directory for the process's effective user.
|
|
@@ -52,11 +55,16 @@ console.log('');
|
|
|
52
55
|
|
|
53
56
|
const results = {
|
|
54
57
|
routing: false,
|
|
58
|
+
statusLine: false,
|
|
59
|
+
hooks: false,
|
|
55
60
|
commands: [],
|
|
56
61
|
restored: [],
|
|
57
62
|
pluginDir: false
|
|
58
63
|
};
|
|
59
64
|
const PREVIOUS_PRIMARY_API_KEY_ENV = 'PLEXOR_PREVIOUS_CLAUDE_PRIMARY_API_KEY';
|
|
65
|
+
const CLAUDE_SETTINGS_PATH = path.join(home, '.claude', 'settings.json');
|
|
66
|
+
const CLAUDE_HOOKS_PATH = path.join(home, '.claude', 'settings.json');
|
|
67
|
+
const CLAUDE_LEGACY_HOOKS_PATH = path.join(home, '.claude', 'hooks.json');
|
|
60
68
|
|
|
61
69
|
function isManagedGatewayUrl(baseUrl = '') {
|
|
62
70
|
return (
|
|
@@ -77,8 +85,9 @@ function clearPlexorRoutingEnv(env = {}) {
|
|
|
77
85
|
const hasManagedBaseUrl = isManagedGatewayUrl(env.ANTHROPIC_BASE_URL || '');
|
|
78
86
|
const hasPlexorAuthToken = isPlexorApiKey(env.ANTHROPIC_AUTH_TOKEN || '');
|
|
79
87
|
const hasPlexorApiKey = isPlexorApiKey(env.ANTHROPIC_API_KEY || '');
|
|
88
|
+
const removedManagedHeaders = removeManagedClaudeCustomHeadersFromEnv(env);
|
|
80
89
|
|
|
81
|
-
if (!hasManagedBaseUrl && !hasPlexorAuthToken && !hasPlexorApiKey) {
|
|
90
|
+
if (!hasManagedBaseUrl && !hasPlexorAuthToken && !hasPlexorApiKey && !removedManagedHeaders) {
|
|
82
91
|
return false;
|
|
83
92
|
}
|
|
84
93
|
|
|
@@ -105,10 +114,16 @@ function clearPlexorRoutingEnv(env = {}) {
|
|
|
105
114
|
return true;
|
|
106
115
|
}
|
|
107
116
|
|
|
117
|
+
function writeJsonAtomically(filePath, value) {
|
|
118
|
+
const tempPath = `${filePath}.tmp.${Date.now()}`;
|
|
119
|
+
fs.writeFileSync(tempPath, JSON.stringify(value, null, 2), { mode: 0o600 });
|
|
120
|
+
fs.renameSync(tempPath, filePath);
|
|
121
|
+
}
|
|
122
|
+
|
|
108
123
|
function restoreClaudePrimaryApiKey(env = {}) {
|
|
109
124
|
const previousPrimaryApiKey = env[PREVIOUS_PRIMARY_API_KEY_ENV] || '';
|
|
110
125
|
if (!previousPrimaryApiKey) {
|
|
111
|
-
return false;
|
|
126
|
+
return { restored: false, warning: null };
|
|
112
127
|
}
|
|
113
128
|
|
|
114
129
|
const statePath = path.join(home, '.claude.json');
|
|
@@ -127,12 +142,14 @@ function restoreClaudePrimaryApiKey(env = {}) {
|
|
|
127
142
|
if (!claudeState.primaryApiKey) {
|
|
128
143
|
claudeState.primaryApiKey = previousPrimaryApiKey;
|
|
129
144
|
}
|
|
130
|
-
delete env[PREVIOUS_PRIMARY_API_KEY_ENV];
|
|
131
145
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
146
|
+
try {
|
|
147
|
+
writeJsonAtomically(statePath, claudeState);
|
|
148
|
+
delete env[PREVIOUS_PRIMARY_API_KEY_ENV];
|
|
149
|
+
return { restored: true, warning: null };
|
|
150
|
+
} catch (e) {
|
|
151
|
+
return { restored: false, warning: e.message };
|
|
152
|
+
}
|
|
136
153
|
}
|
|
137
154
|
|
|
138
155
|
// 1. Remove routing from settings.json
|
|
@@ -145,17 +162,20 @@ try {
|
|
|
145
162
|
const settings = JSON.parse(data);
|
|
146
163
|
if (settings.env) {
|
|
147
164
|
const routingChanged = clearPlexorRoutingEnv(settings.env);
|
|
148
|
-
const
|
|
165
|
+
const primaryApiKeyRestore = restoreClaudePrimaryApiKey(settings.env);
|
|
149
166
|
|
|
150
167
|
// Clean up empty env block
|
|
151
168
|
if (Object.keys(settings.env).length === 0) {
|
|
152
169
|
delete settings.env;
|
|
153
170
|
}
|
|
154
171
|
|
|
155
|
-
if (routingChanged ||
|
|
172
|
+
if (routingChanged || primaryApiKeyRestore.restored) {
|
|
156
173
|
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2), { mode: 0o600 });
|
|
157
174
|
results.routing = true;
|
|
158
175
|
}
|
|
176
|
+
if (primaryApiKeyRestore.warning) {
|
|
177
|
+
console.log(` Warning: Could not restore Claude managed API key: ${primaryApiKeyRestore.warning}`);
|
|
178
|
+
}
|
|
159
179
|
}
|
|
160
180
|
}
|
|
161
181
|
}
|
|
@@ -163,24 +183,34 @@ try {
|
|
|
163
183
|
console.log(` Warning: Could not clean settings.json: ${e.message}`);
|
|
164
184
|
}
|
|
165
185
|
|
|
166
|
-
// 2. Remove
|
|
167
|
-
|
|
168
|
-
const
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
186
|
+
// 2. Remove managed Claude status line
|
|
187
|
+
try {
|
|
188
|
+
const statusLineRemoval = removeManagedStatusLine(CLAUDE_SETTINGS_PATH, home);
|
|
189
|
+
results.statusLine = statusLineRemoval.changed;
|
|
190
|
+
} catch (e) {
|
|
191
|
+
console.log(` Warning: Could not clean Plexor status line: ${e.message}`);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// 2b. Remove managed Claude hooks
|
|
195
|
+
try {
|
|
196
|
+
const hooksRemoval = removeManagedHooks(CLAUDE_HOOKS_PATH);
|
|
197
|
+
results.hooks = hooksRemoval.changed;
|
|
198
|
+
} catch (e) {
|
|
199
|
+
console.log(` Warning: Could not clean Plexor hooks: ${e.message}`);
|
|
200
|
+
}
|
|
201
|
+
try {
|
|
202
|
+
const legacyHooksRemoval = cleanupLegacyManagedHooksFile(CLAUDE_LEGACY_HOOKS_PATH);
|
|
203
|
+
results.hooks = results.hooks || legacyHooksRemoval.changed;
|
|
204
|
+
} catch (e) {
|
|
205
|
+
console.log(` Warning: Could not clean legacy Plexor hooks file: ${e.message}`);
|
|
206
|
+
}
|
|
180
207
|
|
|
208
|
+
// 3. Remove slash command files
|
|
209
|
+
// These are the Plexor-specific command files that get installed to ~/.claude/commands/
|
|
181
210
|
try {
|
|
182
211
|
const commandsDir = path.join(home, '.claude', 'commands');
|
|
183
212
|
if (fs.existsSync(commandsDir)) {
|
|
213
|
+
const plexorCommands = fs.readdirSync(commandsDir).filter((entry) => /^plexor-.*\.md$/i.test(entry));
|
|
184
214
|
for (const cmd of plexorCommands) {
|
|
185
215
|
const cmdPath = path.join(commandsDir, cmd);
|
|
186
216
|
const backupPath = cmdPath + '.backup';
|
|
@@ -201,7 +231,7 @@ try {
|
|
|
201
231
|
console.log(` Warning: Could not clean commands: ${e.message}`);
|
|
202
232
|
}
|
|
203
233
|
|
|
204
|
-
//
|
|
234
|
+
// 4. Remove plugin directory
|
|
205
235
|
try {
|
|
206
236
|
const pluginDir = path.join(home, '.claude', 'plugins', 'plexor');
|
|
207
237
|
if (fs.existsSync(pluginDir)) {
|
|
@@ -212,8 +242,19 @@ try {
|
|
|
212
242
|
console.log(` Warning: Could not remove plugin directory: ${e.message}`);
|
|
213
243
|
}
|
|
214
244
|
|
|
245
|
+
// 5. Remove config directory
|
|
246
|
+
try {
|
|
247
|
+
const configDir = path.join(home, '.plexor');
|
|
248
|
+
if (fs.existsSync(configDir)) {
|
|
249
|
+
fs.rmSync(configDir, { recursive: true, force: true });
|
|
250
|
+
results.configDir = true;
|
|
251
|
+
}
|
|
252
|
+
} catch (e) {
|
|
253
|
+
console.log(` Warning: Could not remove ~/.plexor config directory: ${e.message}`);
|
|
254
|
+
}
|
|
255
|
+
|
|
215
256
|
// Output results
|
|
216
|
-
if (results.routing || results.commands.length > 0 || results.pluginDir) {
|
|
257
|
+
if (results.routing || results.statusLine || results.hooks || results.commands.length > 0 || results.pluginDir) {
|
|
217
258
|
console.log(' Plexor plugin uninstalled');
|
|
218
259
|
console.log('');
|
|
219
260
|
|
|
@@ -223,6 +264,16 @@ if (results.routing || results.commands.length > 0 || results.pluginDir) {
|
|
|
223
264
|
console.log('');
|
|
224
265
|
}
|
|
225
266
|
|
|
267
|
+
if (results.statusLine) {
|
|
268
|
+
console.log(' Removed Plexor Claude status line');
|
|
269
|
+
console.log('');
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
if (results.hooks) {
|
|
273
|
+
console.log(' Removed Plexor Claude hooks');
|
|
274
|
+
console.log('');
|
|
275
|
+
}
|
|
276
|
+
|
|
226
277
|
if (results.commands.length > 0) {
|
|
227
278
|
console.log(' Removed commands:');
|
|
228
279
|
results.commands.forEach(cmd => console.log(` /${cmd}`));
|
|
@@ -239,10 +290,10 @@ if (results.routing || results.commands.length > 0 || results.pluginDir) {
|
|
|
239
290
|
console.log(' Removed plugin directory');
|
|
240
291
|
console.log('');
|
|
241
292
|
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
293
|
+
if (results.configDir) {
|
|
294
|
+
console.log(' Removed ~/.plexor config directory');
|
|
295
|
+
console.log('');
|
|
296
|
+
}
|
|
246
297
|
} else {
|
|
247
298
|
console.log(' No Plexor components found to clean up.');
|
|
248
299
|
console.log('');
|