@plexor-dev/claude-code-plugin 0.1.0-beta.2 → 0.1.0-beta.21

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.
@@ -0,0 +1,170 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Plexor Config Command
5
+ * Display raw configuration (for debugging)
6
+ */
7
+
8
+ const fs = require('fs');
9
+ const path = require('path');
10
+
11
+ const CONFIG_PATH = path.join(process.env.HOME, '.plexor', 'config.json');
12
+ const SESSION_PATH = path.join(process.env.HOME, '.plexor', 'session.json');
13
+ const CACHE_PATH = path.join(process.env.HOME, '.plexor', 'cache.json');
14
+ const PLEXOR_DIR = path.join(process.env.HOME, '.plexor');
15
+
16
+ function fileExists(filePath) {
17
+ try {
18
+ return fs.existsSync(filePath);
19
+ } catch {
20
+ return false;
21
+ }
22
+ }
23
+
24
+ function getFileSize(filePath) {
25
+ try {
26
+ const stats = fs.statSync(filePath);
27
+ return stats.size;
28
+ } catch {
29
+ return 0;
30
+ }
31
+ }
32
+
33
+ function formatBytes(bytes) {
34
+ if (bytes === 0) return '0 B';
35
+ if (bytes < 1024) return `${bytes} B`;
36
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
37
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
38
+ }
39
+
40
+ function loadConfig() {
41
+ try {
42
+ if (!fs.existsSync(CONFIG_PATH)) {
43
+ return { error: 'not_found', message: 'Config file does not exist' };
44
+ }
45
+ const data = fs.readFileSync(CONFIG_PATH, 'utf8');
46
+ return { config: JSON.parse(data) };
47
+ } catch (err) {
48
+ if (err.code === 'ENOENT') {
49
+ return { error: 'not_found', message: 'Config file does not exist' };
50
+ }
51
+ if (err.code === 'EACCES') {
52
+ return { error: 'permission', message: 'Permission denied reading config' };
53
+ }
54
+ if (err instanceof SyntaxError) {
55
+ return { error: 'invalid_json', message: 'Config file contains invalid JSON' };
56
+ }
57
+ return { error: 'unknown', message: err.message };
58
+ }
59
+ }
60
+
61
+ function maskApiKey(key) {
62
+ if (!key) return 'not set';
63
+ if (key.length <= 12) return '***masked***';
64
+ return key.substring(0, 8) + '...' + key.substring(key.length - 4);
65
+ }
66
+
67
+ function main() {
68
+ const args = process.argv.slice(2);
69
+ const showRaw = args.includes('--raw') || args.includes('-r');
70
+ const showPaths = args.includes('--paths') || args.includes('-p');
71
+
72
+ // Show paths only
73
+ if (showPaths) {
74
+ console.log(`┌─────────────────────────────────────────────┐`);
75
+ console.log(`│ Plexor File Paths │`);
76
+ console.log(`├─────────────────────────────────────────────┤`);
77
+ console.log(`│ Directory: ${PLEXOR_DIR.substring(0, 31).padEnd(31)}│`);
78
+ console.log(`│ Config: ${CONFIG_PATH.substring(0, 34).padEnd(34)}│`);
79
+ console.log(`│ Session: ${SESSION_PATH.substring(0, 33).padEnd(33)}│`);
80
+ console.log(`│ Cache: ${CACHE_PATH.substring(0, 35).padEnd(35)}│`);
81
+ console.log(`└─────────────────────────────────────────────┘`);
82
+ return;
83
+ }
84
+
85
+ const result = loadConfig();
86
+
87
+ if (result.error) {
88
+ const errorMessages = {
89
+ not_found: 'Config file does not exist',
90
+ permission: 'Permission denied reading config file',
91
+ invalid_json: 'Config file contains invalid JSON (corrupted?)',
92
+ unknown: result.message || 'Unknown error'
93
+ };
94
+ const errorMsg = errorMessages[result.error] || result.message;
95
+ const suggestion = result.error === 'invalid_json'
96
+ ? 'Try: rm ~/.plexor/config.json && /plexor-login'
97
+ : 'Run /plexor-login to create configuration.';
98
+
99
+ console.log(`┌─────────────────────────────────────────────┐`);
100
+ console.log(`│ Configuration Error │`);
101
+ console.log(`├─────────────────────────────────────────────┤`);
102
+ console.log(`│ Error: ${result.error.padEnd(35)}│`);
103
+ console.log(`│ ${errorMsg.substring(0, 42).padEnd(42)}│`);
104
+ console.log(`├─────────────────────────────────────────────┤`);
105
+ console.log(`│ ${suggestion.substring(0, 42).padEnd(42)}│`);
106
+ console.log(`├─────────────────────────────────────────────┤`);
107
+ console.log(`│ Expected path: │`);
108
+ console.log(`│ ${CONFIG_PATH.substring(0, 42).padEnd(42)}│`);
109
+ console.log(`└─────────────────────────────────────────────┘`);
110
+ return;
111
+ }
112
+
113
+ const config = result.config;
114
+
115
+ // Show raw JSON
116
+ if (showRaw) {
117
+ // Mask API key in raw output
118
+ const safeConfig = JSON.parse(JSON.stringify(config));
119
+ if (safeConfig.auth?.api_key) {
120
+ safeConfig.auth.api_key = maskApiKey(safeConfig.auth.api_key);
121
+ }
122
+ console.log(JSON.stringify(safeConfig, null, 2));
123
+ return;
124
+ }
125
+
126
+ // Show formatted config info
127
+ const configSize = getFileSize(CONFIG_PATH);
128
+ const sessionSize = getFileSize(SESSION_PATH);
129
+ const cacheSize = getFileSize(CACHE_PATH);
130
+ const hasSession = fileExists(SESSION_PATH);
131
+ const hasCache = fileExists(CACHE_PATH);
132
+
133
+ console.log(`┌─────────────────────────────────────────────┐`);
134
+ console.log(`│ Plexor Configuration │`);
135
+ console.log(`├─────────────────────────────────────────────┤`);
136
+ console.log(`│ Version: ${(config.version || 1).toString().padEnd(33)}│`);
137
+ console.log(`├─────────────────────────────────────────────┤`);
138
+ console.log(`│ Authentication │`);
139
+ console.log(`│ └── API Key: ${maskApiKey(config.auth?.api_key).padEnd(29)}│`);
140
+ console.log(`├─────────────────────────────────────────────┤`);
141
+ console.log(`│ Settings │`);
142
+
143
+ const settings = config.settings || {};
144
+ const settingEntries = [
145
+ ['enabled', settings.enabled ?? false],
146
+ ['mode', settings.mode || 'balanced'],
147
+ ['preferred_provider', settings.preferred_provider || 'auto'],
148
+ ['apiUrl', settings.apiUrl || 'https://api.plexor.dev'],
149
+ ['timeout', (settings.timeout || 5000) + 'ms'],
150
+ ['localCacheEnabled', settings.localCacheEnabled ?? false]
151
+ ];
152
+
153
+ for (const [key, value] of settingEntries) {
154
+ const displayValue = String(value).substring(0, 25);
155
+ console.log(`│ ├── ${key.padEnd(18)} ${displayValue.padEnd(18)}│`);
156
+ }
157
+
158
+ console.log(`├─────────────────────────────────────────────┤`);
159
+ console.log(`│ Files │`);
160
+ console.log(`│ ├── config.json: ${formatBytes(configSize).padEnd(24)}│`);
161
+ console.log(`│ ├── session.json: ${(hasSession ? formatBytes(sessionSize) : 'not found').padEnd(23)}│`);
162
+ console.log(`│ └── cache.json: ${(hasCache ? formatBytes(cacheSize) : 'not found').padEnd(25)}│`);
163
+ console.log(`├─────────────────────────────────────────────┤`);
164
+ console.log(`│ Options: │`);
165
+ console.log(`│ /plexor-config --raw Show raw JSON │`);
166
+ console.log(`│ /plexor-config --paths Show file paths │`);
167
+ console.log(`└─────────────────────────────────────────────┘`);
168
+ }
169
+
170
+ main();
@@ -1,43 +1,44 @@
1
1
  ---
2
- description: Configure Plexor settings
2
+ description: Configure Plexor settings (user)
3
3
  ---
4
4
 
5
5
  # Plexor Config
6
6
 
7
- Configure Plexor optimization settings.
7
+ View and modify Plexor configuration. This is an alias for /plexor-settings.
8
8
 
9
- ## Arguments
9
+ ## Steps
10
10
 
11
- $ARGUMENTS - Configuration command and value
11
+ **Step 1: Read current configuration**
12
12
 
13
- ## Supported Commands
14
-
15
- - `plexor-config show` - Show current configuration
16
- - `plexor-config enable` - Enable Plexor optimization
17
- - `plexor-config disable` - Disable Plexor optimization
18
- - `plexor-config cache on|off` - Enable/disable local cache
19
- - `plexor-config provider <name>` - Set preferred provider (anthropic, deepseek, auto)
20
- - `plexor-config reset` - Reset to default configuration
21
-
22
- ## Instructions
23
-
24
- 1. Parse the arguments to determine the command
25
- 2. Read current config from ~/.plexor/config.json
26
- 3. Apply the requested change
27
- 4. Save updated config
28
- 5. Display confirmation
29
-
30
- ## Output
13
+ Use the Read tool to read `~/.plexor/config.json`.
31
14
 
15
+ If the file doesn't exist, show:
16
+ ```
17
+ Plexor Config
18
+ =============
19
+ No configuration found. Run /plexor-login to set up Plexor.
32
20
  ```
33
- Plexor Configuration Updated
34
- ============================
35
21
 
36
- Local cache: Enabled Disabled
22
+ **Step 2: Display current configuration**
37
23
 
38
- Current settings:
39
- ├── Optimization: Enabled
40
- ├── Local cache: Disabled
41
- ├── Preferred provider: Auto
42
- └── Telemetry: Enabled
43
24
  ```
25
+ Plexor Config
26
+ =============
27
+ Enabled: [enabled]
28
+ API URL: [apiUrl]
29
+ API Key: [show "configured" if apiKey exists, otherwise "not configured"]
30
+ Mode: [mode]
31
+ Provider: [preferredProvider]
32
+ Local Cache: [localCacheEnabled]
33
+ Timeout: [timeout]ms
34
+
35
+ Configuration file: ~/.plexor/config.json
36
+
37
+ Other commands:
38
+ - /plexor-settings - View/edit all settings
39
+ - /plexor-mode - Change optimization mode
40
+ - /plexor-provider - Change provider
41
+ - /plexor-enabled - Enable/disable proxy
42
+ ```
43
+
44
+ **IMPORTANT**: After completing the task, STOP. Do not run additional commands or explore the codebase.
@@ -0,0 +1,91 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Plexor Enabled Command
5
+ * Enable or disable Plexor optimization proxy
6
+ */
7
+
8
+ const fs = require('fs');
9
+ const path = require('path');
10
+
11
+ const CONFIG_PATH = path.join(process.env.HOME, '.plexor', 'config.json');
12
+ const PLEXOR_DIR = path.join(process.env.HOME, '.plexor');
13
+
14
+ function loadConfig() {
15
+ try {
16
+ const data = fs.readFileSync(CONFIG_PATH, 'utf8');
17
+ return JSON.parse(data);
18
+ } catch {
19
+ return { version: 1, auth: {}, settings: {} };
20
+ }
21
+ }
22
+
23
+ function saveConfig(config) {
24
+ if (!fs.existsSync(PLEXOR_DIR)) {
25
+ fs.mkdirSync(PLEXOR_DIR, { recursive: true, mode: 0o700 });
26
+ }
27
+ fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2), { mode: 0o600 });
28
+ }
29
+
30
+ function main() {
31
+ const args = process.argv.slice(2);
32
+ const config = loadConfig();
33
+ const currentEnabled = config.settings?.enabled ?? false;
34
+
35
+ // No args - show current status
36
+ if (args.length === 0) {
37
+ const status = currentEnabled ? '● Enabled' : '○ Disabled';
38
+ console.log(`┌─────────────────────────────────────────────┐`);
39
+ console.log(`│ Plexor Proxy Status │`);
40
+ console.log(`├─────────────────────────────────────────────┤`);
41
+ console.log(`│ Status: ${status.padEnd(34)}│`);
42
+ console.log(`├─────────────────────────────────────────────┤`);
43
+ console.log(`│ Usage: │`);
44
+ console.log(`│ /plexor-enabled true - Enable proxy │`);
45
+ console.log(`│ /plexor-enabled false - Disable proxy │`);
46
+ console.log(`│ /plexor-enabled on - Enable proxy │`);
47
+ console.log(`│ /plexor-enabled off - Disable proxy │`);
48
+ console.log(`└─────────────────────────────────────────────┘`);
49
+ return;
50
+ }
51
+
52
+ const arg = args[0].toLowerCase();
53
+ let newEnabled;
54
+
55
+ if (['true', 'on', 'yes', '1', 'enable'].includes(arg)) {
56
+ newEnabled = true;
57
+ } else if (['false', 'off', 'no', '0', 'disable'].includes(arg)) {
58
+ newEnabled = false;
59
+ } else {
60
+ console.error(`Error: Invalid value "${args[0]}"`);
61
+ console.error(`Use: true/false, on/off, yes/no, enable/disable`);
62
+ process.exit(1);
63
+ }
64
+
65
+ if (newEnabled === currentEnabled) {
66
+ const state = currentEnabled ? 'enabled' : 'disabled';
67
+ console.log(`Plexor proxy is already ${state}`);
68
+ return;
69
+ }
70
+
71
+ config.settings = config.settings || {};
72
+ config.settings.enabled = newEnabled;
73
+ saveConfig(config);
74
+
75
+ const newStatus = newEnabled ? '● Enabled' : '○ Disabled';
76
+ const prevStatus = currentEnabled ? 'Enabled' : 'Disabled';
77
+ const message = newEnabled
78
+ ? 'All requests will be routed through Plexor'
79
+ : 'Requests will go directly to providers';
80
+
81
+ console.log(`┌─────────────────────────────────────────────┐`);
82
+ console.log(`│ ✓ Plexor Proxy Updated │`);
83
+ console.log(`├─────────────────────────────────────────────┤`);
84
+ console.log(`│ Previous: ${prevStatus.padEnd(32)}│`);
85
+ console.log(`│ New: ${newStatus.padEnd(37)}│`);
86
+ console.log(`├─────────────────────────────────────────────┤`);
87
+ console.log(`│ ${message.padEnd(42)}│`);
88
+ console.log(`└─────────────────────────────────────────────┘`);
89
+ }
90
+
91
+ main();
@@ -1,36 +1,56 @@
1
1
  ---
2
- description: Enable or disable Plexor proxy (routes all traffic through Plexor API)
2
+ description: Enable or disable Plexor proxy (routes all traffic through Plexor API) (user)
3
3
  ---
4
4
 
5
+ # Plexor Enabled
6
+
5
7
  Toggle Plexor proxy mode on or off.
6
8
 
7
- **IMPORTANT**: Use the `AskUserQuestion` tool to present the user with these options:
9
+ ## Steps
10
+
11
+ **Step 1: Read current configuration**
12
+
13
+ Use the Read tool to read `~/.plexor/config.json` and check the current `enabled` status.
14
+
15
+ **Step 2: Ask user what they want to do**
8
16
 
9
- Question: "Enable Plexor proxy? (routes all prompts through Plexor for optimization)"
17
+ Use the `AskUserQuestion` tool to present options:
18
+
19
+ Question: "Enable or disable Plexor proxy?"
10
20
  Header: "Proxy"
11
21
  Options:
12
- 1. **Enable** - Route all traffic through Plexor API (60-90% cost savings)
13
- 2. **Disable** - Direct to Anthropic (no optimization)
14
-
15
- After the user selects an option:
16
-
17
- ### If Enable:
18
- 1. Update ~/.plexor/config.json: `{"enabled": true}`
19
- 2. Inform user to set environment variable:
20
- ```
21
- export ANTHROPIC_BASE_URL="http://localhost:8000/gateway/anthropic"
22
- ```
23
- 3. Tell user to restart Claude Code: `claude --continue`
24
- 4. Explain benefits:
25
- - 60-90% cost reduction via Mistral/DeepSeek/Gemini/OpenAI routing
26
- - Automatic provider selection based on mode
27
- - Session tracking and savings analytics
28
-
29
- ### If Disable:
30
- 1. Update ~/.plexor/config.json: `{"enabled": false}`
31
- 2. Inform user to unset environment variable:
32
- ```
33
- unset ANTHROPIC_BASE_URL
34
- ```
35
- 3. Tell user to restart Claude Code: `claude --continue`
36
- 4. Note: Prompts will go directly to Anthropic at full price
22
+ 1. **Enable** - Route traffic through Plexor for optimization (60-90% cost savings)
23
+ 2. **Disable** - Direct to Anthropic (no optimization, full price)
24
+
25
+ **Step 3: Update the configuration**
26
+
27
+ Use the Read tool to get the current config, then use the Write tool to update `~/.plexor/config.json`:
28
+ - If **Enable**: Set `"enabled": true`
29
+ - If **Disable**: Set `"enabled": false`
30
+
31
+ Keep all other settings unchanged.
32
+
33
+ **Step 4: Show confirmation**
34
+
35
+ If **Enabled**:
36
+ ```
37
+ Plexor Proxy: ENABLED
38
+
39
+ Benefits:
40
+ - 60-90% cost reduction via intelligent provider routing
41
+ - Automatic selection of Mistral/DeepSeek/Gemini based on task
42
+ - Usage tracking and savings analytics
43
+
44
+ Your prompts will now be routed through Plexor for optimization.
45
+ Run /plexor-status to see your savings.
46
+ ```
47
+
48
+ If **Disabled**:
49
+ ```
50
+ Plexor Proxy: DISABLED
51
+
52
+ Your prompts will go directly to Anthropic at full price.
53
+ Run /plexor-enabled to re-enable optimization.
54
+ ```
55
+
56
+ **IMPORTANT**: After completing the task, STOP. Do not run additional commands or explore the codebase.
@@ -0,0 +1,169 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Plexor Login Command
5
+ * Authenticate with Plexor API
6
+ */
7
+
8
+ const fs = require('fs');
9
+ const path = require('path');
10
+ const https = require('https');
11
+ const http = require('http');
12
+
13
+ const CONFIG_PATH = path.join(process.env.HOME, '.plexor', 'config.json');
14
+ const PLEXOR_DIR = path.join(process.env.HOME, '.plexor');
15
+ const DEFAULT_API_URL = 'https://api.plexor.dev';
16
+
17
+ function loadConfig() {
18
+ try {
19
+ const data = fs.readFileSync(CONFIG_PATH, 'utf8');
20
+ return JSON.parse(data);
21
+ } catch {
22
+ return { version: 1, auth: {}, settings: {} };
23
+ }
24
+ }
25
+
26
+ function saveConfig(config) {
27
+ if (!fs.existsSync(PLEXOR_DIR)) {
28
+ fs.mkdirSync(PLEXOR_DIR, { recursive: true, mode: 0o700 });
29
+ }
30
+ fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2), { mode: 0o600 });
31
+ }
32
+
33
+ function validateApiKey(apiUrl, apiKey) {
34
+ return new Promise((resolve, reject) => {
35
+ const url = new URL(`${apiUrl}/v1/user`);
36
+ const isHttps = url.protocol === 'https:';
37
+ const lib = isHttps ? https : http;
38
+
39
+ const options = {
40
+ hostname: url.hostname,
41
+ port: url.port || (isHttps ? 443 : 80),
42
+ path: url.pathname,
43
+ method: 'GET',
44
+ headers: {
45
+ 'X-Plexor-Key': apiKey
46
+ }
47
+ };
48
+
49
+ const req = lib.request(options, (res) => {
50
+ let data = '';
51
+ res.on('data', chunk => data += chunk);
52
+ res.on('end', () => {
53
+ if (res.statusCode === 200) {
54
+ try {
55
+ resolve(JSON.parse(data));
56
+ } catch {
57
+ reject(new Error('Invalid response from server'));
58
+ }
59
+ } else if (res.statusCode === 401) {
60
+ reject(new Error('Invalid API key'));
61
+ } else {
62
+ reject(new Error(`Server error: ${res.statusCode}`));
63
+ }
64
+ });
65
+ });
66
+
67
+ req.on('error', (err) => reject(new Error(`Connection failed: ${err.message}`)));
68
+ req.setTimeout(10000, () => {
69
+ req.destroy();
70
+ reject(new Error('Connection timeout'));
71
+ });
72
+ req.end();
73
+ });
74
+ }
75
+
76
+ async function promptForApiKey() {
77
+ const rl = readline.createInterface({
78
+ input: process.stdin,
79
+ output: process.stdout
80
+ });
81
+
82
+ return new Promise((resolve) => {
83
+ rl.question('Enter your Plexor API key: ', (answer) => {
84
+ rl.close();
85
+ resolve(answer.trim());
86
+ });
87
+ });
88
+ }
89
+
90
+ async function main() {
91
+ const args = process.argv.slice(2);
92
+ let apiKey = args[0];
93
+
94
+ // Check for existing login
95
+ const config = loadConfig();
96
+ const existingKey = config.auth?.api_key;
97
+
98
+ if (existingKey && !apiKey) {
99
+ console.log(`┌─────────────────────────────────────────────┐`);
100
+ console.log(`│ Already Logged In │`);
101
+ console.log(`├─────────────────────────────────────────────┤`);
102
+ console.log(`│ API Key: ${(existingKey.substring(0, 8) + '...').padEnd(33)}│`);
103
+ console.log(`│ To re-login, provide a new key: │`);
104
+ console.log(`│ /plexor-login <api-key> │`);
105
+ console.log(`│ To logout: │`);
106
+ console.log(`│ /plexor-logout │`);
107
+ console.log(`└─────────────────────────────────────────────┘`);
108
+ return;
109
+ }
110
+
111
+ // If no key provided, prompt for it
112
+ if (!apiKey) {
113
+ console.log(`┌─────────────────────────────────────────────┐`);
114
+ console.log(`│ Plexor Login │`);
115
+ console.log(`├─────────────────────────────────────────────┤`);
116
+ console.log(`│ Get your API key at: │`);
117
+ console.log(`│ https://plexor.dev/dashboard/api-keys │`);
118
+ console.log(`├─────────────────────────────────────────────┤`);
119
+ console.log(`│ Usage: /plexor-login <api-key> │`);
120
+ console.log(`└─────────────────────────────────────────────┘`);
121
+ return;
122
+ }
123
+
124
+ // Validate key format
125
+ if (!apiKey.startsWith('plx_') || apiKey.length < 20) {
126
+ console.error(`Error: Invalid API key format`);
127
+ console.error(`API keys start with "plx_" and are at least 20 characters`);
128
+ process.exit(1);
129
+ }
130
+
131
+ const apiUrl = config.settings?.apiUrl || DEFAULT_API_URL;
132
+
133
+ console.log('Validating API key...');
134
+
135
+ try {
136
+ const user = await validateApiKey(apiUrl, apiKey);
137
+
138
+ config.auth = config.auth || {};
139
+ config.auth.api_key = apiKey;
140
+ config.settings = config.settings || {};
141
+ config.settings.enabled = true;
142
+ saveConfig(config);
143
+
144
+ const email = user.email || 'Unknown';
145
+ const tier = user.tier?.name || 'Free';
146
+
147
+ console.log(`┌─────────────────────────────────────────────┐`);
148
+ console.log(`│ ✓ Login Successful │`);
149
+ console.log(`├─────────────────────────────────────────────┤`);
150
+ console.log(`│ Email: ${email.substring(0, 35).padEnd(35)}│`);
151
+ console.log(`│ Tier: ${tier.padEnd(36)}│`);
152
+ console.log(`├─────────────────────────────────────────────┤`);
153
+ console.log(`│ Plexor proxy is now enabled. │`);
154
+ console.log(`│ Run /plexor-status to see your stats. │`);
155
+ console.log(`└─────────────────────────────────────────────┘`);
156
+ } catch (err) {
157
+ console.error(`┌─────────────────────────────────────────────┐`);
158
+ console.error(`│ ✗ Login Failed │`);
159
+ console.error(`├─────────────────────────────────────────────┤`);
160
+ console.error(`│ ${err.message.padEnd(42)}│`);
161
+ console.error(`└─────────────────────────────────────────────┘`);
162
+ process.exit(1);
163
+ }
164
+ }
165
+
166
+ main().catch(err => {
167
+ console.error('Error:', err.message);
168
+ process.exit(1);
169
+ });