ninja-terminals 2.3.2 → 2.3.4

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.
Files changed (2) hide show
  1. package/cli.js +110 -19
  2. package/package.json +1 -1
package/cli.js CHANGED
@@ -54,6 +54,10 @@ if (hasFlag('--version') || hasFlag('-v')) {
54
54
 
55
55
  // ── Setup command ───────────────────────────────────────────
56
56
  if (hasFlag('--setup')) {
57
+ runSetup().then(() => process.exit(0)).catch(e => { console.error(e); process.exit(1); });
58
+ }
59
+
60
+ async function runSetup() {
57
61
  const fs = require('fs');
58
62
  const path = require('path');
59
63
  const os = require('os');
@@ -100,8 +104,13 @@ if (hasFlag('--setup')) {
100
104
  }
101
105
  };
102
106
 
103
- // Get npm root for copying orchestrator prompt
104
- const npmRoot = path.dirname(require.resolve('ninja-terminals/package.json'));
107
+ // Get npm root for copying orchestrator prompt (works in dev and installed mode)
108
+ let npmRoot;
109
+ try {
110
+ npmRoot = path.dirname(require.resolve('ninja-terminals/package.json'));
111
+ } catch {
112
+ npmRoot = __dirname; // Dev mode fallback
113
+ }
105
114
 
106
115
  fs.writeFileSync(settingsPath, JSON.stringify(mcpConfig, null, 2) + '\n');
107
116
  console.log(`✅ Added ninja-terminals to ${settingsPath}`);
@@ -166,30 +175,110 @@ if (hasFlag('--setup')) {
166
175
 
167
176
  console.log(`
168
177
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
178
+ ✅ MCP configured!
179
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
180
+ `);
181
+
182
+ // Now prompt for login
183
+ const readline = require('readline');
184
+ const https = require('https');
185
+ const { execSync } = require('child_process');
186
+ const { writeAuthToken } = require('./lib/runtime-session');
187
+
188
+ const BACKEND_URL = process.env.NINJA_BACKEND_URL || 'https://emtchat-backend.onrender.com';
189
+
190
+ function prompt(question) {
191
+ return new Promise((resolve) => {
192
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
193
+ rl.question(question, (answer) => { rl.close(); resolve(answer); });
194
+ });
195
+ }
196
+
197
+ function promptPassword(question) {
198
+ return new Promise((resolve) => {
199
+ try { execSync('stty -echo', { stdio: 'pipe' }); } catch {}
200
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
201
+ process.stdout.write(question);
202
+ rl.question('', (answer) => {
203
+ try { execSync('stty echo', { stdio: 'pipe' }); } catch {}
204
+ console.log();
205
+ rl.close();
206
+ resolve(answer);
207
+ });
208
+ });
209
+ }
210
+
211
+ function postJson(url, body) {
212
+ return new Promise((resolve, reject) => {
213
+ const parsed = new URL(url);
214
+ const payload = JSON.stringify(body);
215
+ const req = https.request({
216
+ hostname: parsed.hostname,
217
+ port: parsed.port || 443,
218
+ path: parsed.pathname,
219
+ method: 'POST',
220
+ headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(payload) },
221
+ }, (res) => {
222
+ let data = '';
223
+ res.on('data', chunk => { data += chunk; });
224
+ res.on('end', () => {
225
+ try { resolve({ status: res.statusCode, body: JSON.parse(data) }); }
226
+ catch { resolve({ status: res.statusCode, body: data }); }
227
+ });
228
+ });
229
+ req.on('error', reject);
230
+ req.write(payload);
231
+ req.end();
232
+ });
233
+ }
234
+
235
+ async function doLogin() {
236
+ console.log('Login to your Ninja Terminals account:\n');
237
+ const username = await prompt('Username or email: ');
238
+ const password = await promptPassword('Password: ');
239
+
240
+ if (!username || !password) {
241
+ console.log('\n⚠️ Skipped login. Run `npx ninja-login` later to authenticate.');
242
+ return false;
243
+ }
244
+
245
+ console.log('Authenticating...');
246
+ try {
247
+ const res = await postJson(`${BACKEND_URL}/api/auth/login`, { username, password });
248
+ if (res.status === 200 && res.body.token) {
249
+ writeAuthToken(res.body.token);
250
+ console.log(`\n✅ Logged in as ${username}`);
251
+ console.log(` Token saved to ~/.ninja/token`);
252
+ return true;
253
+ } else {
254
+ console.log(`\n❌ Login failed: ${res.body.message || res.body.error || 'Unknown error'}`);
255
+ console.log(' Run `npx ninja-login` to try again.');
256
+ return false;
257
+ }
258
+ } catch (err) {
259
+ console.log(`\n❌ Connection failed: ${err.message}`);
260
+ console.log(' Run `npx ninja-login` to try again.');
261
+ return false;
262
+ }
263
+ }
264
+
265
+ await doLogin();
266
+
267
+ console.log(`
268
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
169
269
  ✨ Setup complete!
170
270
 
171
- MCPs configured:
172
- ninja-terminals - orchestrates parallel Claude Code instances
173
- • playwright - browser automation (screenshots, clicks, reading)
174
- • fetch - API calls to /api/terminals
175
-
176
- Next steps:
177
- 1. Restart Claude Code to load MCP servers
178
- 2. Run: npx ninja-terminals
179
- 3. Or use MCP tools directly in Claude Code
180
-
181
- MCP tools available after restart:
182
- mcp__ninja-terminals__spawn_terminal
183
- mcp__ninja-terminals__send_input
184
- mcp__ninja-terminals__list_terminals
185
- ... and 9 more
271
+ Next: Restart Claude Code, then tell Claude:
272
+ "use ninja terminals"
186
273
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
187
274
  `);
188
- process.exit(0);
189
275
  }
190
276
 
277
+ // If setup mode was requested, we're done (setup function calls process.exit)
278
+ if (!hasFlag('--setup')) {
279
+
191
280
  const port = parseInt(getArg('--port', '3300'), 10);
192
- const terminals = parseInt(getArg('--terminals', '2'), 10); // Free tier default
281
+ const terminals = parseInt(getArg('--terminals', '4'), 10); // Full access
193
282
  const cwd = getArg('--cwd', process.cwd());
194
283
  const token = getArg('--token', null);
195
284
  const offline = hasFlag('--offline');
@@ -267,3 +356,5 @@ setTimeout(() => {
267
356
  // ── Start the server ─────────────────────────────────────────
268
357
 
269
358
  require('./server.js');
359
+
360
+ } // end if (!hasFlag('--setup'))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ninja-terminals",
3
- "version": "2.3.2",
3
+ "version": "2.3.4",
4
4
  "description": "MCP server for multi-terminal Claude Code orchestration with DAG task management, parallel execution, and self-improvement",
5
5
  "main": "server.js",
6
6
  "bin": {