@plexor-dev/claude-code-plugin-localhost 0.1.0-beta.11
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/LICENSE +21 -0
- package/README.md +114 -0
- package/commands/plexor-enabled.js +281 -0
- package/commands/plexor-enabled.md +48 -0
- package/commands/plexor-login.js +283 -0
- package/commands/plexor-login.md +27 -0
- package/commands/plexor-logout.js +143 -0
- package/commands/plexor-logout.md +27 -0
- package/commands/plexor-setup.md +172 -0
- package/commands/plexor-status.js +406 -0
- package/commands/plexor-status.md +21 -0
- package/configure-localhost.sh +90 -0
- package/hooks/intercept.js +634 -0
- package/hooks/track-response.js +376 -0
- package/lib/cache.js +107 -0
- package/lib/config.js +67 -0
- package/lib/constants.js +44 -0
- package/lib/index.js +19 -0
- package/lib/logger.js +36 -0
- package/lib/plexor-client.js +122 -0
- package/lib/server-sync.js +237 -0
- package/lib/session.js +156 -0
- package/lib/settings-manager.js +352 -0
- package/package.json +57 -0
- package/scripts/plexor-cli.sh +48 -0
- package/scripts/postinstall.js +294 -0
- package/scripts/uninstall.js +97 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Plexor AI
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# @plexor-dev/claude-code-plugin
|
|
2
|
+
|
|
3
|
+
LLM cost optimization plugin for Claude Code. Save up to 90% on AI costs through intelligent prompt optimization and multi-provider routing.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g @plexor-dev/claude-code-plugin
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
This installs slash commands to `~/.claude/commands/`.
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
1. **Install the plugin** (see above)
|
|
16
|
+
|
|
17
|
+
2. **Open Claude Code** and run:
|
|
18
|
+
```
|
|
19
|
+
/plexor-login
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
3. **Follow the prompts** to authenticate via browser
|
|
23
|
+
|
|
24
|
+
4. **Set the gateway URL** in your terminal:
|
|
25
|
+
```bash
|
|
26
|
+
export ANTHROPIC_BASE_URL="https://api.plexor.dev/v1/gateway/anthropic"
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
5. **Restart Claude Code** - all prompts are now optimized!
|
|
30
|
+
|
|
31
|
+
## Commands
|
|
32
|
+
|
|
33
|
+
| Command | Description |
|
|
34
|
+
|---------|-------------|
|
|
35
|
+
| `/plexor-setup` | First-time setup wizard |
|
|
36
|
+
| `/plexor-login` | Authenticate with Plexor API key |
|
|
37
|
+
| `/plexor-logout` | Sign out and clear credentials |
|
|
38
|
+
| `/plexor-status` | View usage stats and savings |
|
|
39
|
+
| `/plexor-enabled` | Enable/disable Plexor routing |
|
|
40
|
+
|
|
41
|
+
## How It Works
|
|
42
|
+
|
|
43
|
+
Plexor acts as an intelligent gateway between Claude Code and LLM providers:
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
Claude Code → Plexor Gateway → Best Provider (Anthropic/DeepSeek/Mistral/Gemini/OpenAI)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The gateway:
|
|
50
|
+
- **Optimizes prompts** to reduce token usage
|
|
51
|
+
- **Routes requests** to the most cost-effective provider
|
|
52
|
+
- **Maintains quality** based on your selected mode
|
|
53
|
+
- **Tracks savings** so you can see your ROI
|
|
54
|
+
|
|
55
|
+
## Optimization Modes
|
|
56
|
+
|
|
57
|
+
| Mode | Savings | Best For |
|
|
58
|
+
|------|---------|----------|
|
|
59
|
+
| **eco** | 60-90% | Development, testing, iteration |
|
|
60
|
+
| **balanced** | 40-60% | Most production workloads |
|
|
61
|
+
| **quality** | 20-40% | Critical responses, customer-facing |
|
|
62
|
+
| **passthrough** | 0% | Debugging, comparison |
|
|
63
|
+
|
|
64
|
+
## Pricing
|
|
65
|
+
|
|
66
|
+
- **Beta**: $1/month (unlimited requests)
|
|
67
|
+
- Savings typically 10-100x the subscription cost
|
|
68
|
+
|
|
69
|
+
## Configuration
|
|
70
|
+
|
|
71
|
+
Settings are stored in `~/.plexor/config.json`:
|
|
72
|
+
|
|
73
|
+
```json
|
|
74
|
+
{
|
|
75
|
+
"version": 1,
|
|
76
|
+
"auth": {
|
|
77
|
+
"api_key": "plx_...",
|
|
78
|
+
"email": "user@example.com"
|
|
79
|
+
},
|
|
80
|
+
"settings": {
|
|
81
|
+
"enabled": true,
|
|
82
|
+
"mode": "balanced",
|
|
83
|
+
"preferred_provider": "auto"
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Uninstall
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
npm uninstall -g @plexor-dev/claude-code-plugin
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
To fully remove:
|
|
95
|
+
```bash
|
|
96
|
+
unset ANTHROPIC_BASE_URL
|
|
97
|
+
rm -rf ~/.plexor
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Requirements
|
|
101
|
+
|
|
102
|
+
- Node.js 16+
|
|
103
|
+
- Claude Code CLI
|
|
104
|
+
- macOS, Linux, or Windows (WSL)
|
|
105
|
+
|
|
106
|
+
## Support
|
|
107
|
+
|
|
108
|
+
- **Documentation**: https://plexor.dev/docs
|
|
109
|
+
- **Issues**: https://github.com/plexor-ai/claude-code-plugin/issues
|
|
110
|
+
- **Email**: hello@plexor.dev
|
|
111
|
+
|
|
112
|
+
## License
|
|
113
|
+
|
|
114
|
+
MIT
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Plexor Enabled Command
|
|
5
|
+
* Enable or disable Plexor optimization proxy
|
|
6
|
+
*
|
|
7
|
+
* KEY FEATURE: When toggling on/off, automatically updates ~/.claude/settings.json
|
|
8
|
+
* to route or un-route ALL Claude Code sessions through Plexor gateway.
|
|
9
|
+
*
|
|
10
|
+
* THE DREAM: User just runs "/plexor-enabled off" to disable, "/plexor-enabled on" to enable.
|
|
11
|
+
* No manual environment variables or config updates required!
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const fs = require('fs');
|
|
15
|
+
const path = require('path');
|
|
16
|
+
|
|
17
|
+
// Import centralized constants with HOME directory validation
|
|
18
|
+
const { PLEXOR_DIR, CONFIG_PATH } = require('../lib/constants');
|
|
19
|
+
|
|
20
|
+
// Import settings manager with error handling for missing lib
|
|
21
|
+
let settingsManager, PLEXOR_STAGING_URL, PLEXOR_PROD_URL;
|
|
22
|
+
try {
|
|
23
|
+
const lib = require('../lib/settings-manager');
|
|
24
|
+
settingsManager = lib.settingsManager;
|
|
25
|
+
PLEXOR_STAGING_URL = lib.PLEXOR_STAGING_URL;
|
|
26
|
+
PLEXOR_PROD_URL = lib.PLEXOR_PROD_URL;
|
|
27
|
+
} catch (err) {
|
|
28
|
+
if (err.code === 'MODULE_NOT_FOUND') {
|
|
29
|
+
console.error('Error: Plexor plugin files are missing or corrupted.');
|
|
30
|
+
console.error(' Please reinstall: npm install @plexor-dev/claude-code-plugin-localhost');
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
throw err;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function loadConfig() {
|
|
37
|
+
try {
|
|
38
|
+
if (!fs.existsSync(CONFIG_PATH)) {
|
|
39
|
+
return { version: 1, auth: {}, settings: {} };
|
|
40
|
+
}
|
|
41
|
+
const data = fs.readFileSync(CONFIG_PATH, 'utf8');
|
|
42
|
+
if (!data || data.trim() === '') {
|
|
43
|
+
return { version: 1, auth: {}, settings: {} };
|
|
44
|
+
}
|
|
45
|
+
const config = JSON.parse(data);
|
|
46
|
+
if (typeof config !== 'object' || config === null) {
|
|
47
|
+
console.warn('Warning: Config file has invalid format, using defaults');
|
|
48
|
+
return { version: 1, auth: {}, settings: {} };
|
|
49
|
+
}
|
|
50
|
+
return config;
|
|
51
|
+
} catch (err) {
|
|
52
|
+
if (err instanceof SyntaxError) {
|
|
53
|
+
console.warn('Warning: Config file is corrupted, using defaults');
|
|
54
|
+
// Backup corrupted file
|
|
55
|
+
try {
|
|
56
|
+
fs.copyFileSync(CONFIG_PATH, CONFIG_PATH + '.corrupted');
|
|
57
|
+
} catch { /* ignore */ }
|
|
58
|
+
}
|
|
59
|
+
return { version: 1, auth: {}, settings: {} };
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function saveConfig(config) {
|
|
64
|
+
try {
|
|
65
|
+
if (!fs.existsSync(PLEXOR_DIR)) {
|
|
66
|
+
fs.mkdirSync(PLEXOR_DIR, { recursive: true, mode: 0o700 });
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Atomic write: write to temp file, then rename
|
|
70
|
+
const crypto = require('crypto');
|
|
71
|
+
const tempId = crypto.randomBytes(8).toString('hex');
|
|
72
|
+
const tempPath = path.join(PLEXOR_DIR, `.config.${tempId}.tmp`);
|
|
73
|
+
|
|
74
|
+
fs.writeFileSync(tempPath, JSON.stringify(config, null, 2), { mode: 0o600 });
|
|
75
|
+
fs.renameSync(tempPath, CONFIG_PATH);
|
|
76
|
+
return true;
|
|
77
|
+
} catch (err) {
|
|
78
|
+
if (err.code === 'EACCES' || err.code === 'EPERM') {
|
|
79
|
+
console.error(`Error: Cannot write to ~/.plexor/config.json`);
|
|
80
|
+
console.error(' Check file permissions or run with appropriate access.');
|
|
81
|
+
} else {
|
|
82
|
+
console.error('Failed to save config:', err.message);
|
|
83
|
+
}
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Validate API key format
|
|
90
|
+
* @param {string} key - API key to validate
|
|
91
|
+
* @returns {boolean} true if valid format
|
|
92
|
+
*/
|
|
93
|
+
function isValidApiKeyFormat(key) {
|
|
94
|
+
return key && typeof key === 'string' && key.startsWith('plx_') && key.length >= 20;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Check for state mismatch between config.json enabled flag and settings.json routing
|
|
99
|
+
* @param {boolean} configEnabled - enabled flag from config.json
|
|
100
|
+
* @param {boolean} routingActive - whether settings.json has Plexor routing configured
|
|
101
|
+
* @returns {Object|null} mismatch details or null if states are consistent
|
|
102
|
+
*/
|
|
103
|
+
function checkStateMismatch(configEnabled, routingActive) {
|
|
104
|
+
if (configEnabled && !routingActive) {
|
|
105
|
+
return {
|
|
106
|
+
type: 'config-enabled-routing-inactive',
|
|
107
|
+
message: 'Config shows enabled but Claude routing is not configured',
|
|
108
|
+
suggestion: 'Run /plexor-enabled true to sync and configure routing'
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
if (!configEnabled && routingActive) {
|
|
112
|
+
return {
|
|
113
|
+
type: 'config-disabled-routing-active',
|
|
114
|
+
message: 'Config shows disabled but Claude routing is active',
|
|
115
|
+
suggestion: 'Run /plexor-enabled false to sync and disable routing'
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function main() {
|
|
122
|
+
const args = process.argv.slice(2);
|
|
123
|
+
const config = loadConfig();
|
|
124
|
+
const currentEnabled = config.settings?.enabled ?? false;
|
|
125
|
+
const apiKey = config.auth?.api_key;
|
|
126
|
+
|
|
127
|
+
// Get current Claude settings.json routing status
|
|
128
|
+
const routingStatus = settingsManager.getRoutingStatus();
|
|
129
|
+
|
|
130
|
+
// No args - show current status
|
|
131
|
+
if (args.length === 0) {
|
|
132
|
+
const status = currentEnabled ? '● Enabled' : '○ Disabled';
|
|
133
|
+
const routingStr = routingStatus.enabled ? '● Active' : '○ Inactive';
|
|
134
|
+
|
|
135
|
+
// Check for state mismatch between config enabled flag and routing status
|
|
136
|
+
const stateMismatch = checkStateMismatch(currentEnabled, routingStatus.enabled);
|
|
137
|
+
|
|
138
|
+
console.log(`┌─────────────────────────────────────────────┐`);
|
|
139
|
+
console.log(`│ Plexor Proxy Status │`);
|
|
140
|
+
console.log(`├─────────────────────────────────────────────┤`);
|
|
141
|
+
console.log(`│ Plugin Config: ${status.padEnd(27)}│`);
|
|
142
|
+
console.log(`│ Claude Routing: ${routingStr.padEnd(26)}│`);
|
|
143
|
+
if (routingStatus.enabled) {
|
|
144
|
+
console.log(`│ Endpoint: ${(routingStatus.isStaging ? 'Staging' : 'Production').padEnd(32)}│`);
|
|
145
|
+
}
|
|
146
|
+
if (stateMismatch) {
|
|
147
|
+
console.log(`├─────────────────────────────────────────────┤`);
|
|
148
|
+
console.log(`│ ⚠ State mismatch detected: │`);
|
|
149
|
+
console.log(`│ ${stateMismatch.message.padEnd(42)}│`);
|
|
150
|
+
console.log(`│ ${stateMismatch.suggestion.padEnd(42)}│`);
|
|
151
|
+
}
|
|
152
|
+
console.log(`├─────────────────────────────────────────────┤`);
|
|
153
|
+
console.log(`│ Usage: │`);
|
|
154
|
+
console.log(`│ /plexor-enabled true - Enable proxy │`);
|
|
155
|
+
console.log(`│ /plexor-enabled false - Disable proxy │`);
|
|
156
|
+
console.log(`│ /plexor-enabled on - Enable proxy │`);
|
|
157
|
+
console.log(`│ /plexor-enabled off - Disable proxy │`);
|
|
158
|
+
console.log(`└─────────────────────────────────────────────┘`);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const arg = args[0].toLowerCase();
|
|
163
|
+
let newEnabled;
|
|
164
|
+
|
|
165
|
+
if (['true', 'on', 'yes', '1', 'enable'].includes(arg)) {
|
|
166
|
+
newEnabled = true;
|
|
167
|
+
} else if (['false', 'off', 'no', '0', 'disable'].includes(arg)) {
|
|
168
|
+
newEnabled = false;
|
|
169
|
+
} else {
|
|
170
|
+
console.error(`Error: Invalid value "${args[0]}"`);
|
|
171
|
+
console.error(`Use: true/false, on/off, yes/no, enable/disable`);
|
|
172
|
+
process.exit(1);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// THE KEY FEATURE: Update Claude Code settings.json routing
|
|
176
|
+
let routingUpdated = false;
|
|
177
|
+
let missingApiKey = false;
|
|
178
|
+
let invalidApiKey = false;
|
|
179
|
+
|
|
180
|
+
if (newEnabled) {
|
|
181
|
+
// Enable routing - need valid API key from config
|
|
182
|
+
if (!apiKey) {
|
|
183
|
+
missingApiKey = true;
|
|
184
|
+
} else if (!isValidApiKeyFormat(apiKey)) {
|
|
185
|
+
invalidApiKey = true;
|
|
186
|
+
} else {
|
|
187
|
+
// Update Plexor plugin config first
|
|
188
|
+
config.settings = config.settings || {};
|
|
189
|
+
config.settings.enabled = newEnabled;
|
|
190
|
+
if (!saveConfig(config)) {
|
|
191
|
+
process.exit(1);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// LOCALHOST PACKAGE - uses tunnel URL
|
|
195
|
+
const apiUrl = config.settings?.apiUrl || 'LOCALHOST_TUNNEL_URL';
|
|
196
|
+
const useStaging = apiUrl.includes('staging');
|
|
197
|
+
routingUpdated = settingsManager.enablePlexorRouting(apiKey, { useStaging });
|
|
198
|
+
|
|
199
|
+
// Check if settings.json update failed
|
|
200
|
+
if (!routingUpdated) {
|
|
201
|
+
console.log(`┌─────────────────────────────────────────────┐`);
|
|
202
|
+
console.log(`│ ✗ Failed to Enable Plexor Routing │`);
|
|
203
|
+
console.log(`├─────────────────────────────────────────────┤`);
|
|
204
|
+
console.log(`│ Could not update ~/.claude/settings.json │`);
|
|
205
|
+
console.log(`│ Config.json was updated but routing failed.│`);
|
|
206
|
+
console.log(`├─────────────────────────────────────────────┤`);
|
|
207
|
+
console.log(`│ Check file permissions and try again. │`);
|
|
208
|
+
console.log(`└─────────────────────────────────────────────┘`);
|
|
209
|
+
process.exit(1);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
} else {
|
|
213
|
+
// Update Plexor plugin config
|
|
214
|
+
config.settings = config.settings || {};
|
|
215
|
+
config.settings.enabled = newEnabled;
|
|
216
|
+
if (!saveConfig(config)) {
|
|
217
|
+
process.exit(1);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Disable routing - remove env vars from settings.json
|
|
221
|
+
routingUpdated = settingsManager.disablePlexorRouting();
|
|
222
|
+
|
|
223
|
+
// Check if settings.json update failed
|
|
224
|
+
if (!routingUpdated) {
|
|
225
|
+
console.log(`┌─────────────────────────────────────────────┐`);
|
|
226
|
+
console.log(`│ ✗ Failed to Disable Plexor Routing │`);
|
|
227
|
+
console.log(`├─────────────────────────────────────────────┤`);
|
|
228
|
+
console.log(`│ Could not update ~/.claude/settings.json │`);
|
|
229
|
+
console.log(`│ Config.json was updated but routing failed.│`);
|
|
230
|
+
console.log(`├─────────────────────────────────────────────┤`);
|
|
231
|
+
console.log(`│ Check file permissions and try again. │`);
|
|
232
|
+
console.log(`└─────────────────────────────────────────────┘`);
|
|
233
|
+
process.exit(1);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Show error if no API key when enabling
|
|
238
|
+
if (missingApiKey) {
|
|
239
|
+
console.log(`┌─────────────────────────────────────────────┐`);
|
|
240
|
+
console.log(`│ ✗ Cannot Enable Plexor │`);
|
|
241
|
+
console.log(`├─────────────────────────────────────────────┤`);
|
|
242
|
+
console.log(`│ No API key configured. │`);
|
|
243
|
+
console.log(`│ Run /plexor-login <api-key> first. │`);
|
|
244
|
+
console.log(`├─────────────────────────────────────────────┤`);
|
|
245
|
+
console.log(`│ Get your API key at: │`);
|
|
246
|
+
console.log(`│ https://plexor.dev/dashboard/api-keys │`);
|
|
247
|
+
console.log(`└─────────────────────────────────────────────┘`);
|
|
248
|
+
process.exit(1);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// Show error if API key format is invalid
|
|
252
|
+
if (invalidApiKey) {
|
|
253
|
+
console.log(`┌─────────────────────────────────────────────┐`);
|
|
254
|
+
console.log(`│ ✗ Cannot Enable Plexor │`);
|
|
255
|
+
console.log(`├─────────────────────────────────────────────┤`);
|
|
256
|
+
console.log(`│ Invalid API key format in config. │`);
|
|
257
|
+
console.log(`│ Keys must start with "plx_" (20+ chars). │`);
|
|
258
|
+
console.log(`├─────────────────────────────────────────────┤`);
|
|
259
|
+
console.log(`│ Run /plexor-login <api-key> to fix. │`);
|
|
260
|
+
console.log(`└─────────────────────────────────────────────┘`);
|
|
261
|
+
process.exit(1);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const newStatus = newEnabled ? '● Enabled' : '○ Disabled';
|
|
265
|
+
const prevStatus = currentEnabled ? 'Enabled' : 'Disabled';
|
|
266
|
+
const routingMsg = routingUpdated
|
|
267
|
+
? (newEnabled ? 'Claude Code now routes through Plexor' : 'Claude Code now connects directly')
|
|
268
|
+
: 'Manual routing update may be needed';
|
|
269
|
+
|
|
270
|
+
console.log(`┌─────────────────────────────────────────────┐`);
|
|
271
|
+
console.log(`│ ✓ Plexor Proxy Updated │`);
|
|
272
|
+
console.log(`├─────────────────────────────────────────────┤`);
|
|
273
|
+
console.log(`│ Previous: ${prevStatus.padEnd(32)}│`);
|
|
274
|
+
console.log(`│ New: ${newStatus.padEnd(37)}│`);
|
|
275
|
+
console.log(`├─────────────────────────────────────────────┤`);
|
|
276
|
+
console.log(`│ ${routingMsg.padEnd(42)}│`);
|
|
277
|
+
console.log(`│ Changes take effect immediately. │`);
|
|
278
|
+
console.log(`└─────────────────────────────────────────────┘`);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
main();
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Enable or disable Plexor proxy (routes all traffic through Plexor API) (user)
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Plexor Enabled
|
|
6
|
+
|
|
7
|
+
Toggle Plexor proxy on or off.
|
|
8
|
+
|
|
9
|
+
## If argument provided (on/off/true/false)
|
|
10
|
+
|
|
11
|
+
Run the command directly with the argument:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
node ~/.claude/plugins/plexor/commands/plexor-enabled.js <argument>
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Then display the output and STOP.
|
|
18
|
+
|
|
19
|
+
## If NO argument provided
|
|
20
|
+
|
|
21
|
+
**Step 1**: First get current status by running:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
node ~/.claude/plugins/plexor/commands/plexor-enabled.js
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**Step 2**: Based on the output, use AskUserQuestion to present options:
|
|
28
|
+
|
|
29
|
+
If currently ENABLED (shows "● Enabled" or "● Active"):
|
|
30
|
+
- Question: "Plexor is currently ON. What would you like to do?"
|
|
31
|
+
- Header: "Plexor"
|
|
32
|
+
- Options:
|
|
33
|
+
1. **Turn OFF** - Disable Plexor routing (connect directly to Anthropic)
|
|
34
|
+
2. **Keep ON** - No change
|
|
35
|
+
|
|
36
|
+
If currently DISABLED (shows "○ Disabled" or "○ Inactive"):
|
|
37
|
+
- Question: "Plexor is currently OFF. What would you like to do?"
|
|
38
|
+
- Header: "Plexor"
|
|
39
|
+
- Options:
|
|
40
|
+
1. **Turn ON** - Enable Plexor routing
|
|
41
|
+
2. **Keep OFF** - No change
|
|
42
|
+
|
|
43
|
+
**Step 3**: Based on user selection:
|
|
44
|
+
- If "Turn OFF" selected: Run `node ~/.claude/plugins/plexor/commands/plexor-enabled.js false`
|
|
45
|
+
- If "Turn ON" selected: Run `node ~/.claude/plugins/plexor/commands/plexor-enabled.js true`
|
|
46
|
+
- If "Keep" selected: Do nothing, just confirm current state
|
|
47
|
+
|
|
48
|
+
**IMPORTANT**: After completing, STOP. Do not read files, explore codebase, or run additional commands.
|