@mmmbuto/nexuscli 0.7.8 → 0.8.0
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/README.md +17 -17
- package/lib/cli/model.js +4 -4
- package/lib/cli/uninstall.js +29 -29
- package/lib/setup/postinstall.js +4 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
## Overview
|
|
11
11
|
|
|
12
|
-
NexusCLI
|
|
12
|
+
NexusCLI is a lightweight AI cockpit (Termux-first) to orchestrate Claude Code, Codex CLI, and Gemini CLI from the web/terminal, with live interrupt and native session resume.
|
|
13
13
|
|
|
14
14
|
---
|
|
15
15
|
|
|
@@ -28,14 +28,14 @@ NexusCLI è un cockpit AI leggero (Termux-first) per orchestrare Claude Code, Co
|
|
|
28
28
|
|
|
29
29
|
---
|
|
30
30
|
|
|
31
|
-
## Highlights (v0.
|
|
31
|
+
## Highlights (v0.8.0)
|
|
32
32
|
|
|
33
33
|
- Multi-engine: Claude, Codex, Gemini
|
|
34
|
-
-
|
|
35
|
-
-
|
|
36
|
-
-
|
|
37
|
-
- Voice input (Whisper), HTTPS
|
|
38
|
-
-
|
|
34
|
+
- Native resume: same engine resumes the session; switching engines uses handoff with summary/history
|
|
35
|
+
- Reliable stop: stop button interrupts the active process (Claude/Codex/Gemini)
|
|
36
|
+
- Session import: on startup it imports native sessions from ~/.claude ~/.codex ~/.gemini; manual endpoint `POST /api/v1/sessions/import`
|
|
37
|
+
- Voice input (Whisper), auto HTTPS for remote microphone
|
|
38
|
+
- Mobile-first UI with SSE streaming and explicit workspace selection
|
|
39
39
|
|
|
40
40
|
## Supported Engines
|
|
41
41
|
|
|
@@ -85,16 +85,16 @@ nexuscli start
|
|
|
85
85
|
|
|
86
86
|
| Command | Description |
|
|
87
87
|
|---------|-------------|
|
|
88
|
-
| `nexuscli init` | Setup wizard (config,
|
|
89
|
-
| `nexuscli start` |
|
|
90
|
-
| `nexuscli stop` |
|
|
91
|
-
| `nexuscli status` |
|
|
92
|
-
| `nexuscli engines` |
|
|
93
|
-
| `nexuscli workspaces` |
|
|
94
|
-
| `nexuscli model` |
|
|
95
|
-
| `nexuscli api` | API keys
|
|
96
|
-
| `nexuscli users` |
|
|
97
|
-
| `POST /api/v1/sessions/import` | Import
|
|
88
|
+
| `nexuscli init` | Setup wizard (config, certs, data) |
|
|
89
|
+
| `nexuscli start` | Start server (HTTP 41800 / HTTPS 41801) |
|
|
90
|
+
| `nexuscli stop` | Stop server |
|
|
91
|
+
| `nexuscli status` | Status and available engines |
|
|
92
|
+
| `nexuscli engines` | Manage engines |
|
|
93
|
+
| `nexuscli workspaces` | Manage workspaces |
|
|
94
|
+
| `nexuscli model` | Default model |
|
|
95
|
+
| `nexuscli api` | Additional API keys (e.g., Whisper) |
|
|
96
|
+
| `nexuscli users` | Users |
|
|
97
|
+
| `POST /api/v1/sessions/import` | Import native sessions (admin) |
|
|
98
98
|
|
|
99
99
|
---
|
|
100
100
|
|
package/lib/cli/model.js
CHANGED
|
@@ -17,8 +17,8 @@ const {
|
|
|
17
17
|
|
|
18
18
|
async function modelCommand(modelId) {
|
|
19
19
|
if (!isInitialized()) {
|
|
20
|
-
console.log(chalk.red('NexusCLI
|
|
21
|
-
console.log(chalk.yellow('
|
|
20
|
+
console.log(chalk.red('NexusCLI is not initialized.'));
|
|
21
|
+
console.log(chalk.yellow('Run first: nexuscli init'));
|
|
22
22
|
return;
|
|
23
23
|
}
|
|
24
24
|
|
|
@@ -26,7 +26,7 @@ async function modelCommand(modelId) {
|
|
|
26
26
|
const allModels = getAllModels();
|
|
27
27
|
|
|
28
28
|
const printAvailableModels = () => {
|
|
29
|
-
console.log(chalk.bold('\
|
|
29
|
+
console.log(chalk.bold('\nAvailable models:'));
|
|
30
30
|
for (const [key, cli] of Object.entries(cliTools)) {
|
|
31
31
|
console.log(chalk.dim(`${cli.name}:`));
|
|
32
32
|
for (const model of cli.models || []) {
|
|
@@ -56,7 +56,7 @@ async function modelCommand(modelId) {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
if (!isValidModelId(modelId)) {
|
|
59
|
-
console.log(chalk.red(`✗
|
|
59
|
+
console.log(chalk.red(`✗ Invalid model: ${modelId}`));
|
|
60
60
|
printAvailableModels();
|
|
61
61
|
process.exitCode = 1;
|
|
62
62
|
return;
|
package/lib/cli/uninstall.js
CHANGED
|
@@ -62,22 +62,22 @@ async function uninstallCommand(options) {
|
|
|
62
62
|
const bootExists = fs.existsSync(BOOT_SCRIPT);
|
|
63
63
|
|
|
64
64
|
if (!dataExists && !bootExists) {
|
|
65
|
-
console.log(chalk.yellow('
|
|
65
|
+
console.log(chalk.yellow('No NexusCLI data found.'));
|
|
66
66
|
console.log('');
|
|
67
|
-
console.log('
|
|
67
|
+
console.log('To remove the npm package, run:');
|
|
68
68
|
console.log(chalk.cyan(' npm uninstall -g @mmmbuto/nexuscli'));
|
|
69
69
|
console.log('');
|
|
70
70
|
return;
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
// Show what will be affected
|
|
74
|
-
console.log(chalk.white.bold('
|
|
74
|
+
console.log(chalk.white.bold('Data found:'));
|
|
75
75
|
console.log('');
|
|
76
76
|
|
|
77
77
|
if (dataExists) {
|
|
78
78
|
const dataSize = getDirSize(DATA_DIR);
|
|
79
79
|
console.log(chalk.cyan(` 📁 ${DATA_DIR}`));
|
|
80
|
-
console.log(chalk.gray(`
|
|
80
|
+
console.log(chalk.gray(` Size: ${formatSize(dataSize)}`));
|
|
81
81
|
|
|
82
82
|
// List contents
|
|
83
83
|
const contents = fs.readdirSync(DATA_DIR);
|
|
@@ -93,57 +93,57 @@ async function uninstallCommand(options) {
|
|
|
93
93
|
|
|
94
94
|
if (bootExists) {
|
|
95
95
|
console.log(chalk.cyan(` 🚀 ${BOOT_SCRIPT}`));
|
|
96
|
-
console.log(chalk.gray('
|
|
96
|
+
console.log(chalk.gray(' Termux auto-start script'));
|
|
97
97
|
console.log('');
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
// Stop server if running
|
|
101
|
-
console.log(chalk.yellow('
|
|
101
|
+
console.log(chalk.yellow('Stopping server...'));
|
|
102
102
|
try {
|
|
103
103
|
execSync('pkill -f "node.*nexuscli" 2>/dev/null || true', { stdio: 'ignore' });
|
|
104
|
-
console.log(chalk.green('✓ Server
|
|
104
|
+
console.log(chalk.green('✓ Server stopped'));
|
|
105
105
|
} catch (e) {
|
|
106
|
-
console.log(chalk.gray(' Server
|
|
106
|
+
console.log(chalk.gray(' Server not running'));
|
|
107
107
|
}
|
|
108
108
|
console.log('');
|
|
109
109
|
|
|
110
110
|
// Ask what to do
|
|
111
|
-
console.log(chalk.white.bold('
|
|
111
|
+
console.log(chalk.white.bold('Choose an option:'));
|
|
112
112
|
console.log('');
|
|
113
|
-
console.log(chalk.cyan(' 1)') + '
|
|
114
|
-
console.log(chalk.cyan(' 2)') + '
|
|
115
|
-
console.log(chalk.cyan(' 3)') + '
|
|
113
|
+
console.log(chalk.cyan(' 1)') + ' Remove EVERYTHING (data + configuration + boot script)');
|
|
114
|
+
console.log(chalk.cyan(' 2)') + ' Keep data (remove only boot script)');
|
|
115
|
+
console.log(chalk.cyan(' 3)') + ' Cancel');
|
|
116
116
|
console.log('');
|
|
117
117
|
|
|
118
|
-
const choice = await prompt(chalk.yellow('
|
|
118
|
+
const choice = await prompt(chalk.yellow('Choice [1/2/3]: '));
|
|
119
119
|
|
|
120
120
|
if (choice === '3' || choice === 'n' || choice === 'no' || choice === '') {
|
|
121
121
|
console.log('');
|
|
122
|
-
console.log(chalk.green('
|
|
122
|
+
console.log(chalk.green('Operation cancelled.'));
|
|
123
123
|
return;
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
if (choice === '1') {
|
|
127
127
|
// Remove everything
|
|
128
128
|
console.log('');
|
|
129
|
-
const confirm = await prompt(chalk.red.bold('⚠️
|
|
129
|
+
const confirm = await prompt(chalk.red.bold('⚠️ WARNING: All data will be deleted! Confirm? [y/N]: '));
|
|
130
130
|
|
|
131
131
|
if (confirm !== 's' && confirm !== 'si' && confirm !== 'y' && confirm !== 'yes') {
|
|
132
132
|
console.log('');
|
|
133
|
-
console.log(chalk.green('
|
|
133
|
+
console.log(chalk.green('Operation cancelled.'));
|
|
134
134
|
return;
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
console.log('');
|
|
138
|
-
console.log(chalk.yellow('
|
|
138
|
+
console.log(chalk.yellow('Removing...'));
|
|
139
139
|
|
|
140
140
|
// Remove boot script
|
|
141
141
|
if (bootExists) {
|
|
142
142
|
try {
|
|
143
143
|
fs.unlinkSync(BOOT_SCRIPT);
|
|
144
|
-
console.log(chalk.green(`✓
|
|
144
|
+
console.log(chalk.green(`✓ Removed ${BOOT_SCRIPT}`));
|
|
145
145
|
} catch (e) {
|
|
146
|
-
console.log(chalk.red(`✗
|
|
146
|
+
console.log(chalk.red(`✗ Failed to remove boot script: ${e.message}`));
|
|
147
147
|
}
|
|
148
148
|
}
|
|
149
149
|
|
|
@@ -151,14 +151,14 @@ async function uninstallCommand(options) {
|
|
|
151
151
|
if (dataExists) {
|
|
152
152
|
try {
|
|
153
153
|
fs.rmSync(DATA_DIR, { recursive: true, force: true });
|
|
154
|
-
console.log(chalk.green(`✓
|
|
154
|
+
console.log(chalk.green(`✓ Removed ${DATA_DIR}`));
|
|
155
155
|
} catch (e) {
|
|
156
|
-
console.log(chalk.red(`✗
|
|
156
|
+
console.log(chalk.red(`✗ Failed to remove data: ${e.message}`));
|
|
157
157
|
}
|
|
158
158
|
}
|
|
159
159
|
|
|
160
160
|
console.log('');
|
|
161
|
-
console.log(chalk.green.bold('✓
|
|
161
|
+
console.log(chalk.green.bold('✓ Cleanup complete!'));
|
|
162
162
|
|
|
163
163
|
} else if (choice === '2') {
|
|
164
164
|
// Keep data, only remove boot script
|
|
@@ -167,25 +167,25 @@ async function uninstallCommand(options) {
|
|
|
167
167
|
if (bootExists) {
|
|
168
168
|
try {
|
|
169
169
|
fs.unlinkSync(BOOT_SCRIPT);
|
|
170
|
-
console.log(chalk.green(`✓
|
|
170
|
+
console.log(chalk.green(`✓ Removed ${BOOT_SCRIPT}`));
|
|
171
171
|
} catch (e) {
|
|
172
|
-
console.log(chalk.red(`✗
|
|
172
|
+
console.log(chalk.red(`✗ Failed to remove boot script: ${e.message}`));
|
|
173
173
|
}
|
|
174
174
|
}
|
|
175
175
|
|
|
176
176
|
console.log('');
|
|
177
|
-
console.log(chalk.green.bold('✓ Boot script
|
|
178
|
-
console.log(chalk.cyan(`
|
|
179
|
-
console.log(chalk.gray('
|
|
177
|
+
console.log(chalk.green.bold('✓ Boot script removed'));
|
|
178
|
+
console.log(chalk.cyan(` Your data remains in: ${DATA_DIR}`));
|
|
179
|
+
console.log(chalk.gray(' Reinstalling NexusCLI will restore your configuration.'));
|
|
180
180
|
|
|
181
181
|
} else {
|
|
182
182
|
console.log('');
|
|
183
|
-
console.log(chalk.red('
|
|
183
|
+
console.log(chalk.red('Invalid choice. Operation cancelled.'));
|
|
184
184
|
return;
|
|
185
185
|
}
|
|
186
186
|
|
|
187
187
|
console.log('');
|
|
188
|
-
console.log(chalk.white.bold('
|
|
188
|
+
console.log(chalk.white.bold('To finish uninstalling, run:'));
|
|
189
189
|
console.log('');
|
|
190
190
|
console.log(chalk.cyan(' npm uninstall -g @mmmbuto/nexuscli'));
|
|
191
191
|
console.log('');
|
package/lib/setup/postinstall.js
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
const { execSync, spawn } = require('child_process');
|
|
8
8
|
const fs = require('fs');
|
|
9
9
|
const path = require('path');
|
|
10
|
+
const pkg = require('../../package.json');
|
|
10
11
|
|
|
11
12
|
// Check if running in Termux
|
|
12
13
|
const isTermux =
|
|
@@ -127,8 +128,10 @@ async function main() {
|
|
|
127
128
|
// ============================================
|
|
128
129
|
// TERMUX INSTALLATION
|
|
129
130
|
// ============================================
|
|
131
|
+
const versionLabel = `📱 NexusCLI TRI CLI v${pkg.version}`;
|
|
132
|
+
const padding = Math.max(0, 45 - versionLabel.length);
|
|
130
133
|
console.log(colors.bold('╔═══════════════════════════════════════════════════╗'));
|
|
131
|
-
console.log(colors.bold('
|
|
134
|
+
console.log(colors.bold(`║ ${versionLabel}${' '.repeat(padding)}║`));
|
|
132
135
|
console.log(colors.bold('║ Claude • Codex • Gemini ║'));
|
|
133
136
|
console.log(colors.bold('╚═══════════════════════════════════════════════════╝'));
|
|
134
137
|
console.log('');
|