@plexor-dev/claude-code-plugin 0.1.0-beta.31 → 0.1.0-beta.32
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-enabled.js +3 -3
- package/commands/plexor-login.js +74 -9
- package/commands/plexor-logout.js +23 -5
- package/commands/plexor-status.js +3 -4
- package/lib/constants.js +19 -1
- package/package.json +1 -1
- package/scripts/uninstall.js +33 -3
|
@@ -14,6 +14,9 @@
|
|
|
14
14
|
const fs = require('fs');
|
|
15
15
|
const path = require('path');
|
|
16
16
|
|
|
17
|
+
// Import centralized constants with HOME directory validation
|
|
18
|
+
const { PLEXOR_DIR, CONFIG_PATH } = require('../lib/constants');
|
|
19
|
+
|
|
17
20
|
// Import settings manager with error handling for missing lib
|
|
18
21
|
let settingsManager, PLEXOR_STAGING_URL, PLEXOR_PROD_URL;
|
|
19
22
|
try {
|
|
@@ -30,9 +33,6 @@ try {
|
|
|
30
33
|
throw err;
|
|
31
34
|
}
|
|
32
35
|
|
|
33
|
-
const CONFIG_PATH = path.join(process.env.HOME, '.plexor', 'config.json');
|
|
34
|
-
const PLEXOR_DIR = path.join(process.env.HOME, '.plexor');
|
|
35
|
-
|
|
36
36
|
function loadConfig() {
|
|
37
37
|
try {
|
|
38
38
|
if (!fs.existsSync(CONFIG_PATH)) {
|
package/commands/plexor-login.js
CHANGED
|
@@ -13,6 +13,9 @@ const path = require('path');
|
|
|
13
13
|
const https = require('https');
|
|
14
14
|
const http = require('http');
|
|
15
15
|
|
|
16
|
+
// Import centralized constants with HOME directory validation
|
|
17
|
+
const { PLEXOR_DIR, CONFIG_PATH, DEFAULT_API_URL } = require('../lib/constants');
|
|
18
|
+
|
|
16
19
|
// Import settings manager with error handling for missing lib
|
|
17
20
|
let settingsManager;
|
|
18
21
|
try {
|
|
@@ -26,11 +29,6 @@ try {
|
|
|
26
29
|
throw err;
|
|
27
30
|
}
|
|
28
31
|
|
|
29
|
-
const CONFIG_PATH = path.join(process.env.HOME, '.plexor', 'config.json');
|
|
30
|
-
const PLEXOR_DIR = path.join(process.env.HOME, '.plexor');
|
|
31
|
-
// PRODUCTION PACKAGE - uses production API
|
|
32
|
-
const DEFAULT_API_URL = 'https://api.plexor.dev';
|
|
33
|
-
|
|
34
32
|
function loadConfig() {
|
|
35
33
|
try {
|
|
36
34
|
if (!fs.existsSync(CONFIG_PATH)) {
|
|
@@ -121,9 +119,62 @@ function validateApiKey(apiUrl, apiKey) {
|
|
|
121
119
|
});
|
|
122
120
|
}
|
|
123
121
|
|
|
122
|
+
/**
|
|
123
|
+
* Read API key from stdin (for piped input)
|
|
124
|
+
* @returns {Promise<string>} The API key read from stdin
|
|
125
|
+
*/
|
|
126
|
+
function readFromStdin() {
|
|
127
|
+
return new Promise((resolve, reject) => {
|
|
128
|
+
let data = '';
|
|
129
|
+
const timeout = setTimeout(() => {
|
|
130
|
+
reject(new Error('Timeout reading from stdin'));
|
|
131
|
+
}, 5000);
|
|
132
|
+
|
|
133
|
+
process.stdin.setEncoding('utf8');
|
|
134
|
+
process.stdin.on('data', (chunk) => {
|
|
135
|
+
data += chunk;
|
|
136
|
+
});
|
|
137
|
+
process.stdin.on('end', () => {
|
|
138
|
+
clearTimeout(timeout);
|
|
139
|
+
resolve(data.trim());
|
|
140
|
+
});
|
|
141
|
+
process.stdin.on('error', (err) => {
|
|
142
|
+
clearTimeout(timeout);
|
|
143
|
+
reject(err);
|
|
144
|
+
});
|
|
145
|
+
process.stdin.resume();
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
|
|
124
149
|
async function main() {
|
|
125
150
|
const args = process.argv.slice(2);
|
|
126
|
-
let apiKey =
|
|
151
|
+
let apiKey = null;
|
|
152
|
+
let keySource = null;
|
|
153
|
+
|
|
154
|
+
// SECURITY FIX: Check for API key in order of preference
|
|
155
|
+
// 1. Environment variable (most secure for scripts/CI)
|
|
156
|
+
// 2. Stdin pipe (secure for interactive use)
|
|
157
|
+
// 3. Command line argument (warns about security risk)
|
|
158
|
+
|
|
159
|
+
// Check environment variable first (most secure)
|
|
160
|
+
if (process.env.PLEXOR_API_KEY) {
|
|
161
|
+
apiKey = process.env.PLEXOR_API_KEY;
|
|
162
|
+
keySource = 'environment';
|
|
163
|
+
}
|
|
164
|
+
// Check if stdin has data (piped input)
|
|
165
|
+
else if (!process.stdin.isTTY && args.length === 0) {
|
|
166
|
+
try {
|
|
167
|
+
apiKey = await readFromStdin();
|
|
168
|
+
keySource = 'stdin';
|
|
169
|
+
} catch {
|
|
170
|
+
// Stdin read failed, continue to check args
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
// Check command line argument (least secure - shows in ps)
|
|
174
|
+
else if (args[0]) {
|
|
175
|
+
apiKey = args[0];
|
|
176
|
+
keySource = 'argument';
|
|
177
|
+
}
|
|
127
178
|
|
|
128
179
|
// Check for existing login
|
|
129
180
|
const config = loadConfig();
|
|
@@ -135,14 +186,14 @@ async function main() {
|
|
|
135
186
|
console.log(`├─────────────────────────────────────────────┤`);
|
|
136
187
|
console.log(`│ API Key: ${(existingKey.substring(0, 8) + '...').padEnd(33)}│`);
|
|
137
188
|
console.log(`│ To re-login, provide a new key: │`);
|
|
138
|
-
console.log(`│ /plexor-login
|
|
189
|
+
console.log(`│ echo $PLEXOR_API_KEY | /plexor-login │`);
|
|
139
190
|
console.log(`│ To logout: │`);
|
|
140
191
|
console.log(`│ /plexor-logout │`);
|
|
141
192
|
console.log(`└─────────────────────────────────────────────┘`);
|
|
142
193
|
return;
|
|
143
194
|
}
|
|
144
195
|
|
|
145
|
-
// If no key provided,
|
|
196
|
+
// If no key provided, show secure usage options
|
|
146
197
|
if (!apiKey) {
|
|
147
198
|
console.log(`┌─────────────────────────────────────────────┐`);
|
|
148
199
|
console.log(`│ Plexor Login │`);
|
|
@@ -150,11 +201,25 @@ async function main() {
|
|
|
150
201
|
console.log(`│ Get your API key at: │`);
|
|
151
202
|
console.log(`│ https://plexor.dev/dashboard/api-keys │`);
|
|
152
203
|
console.log(`├─────────────────────────────────────────────┤`);
|
|
153
|
-
console.log(`│
|
|
204
|
+
console.log(`│ Secure usage (recommended): │`);
|
|
205
|
+
console.log(`│ echo "plx_..." | /plexor-login │`);
|
|
206
|
+
console.log(`│ PLEXOR_API_KEY=plx_... /plexor-login │`);
|
|
207
|
+
console.log(`├─────────────────────────────────────────────┤`);
|
|
208
|
+
console.log(`│ Direct usage (visible in ps): │`);
|
|
209
|
+
console.log(`│ /plexor-login <api-key> │`);
|
|
154
210
|
console.log(`└─────────────────────────────────────────────┘`);
|
|
155
211
|
return;
|
|
156
212
|
}
|
|
157
213
|
|
|
214
|
+
// Warn if API key was passed as command line argument
|
|
215
|
+
if (keySource === 'argument') {
|
|
216
|
+
console.log(`⚠ Security note: API key passed as argument is visible in`);
|
|
217
|
+
console.log(` process list (ps aux). For better security, use:`);
|
|
218
|
+
console.log(` echo "plx_..." | /plexor-login`);
|
|
219
|
+
console.log(` PLEXOR_API_KEY=plx_... /plexor-login`);
|
|
220
|
+
console.log('');
|
|
221
|
+
}
|
|
222
|
+
|
|
158
223
|
// Validate key format
|
|
159
224
|
if (!apiKey.startsWith('plx_') || apiKey.length < 20) {
|
|
160
225
|
console.error(`Error: Invalid API key format`);
|
|
@@ -8,10 +8,22 @@
|
|
|
8
8
|
const fs = require('fs');
|
|
9
9
|
const path = require('path');
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
const CONFIG_PATH =
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
// Import centralized constants with HOME directory validation
|
|
12
|
+
const { PLEXOR_DIR, CONFIG_PATH, SESSION_PATH, CACHE_PATH } = require('../lib/constants');
|
|
13
|
+
|
|
14
|
+
// Import settings manager for Claude Code routing cleanup
|
|
15
|
+
let settingsManager;
|
|
16
|
+
try {
|
|
17
|
+
const lib = require('../lib/settings-manager');
|
|
18
|
+
settingsManager = lib.settingsManager;
|
|
19
|
+
} catch (err) {
|
|
20
|
+
if (err.code === 'MODULE_NOT_FOUND') {
|
|
21
|
+
console.error('Error: Plexor plugin files are missing or corrupted.');
|
|
22
|
+
console.error(' Please reinstall: npm install @plexor-dev/claude-code-plugin');
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
throw err;
|
|
26
|
+
}
|
|
15
27
|
|
|
16
28
|
function loadConfig() {
|
|
17
29
|
try {
|
|
@@ -96,6 +108,11 @@ function main() {
|
|
|
96
108
|
process.exit(1);
|
|
97
109
|
}
|
|
98
110
|
|
|
111
|
+
// CRITICAL FIX: Disable Claude Code routing in ~/.claude/settings.json
|
|
112
|
+
// This removes ANTHROPIC_BASE_URL and ANTHROPIC_AUTH_TOKEN so Claude Code
|
|
113
|
+
// no longer tries to route through Plexor with removed credentials
|
|
114
|
+
const routingDisabled = settingsManager.disablePlexorRouting();
|
|
115
|
+
|
|
99
116
|
// Clear session
|
|
100
117
|
deleteFile(SESSION_PATH);
|
|
101
118
|
|
|
@@ -109,12 +126,13 @@ function main() {
|
|
|
109
126
|
console.log(`│ ✓ Logged Out │`);
|
|
110
127
|
console.log(`├─────────────────────────────────────────────┤`);
|
|
111
128
|
console.log(`│ ✓ API key removed │`);
|
|
112
|
-
console.log(`│ ✓
|
|
129
|
+
console.log(`│ ${routingDisabled ? '✓' : '○'} Claude Code routing disabled │`);
|
|
113
130
|
console.log(`│ ✓ Session cleared │`);
|
|
114
131
|
if (clearCache) {
|
|
115
132
|
console.log(`│ ${cacheCleared ? '✓' : '○'} Cache cleared │`);
|
|
116
133
|
}
|
|
117
134
|
console.log(`├─────────────────────────────────────────────┤`);
|
|
135
|
+
console.log(`│ Claude Code now connects directly. │`);
|
|
118
136
|
console.log(`│ Run /plexor-login to re-authenticate. │`);
|
|
119
137
|
if (!clearCache) {
|
|
120
138
|
console.log(`│ Use --clear-cache to also clear cache. │`);
|
|
@@ -9,10 +9,9 @@ const fs = require('fs');
|
|
|
9
9
|
const path = require('path');
|
|
10
10
|
const https = require('https');
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
const
|
|
14
|
-
const CLAUDE_SETTINGS_PATH = path.join(
|
|
15
|
-
const SESSION_TIMEOUT_MS = 30 * 60 * 1000; // 30 minutes
|
|
12
|
+
// Import centralized constants with HOME directory validation
|
|
13
|
+
const { HOME_DIR, CONFIG_PATH, SESSION_PATH, SESSION_TIMEOUT_MS } = require('../lib/constants');
|
|
14
|
+
const CLAUDE_SETTINGS_PATH = path.join(HOME_DIR, '.claude', 'settings.json');
|
|
16
15
|
|
|
17
16
|
/**
|
|
18
17
|
* Check if Claude Code is actually routing through Plexor
|
package/lib/constants.js
CHANGED
|
@@ -4,7 +4,23 @@
|
|
|
4
4
|
|
|
5
5
|
const path = require('path');
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Get the user's home directory with proper validation
|
|
9
|
+
* @returns {string} Home directory path
|
|
10
|
+
* @throws {Error} If HOME is not set or empty
|
|
11
|
+
*/
|
|
12
|
+
function getHomeDir() {
|
|
13
|
+
const home = process.env.HOME || process.env.USERPROFILE;
|
|
14
|
+
if (!home || home.trim() === '') {
|
|
15
|
+
console.error('Error: HOME environment variable is not set.');
|
|
16
|
+
console.error(' Please set HOME to your user directory before running Plexor commands.');
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
return home;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const HOME_DIR = getHomeDir();
|
|
23
|
+
const PLEXOR_DIR = path.join(HOME_DIR, '.plexor');
|
|
8
24
|
const CONFIG_PATH = path.join(PLEXOR_DIR, 'config.json');
|
|
9
25
|
const SESSION_PATH = path.join(PLEXOR_DIR, 'session.json');
|
|
10
26
|
const CACHE_PATH = path.join(PLEXOR_DIR, 'cache.json');
|
|
@@ -15,6 +31,8 @@ const DEFAULT_API_URL = 'https://api.plexor.dev';
|
|
|
15
31
|
const DEFAULT_TIMEOUT = 5000;
|
|
16
32
|
|
|
17
33
|
module.exports = {
|
|
34
|
+
getHomeDir,
|
|
35
|
+
HOME_DIR,
|
|
18
36
|
PLEXOR_DIR,
|
|
19
37
|
CONFIG_PATH,
|
|
20
38
|
SESSION_PATH,
|
package/package.json
CHANGED
package/scripts/uninstall.js
CHANGED
|
@@ -11,11 +11,32 @@ const fs = require('fs');
|
|
|
11
11
|
const path = require('path');
|
|
12
12
|
const os = require('os');
|
|
13
13
|
|
|
14
|
+
// Import settings manager for Claude Code routing cleanup
|
|
15
|
+
let settingsManager;
|
|
16
|
+
try {
|
|
17
|
+
const lib = require('../lib/settings-manager');
|
|
18
|
+
settingsManager = lib.settingsManager;
|
|
19
|
+
} catch (err) {
|
|
20
|
+
// If settings manager can't be loaded during uninstall, continue anyway
|
|
21
|
+
settingsManager = null;
|
|
22
|
+
}
|
|
23
|
+
|
|
14
24
|
const COMMANDS_SOURCE = path.join(__dirname, '..', 'commands');
|
|
15
25
|
const CLAUDE_COMMANDS_DIR = path.join(os.homedir(), '.claude', 'commands');
|
|
16
26
|
|
|
17
27
|
function main() {
|
|
18
28
|
try {
|
|
29
|
+
// CRITICAL: Disable Claude Code routing before removing commands
|
|
30
|
+
// This ensures users don't get stuck with Plexor routing after uninstall
|
|
31
|
+
let routingDisabled = false;
|
|
32
|
+
if (settingsManager) {
|
|
33
|
+
try {
|
|
34
|
+
routingDisabled = settingsManager.disablePlexorRouting();
|
|
35
|
+
} catch (e) {
|
|
36
|
+
// Continue with uninstall even if routing cleanup fails
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
19
40
|
// Get list of our command files
|
|
20
41
|
const files = fs.readdirSync(COMMANDS_SOURCE)
|
|
21
42
|
.filter(f => f.endsWith('.md'));
|
|
@@ -39,12 +60,21 @@ function main() {
|
|
|
39
60
|
}
|
|
40
61
|
}
|
|
41
62
|
|
|
42
|
-
if (removed.length > 0) {
|
|
63
|
+
if (removed.length > 0 || routingDisabled) {
|
|
43
64
|
console.log('');
|
|
44
65
|
console.log(' Plexor plugin uninstalled');
|
|
45
66
|
console.log('');
|
|
46
|
-
|
|
47
|
-
|
|
67
|
+
|
|
68
|
+
if (routingDisabled) {
|
|
69
|
+
console.log(' ✓ Claude Code routing disabled');
|
|
70
|
+
console.log(' (Claude Code now connects directly to Anthropic)');
|
|
71
|
+
console.log('');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (removed.length > 0) {
|
|
75
|
+
console.log(' Removed commands:');
|
|
76
|
+
removed.forEach(cmd => console.log(` /${cmd}`));
|
|
77
|
+
}
|
|
48
78
|
|
|
49
79
|
if (restored.length > 0) {
|
|
50
80
|
console.log('');
|