blun-king-cli 1.1.0 → 1.3.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.
Files changed (2) hide show
  1. package/bin/blun.js +349 -34
  2. package/package.json +1 -1
package/bin/blun.js CHANGED
@@ -47,10 +47,16 @@ var config = loadConfig();
47
47
 
48
48
  // ── Colors ──
49
49
  const C = {
50
- reset: "\x1b[0m", bold: "\x1b[1m", dim: "\x1b[2m",
50
+ reset: "\x1b[0m", bold: "\x1b[1m", dim: "\x1b[2m", italic: "\x1b[3m",
51
51
  red: "\x1b[31m", green: "\x1b[32m", yellow: "\x1b[33m",
52
52
  blue: "\x1b[34m", magenta: "\x1b[35m", cyan: "\x1b[36m", white: "\x1b[37m",
53
- bg_blue: "\x1b[44m", bg_green: "\x1b[42m"
53
+ gray: "\x1b[90m", brightBlue: "\x1b[94m", brightCyan: "\x1b[96m", brightWhite: "\x1b[97m",
54
+ bg_blue: "\x1b[44m", bg_green: "\x1b[42m", bg_gray: "\x1b[100m", bg_darkBlue: "\x1b[48;5;17m"
55
+ };
56
+ // Box drawing helpers
57
+ const BOX = {
58
+ tl: "╭", tr: "╮", bl: "╰", br: "╯", h: "─", v: "│",
59
+ sep: "├", sepR: "┤", dot: "●", arrow: "❯", chat: "💬", bot: "🤖", user: "👤"
54
60
  };
55
61
 
56
62
  function log(msg) { if (config.verbose) fs.appendFileSync(LOG_FILE, new Date().toISOString() + " " + msg + "\n"); }
@@ -98,51 +104,81 @@ var chatHistory = [];
98
104
 
99
105
  // ── Print Helpers ──
100
106
  function printHeader() {
107
+ var w = Math.min(process.stdout.columns || 60, 60);
108
+ var line = BOX.h.repeat(w - 4);
101
109
  console.log("");
102
- console.log(C.bold + C.blue + " ╔══════════════════════════════════════╗" + C.reset);
103
- console.log(C.bold + C.blue + " BLUN KING CLI v1.0 ║" + C.reset);
104
- console.log(C.bold + C.blue + " Premium KI — Local First" + C.reset);
105
- console.log(C.bold + C.blue + " ╚══════════════════════════════════════╝" + C.reset);
106
- console.log("");
107
- console.log(C.dim + " API: " + config.api.base_url + C.reset);
108
- console.log(C.dim + " Auth: " + config.auth.type + (config.auth.api_key ? " (key set)" : " (no key)") + C.reset);
109
- console.log(C.dim + " Model: " + config.model + C.reset);
110
- console.log(C.dim + " Workdir: " + config.workdir + C.reset);
110
+ console.log(C.brightBlue + " " + BOX.tl + line + BOX.tr + C.reset);
111
+ console.log(C.brightBlue + " " + BOX.v + C.reset + C.bold + C.brightWhite + " " + BOX.bot + " BLUN KING CLI" + C.reset + C.dim + " v1.1" + C.reset + " ".repeat(Math.max(0, w - 24)) + C.brightBlue + BOX.v + C.reset);
112
+ console.log(C.brightBlue + " " + BOX.v + C.reset + C.gray + " Premium KI — Local First — Autonom" + C.reset + " ".repeat(Math.max(0, w - 41)) + C.brightBlue + BOX.v + C.reset);
113
+ console.log(C.brightBlue + " " + BOX.v + line + BOX.v + C.reset);
114
+ console.log(C.brightBlue + " " + BOX.v + C.reset + C.gray + " API " + C.brightCyan + config.api.base_url + C.reset + " ".repeat(Math.max(0, w - 14 - config.api.base_url.length)) + C.brightBlue + BOX.v + C.reset);
115
+ console.log(C.brightBlue + " " + BOX.v + C.reset + C.gray + " Model " + C.brightCyan + config.model + C.reset + " ".repeat(Math.max(0, w - 14 - config.model.length)) + C.brightBlue + BOX.v + C.reset);
116
+ var wdShort = config.workdir.length > w - 16 ? "..." + config.workdir.slice(-(w - 19)) : config.workdir;
117
+ console.log(C.brightBlue + " " + BOX.v + C.reset + C.gray + " Dir " + C.brightCyan + wdShort + C.reset + " ".repeat(Math.max(0, w - 14 - wdShort.length)) + C.brightBlue + BOX.v + C.reset);
118
+ console.log(C.brightBlue + " " + BOX.bl + line + BOX.br + C.reset);
111
119
  console.log("");
112
- console.log(C.dim + " Type /help for commands, or just chat." + C.reset);
120
+ console.log(C.gray + " /help " + C.dim + "for commands " + C.gray + BOX.dot + " just type to chat" + C.reset);
113
121
  console.log("");
114
122
  }
115
123
 
116
- function printAnswer(answer) {
124
+ // ── Update Checker ──
125
+ function checkForUpdates() {
126
+ try {
127
+ var currentVersion = "1.3.0";
128
+ var latest = execSync("npm view blun-king-cli version 2>/dev/null", { encoding: "utf8", timeout: 5000 }).trim();
129
+ if (latest && latest !== currentVersion) {
130
+ console.log(C.yellow + C.bold + " " + BOX.arrow + " Update available: " + currentVersion + " → " + latest + C.reset);
131
+ console.log(C.yellow + " npm update -g blun-king-cli" + C.reset);
132
+ console.log("");
133
+ }
134
+ } catch(e) { /* silent */ }
135
+ }
136
+
137
+ function printAnswer(answer, meta) {
117
138
  console.log("");
118
- console.log(C.green + C.bold + "BLUN King:" + C.reset);
119
- // Simple markdown rendering
139
+ console.log(C.green + C.bold + " " + BOX.bot + " BLUN King" + C.reset + (meta ? C.gray + " " + BOX.dot + " " + meta + C.reset : ""));
140
+ console.log(C.green + " " + BOX.h.repeat(40) + C.reset);
141
+ // Markdown rendering
120
142
  var lines = answer.split("\n");
121
143
  var inCode = false;
122
144
  for (var i = 0; i < lines.length; i++) {
123
145
  var line = lines[i];
124
146
  if (line.startsWith("```")) {
125
147
  inCode = !inCode;
126
- console.log(C.dim + line + C.reset);
148
+ if (inCode) {
149
+ var lang = line.slice(3).trim();
150
+ console.log(C.dim + " " + BOX.tl + BOX.h.repeat(38) + (lang ? " " + lang + " " : "") + C.reset);
151
+ } else {
152
+ console.log(C.dim + " " + BOX.bl + BOX.h.repeat(38) + C.reset);
153
+ }
127
154
  } else if (inCode) {
128
- console.log(C.cyan + line + C.reset);
155
+ console.log(C.cyan + " " + BOX.v + " " + line + C.reset);
129
156
  } else if (line.startsWith("# ")) {
130
- console.log(C.bold + C.yellow + line + C.reset);
157
+ console.log(C.bold + C.yellow + " " + line + C.reset);
131
158
  } else if (line.startsWith("## ")) {
132
- console.log(C.bold + C.magenta + line + C.reset);
159
+ console.log(C.bold + C.magenta + " " + line + C.reset);
133
160
  } else if (line.startsWith("### ")) {
134
- console.log(C.bold + line + C.reset);
161
+ console.log(C.bold + " " + line + C.reset);
135
162
  } else if (line.startsWith("- ") || line.startsWith("* ")) {
136
- console.log(C.white + " " + line + C.reset);
163
+ console.log(C.white + " " + line + C.reset);
137
164
  } else if (line.match(/^\d+\./)) {
138
- console.log(C.white + " " + line + C.reset);
165
+ console.log(C.white + " " + line + C.reset);
166
+ } else if (line.startsWith("**") && line.endsWith("**")) {
167
+ console.log(C.bold + C.brightWhite + " " + line + C.reset);
139
168
  } else {
140
- console.log(line);
169
+ console.log(" " + line);
141
170
  }
142
171
  }
143
172
  console.log("");
144
173
  }
145
174
 
175
+ function printUserMessage(msg) {
176
+ console.log("");
177
+ console.log(C.brightBlue + C.bold + " " + BOX.user + " Du" + C.reset);
178
+ console.log(C.brightBlue + " " + BOX.h.repeat(40) + C.reset);
179
+ console.log(C.brightWhite + " " + msg + C.reset);
180
+ }
181
+
146
182
  function printError(msg) { console.log(C.red + "ERROR: " + msg + C.reset); }
147
183
  function printInfo(msg) { console.log(C.cyan + msg + C.reset); }
148
184
  function printSuccess(msg) { console.log(C.green + "✓ " + msg + C.reset); }
@@ -176,6 +212,16 @@ async function handleCommand(input) {
176
212
  console.log(" /score <text> Score a response");
177
213
  console.log(" /eval Run eval suite");
178
214
  console.log("");
215
+ console.log(C.yellow + " PLUGINS (MCP)" + C.reset);
216
+ console.log(" /plugin list List installed plugins");
217
+ console.log(" /plugin add <cmd> Add MCP server (npm pkg or local path)");
218
+ console.log(" /plugin remove <n>Remove a plugin");
219
+ console.log(" /plugin run <n> Start a plugin server");
220
+ console.log(" /plugin stop <n> Stop a plugin server");
221
+ console.log(" /permissions Show permission settings");
222
+ console.log(" /permissions allow-all Allow all tool calls");
223
+ console.log(" /permissions ask Ask before each tool call");
224
+ console.log("");
179
225
  console.log(C.yellow + " SETTINGS" + C.reset);
180
226
  console.log(" /settings Show all settings");
181
227
  console.log(" /set auth api Switch to API key auth");
@@ -310,6 +356,26 @@ async function handleCommand(input) {
310
356
  cmdInit();
311
357
  break;
312
358
 
359
+ case "/plugin":
360
+ cmdPlugin(args);
361
+ break;
362
+
363
+ case "/permissions":
364
+ cmdPermissions(args);
365
+ break;
366
+
367
+ case "/agent":
368
+ await cmdAgent(args);
369
+ break;
370
+
371
+ case "/screenshot":
372
+ await cmdScreenshot(args);
373
+ break;
374
+
375
+ case "/render":
376
+ await cmdRender(args);
377
+ break;
378
+
313
379
  case "/exit":
314
380
  case "/quit":
315
381
  case "/q":
@@ -324,12 +390,22 @@ async function handleCommand(input) {
324
390
  // ── Chat ──
325
391
  async function sendChat(message) {
326
392
  try {
327
- process.stdout.write(C.dim + "⏳ thinking..." + C.reset);
393
+ printUserMessage(message);
394
+ // Animated thinking
395
+ var dots = 0;
396
+ var thinkFrames = ["thinking", "thinking.", "thinking..", "thinking..."];
397
+ var thinkTimer = setInterval(function() {
398
+ process.stdout.write("\r" + C.dim + " " + BOX.bot + " " + thinkFrames[dots % 4] + " " + C.reset);
399
+ dots++;
400
+ }, 300);
401
+
328
402
  var resp = await apiCall("POST", "/chat", {
329
403
  message: message,
330
404
  history: chatHistory.slice(-10)
331
405
  });
332
- process.stdout.write("\r" + " ".repeat(30) + "\r");
406
+
407
+ clearInterval(thinkTimer);
408
+ process.stdout.write("\r" + " ".repeat(40) + "\r");
333
409
 
334
410
  if (resp.status !== 200) {
335
411
  printError(resp.data.error || "API Error " + resp.status);
@@ -339,17 +415,14 @@ async function sendChat(message) {
339
415
  chatHistory.push({ role: "user", content: message });
340
416
  chatHistory.push({ role: "assistant", content: resp.data.answer });
341
417
 
342
- printAnswer(resp.data.answer);
343
-
344
- // Status line
345
418
  var q = resp.data.quality || {};
346
- console.log(C.dim + " [" + resp.data.task_type + "/" + resp.data.role + " | score: " + (q.score || "?") +
347
- (q.retried ? " | retried" : "") +
348
- (q.flags && q.flags.length > 0 ? " | flags: " + q.flags.join(", ") : "") + "]" + C.reset);
349
- console.log("");
419
+ var meta = resp.data.task_type + "/" + resp.data.role + " " + BOX.dot + " score: " + (q.score || "?") +
420
+ (q.retried ? " " + BOX.dot + " retried" : "");
421
+ printAnswer(resp.data.answer, meta);
350
422
 
351
423
  } catch(e) {
352
- process.stdout.write("\r" + " ".repeat(30) + "\r");
424
+ if (typeof thinkTimer !== "undefined") clearInterval(thinkTimer);
425
+ process.stdout.write("\r" + " ".repeat(40) + "\r");
353
426
  printError("Connection failed: " + e.message);
354
427
  }
355
428
  }
@@ -1042,6 +1115,232 @@ function cmdInit(args) {
1042
1115
  }
1043
1116
  }
1044
1117
 
1118
+ // ── Plugins (MCP-style) ──
1119
+ const PLUGINS_FILE = path.join(CONFIG_DIR, "plugins.json");
1120
+ const PERMISSIONS_FILE = path.join(CONFIG_DIR, "permissions.json");
1121
+
1122
+ function loadPlugins() {
1123
+ if (fs.existsSync(PLUGINS_FILE)) {
1124
+ try { return JSON.parse(fs.readFileSync(PLUGINS_FILE, "utf8")); } catch(e) {}
1125
+ }
1126
+ return {};
1127
+ }
1128
+
1129
+ function savePlugins(p) { fs.writeFileSync(PLUGINS_FILE, JSON.stringify(p, null, 2)); }
1130
+
1131
+ function loadPermissions() {
1132
+ if (fs.existsSync(PERMISSIONS_FILE)) {
1133
+ try { return JSON.parse(fs.readFileSync(PERMISSIONS_FILE, "utf8")); } catch(e) {}
1134
+ }
1135
+ return { mode: "ask", allowed: [], denied: [] };
1136
+ }
1137
+
1138
+ function savePermissions(p) { fs.writeFileSync(PERMISSIONS_FILE, JSON.stringify(p, null, 2)); }
1139
+
1140
+ // Built-in plugin templates
1141
+ var PLUGIN_TEMPLATES = {
1142
+ telegram: {
1143
+ name: "telegram",
1144
+ description: "Telegram Bot Bridge — send/receive messages",
1145
+ type: "builtin",
1146
+ config: { bot_token: "", chat_id: "" },
1147
+ commands: ["/tg send <msg>", "/tg status"],
1148
+ setup: ["bot_token", "chat_id"]
1149
+ },
1150
+ github: {
1151
+ name: "github",
1152
+ description: "GitHub Integration — repos, issues, PRs",
1153
+ type: "builtin",
1154
+ config: { token: "", default_repo: "" },
1155
+ commands: ["/gh repos", "/gh issues", "/gh pr"],
1156
+ setup: ["token"]
1157
+ },
1158
+ browser: {
1159
+ name: "browser",
1160
+ description: "Playwright Browser — screenshots, rendering, scraping",
1161
+ type: "builtin",
1162
+ config: {},
1163
+ commands: ["/screenshot <url>", "/render <url>"],
1164
+ setup: []
1165
+ },
1166
+ slack: {
1167
+ name: "slack",
1168
+ description: "Slack Webhook — send messages to channels",
1169
+ type: "builtin",
1170
+ config: { webhook_url: "" },
1171
+ commands: ["/slack send <msg>"],
1172
+ setup: ["webhook_url"]
1173
+ },
1174
+ docker: {
1175
+ name: "docker",
1176
+ description: "Docker Management — containers, images, logs",
1177
+ type: "builtin",
1178
+ config: { host: "localhost" },
1179
+ commands: ["/docker ps", "/docker logs <container>"],
1180
+ setup: []
1181
+ }
1182
+ };
1183
+
1184
+ function cmdPlugin(args) {
1185
+ var plugins = loadPlugins();
1186
+ var parts = (args || "").split(/\s+/);
1187
+ var action = parts[0] || "list";
1188
+
1189
+ if (action === "list") {
1190
+ console.log("");
1191
+ console.log(C.bold + " " + BOX.bot + " Installed Plugins:" + C.reset);
1192
+ console.log(C.brightBlue + " " + BOX.h.repeat(40) + C.reset);
1193
+ var names = Object.keys(plugins);
1194
+ if (names.length === 0) {
1195
+ console.log(C.gray + " (none installed)" + C.reset);
1196
+ } else {
1197
+ names.forEach(function(name) {
1198
+ var p = plugins[name];
1199
+ var status = p.running ? C.green + BOX.dot + " running" : C.gray + BOX.dot + " stopped";
1200
+ console.log(" " + C.brightCyan + name + C.reset + " — " + (p.description || "") + " " + status + C.reset);
1201
+ });
1202
+ }
1203
+ console.log("");
1204
+ console.log(C.gray + " Available: " + Object.keys(PLUGIN_TEMPLATES).join(", ") + C.reset);
1205
+ console.log(C.gray + " Or add custom: /plugin add <npm-package> or /plugin add <path>" + C.reset);
1206
+ console.log("");
1207
+
1208
+ } else if (action === "add" && parts[1]) {
1209
+ var pluginName = parts[1];
1210
+ if (PLUGIN_TEMPLATES[pluginName]) {
1211
+ // Built-in plugin
1212
+ var tmpl = PLUGIN_TEMPLATES[pluginName];
1213
+ plugins[pluginName] = {
1214
+ name: tmpl.name,
1215
+ description: tmpl.description,
1216
+ type: tmpl.type,
1217
+ config: Object.assign({}, tmpl.config),
1218
+ commands: tmpl.commands,
1219
+ installed: new Date().toISOString(),
1220
+ running: false
1221
+ };
1222
+
1223
+ // If setup fields needed, prompt
1224
+ if (tmpl.setup && tmpl.setup.length > 0) {
1225
+ printInfo("Plugin '" + pluginName + "' needs configuration:");
1226
+ tmpl.setup.forEach(function(field) {
1227
+ printInfo(" Set with: /set plugin." + pluginName + "." + field + " <value>");
1228
+ });
1229
+ }
1230
+
1231
+ savePlugins(plugins);
1232
+ printSuccess("Plugin '" + pluginName + "' installed!");
1233
+ } else {
1234
+ // Custom: npm package or local path
1235
+ printInfo("Installing custom plugin: " + pluginName);
1236
+ try {
1237
+ execSync("npm install " + pluginName, { cwd: CONFIG_DIR, encoding: "utf8", stdio: "pipe" });
1238
+ plugins[pluginName] = {
1239
+ name: pluginName,
1240
+ description: "Custom MCP server",
1241
+ type: "npm",
1242
+ config: {},
1243
+ commands: [],
1244
+ installed: new Date().toISOString(),
1245
+ running: false
1246
+ };
1247
+ savePlugins(plugins);
1248
+ printSuccess("Plugin '" + pluginName + "' installed via npm!");
1249
+ } catch(e) {
1250
+ printError("Install failed: " + e.message.slice(0, 200));
1251
+ }
1252
+ }
1253
+
1254
+ } else if (action === "remove" && parts[1]) {
1255
+ delete plugins[parts[1]];
1256
+ savePlugins(plugins);
1257
+ printSuccess("Plugin '" + parts[1] + "' removed.");
1258
+
1259
+ } else if (action === "run" && parts[1]) {
1260
+ if (!plugins[parts[1]]) { printError("Plugin not found: " + parts[1]); return; }
1261
+ plugins[parts[1]].running = true;
1262
+ savePlugins(plugins);
1263
+ printSuccess("Plugin '" + parts[1] + "' started.");
1264
+
1265
+ } else if (action === "stop" && parts[1]) {
1266
+ if (!plugins[parts[1]]) { printError("Plugin not found: " + parts[1]); return; }
1267
+ plugins[parts[1]].running = false;
1268
+ savePlugins(plugins);
1269
+ printSuccess("Plugin '" + parts[1] + "' stopped.");
1270
+
1271
+ } else {
1272
+ printError("Usage: /plugin list|add|remove|run|stop <name>");
1273
+ }
1274
+ }
1275
+
1276
+ function cmdPermissions(args) {
1277
+ var perms = loadPermissions();
1278
+ if (!args) {
1279
+ console.log("");
1280
+ console.log(C.bold + " Permissions:" + C.reset);
1281
+ console.log(" Mode: " + C.brightCyan + perms.mode + C.reset);
1282
+ console.log(" Allowed: " + (perms.allowed.length > 0 ? perms.allowed.join(", ") : C.gray + "(none)" + C.reset));
1283
+ console.log(" Denied: " + (perms.denied.length > 0 ? perms.denied.join(", ") : C.gray + "(none)" + C.reset));
1284
+ console.log("");
1285
+ console.log(C.gray + " /permissions allow-all — Skip all permission prompts" + C.reset);
1286
+ console.log(C.gray + " /permissions ask — Ask before each tool call" + C.reset);
1287
+ console.log("");
1288
+ } else if (args === "allow-all") {
1289
+ perms.mode = "allow-all";
1290
+ savePermissions(perms);
1291
+ printSuccess("Permission mode: allow-all (no prompts)");
1292
+ } else if (args === "ask") {
1293
+ perms.mode = "ask";
1294
+ savePermissions(perms);
1295
+ printSuccess("Permission mode: ask (prompt before each tool call)");
1296
+ }
1297
+ }
1298
+
1299
+ // ── Agent Loop (CLI wrapper) ──
1300
+ async function cmdAgent(args) {
1301
+ if (!args) { printError("Usage: /agent <goal>"); return; }
1302
+ try {
1303
+ printUserMessage(args);
1304
+ process.stdout.write(C.dim + " " + BOX.bot + " working autonomously..." + C.reset);
1305
+ var resp = await apiCall("POST", "/agent", { goal: args, verbose: true });
1306
+ process.stdout.write("\r" + " ".repeat(50) + "\r");
1307
+ if (resp.status !== 200) { printError(resp.data.error || "Error"); return; }
1308
+ var d = resp.data;
1309
+ var meta = d.steps_executed + " steps" + (d.files.length > 0 ? " " + BOX.dot + " " + d.files.length + " files" : "");
1310
+ printAnswer(d.answer, meta);
1311
+ if (d.files.length > 0) {
1312
+ console.log(C.green + " Files:" + C.reset);
1313
+ d.files.forEach(function(f) { console.log(" " + C.brightCyan + f.name + C.reset + " → " + config.api.base_url + f.download); });
1314
+ console.log("");
1315
+ }
1316
+ } catch(e) { printError(e.message); }
1317
+ }
1318
+
1319
+ // ── Screenshot/Render (CLI wrapper) ──
1320
+ async function cmdScreenshot(args) {
1321
+ if (!args) { printError("Usage: /screenshot <url>"); return; }
1322
+ try {
1323
+ printInfo("Taking screenshot of " + args + "...");
1324
+ var resp = await apiCall("POST", "/screenshot", { url: args });
1325
+ if (resp.status !== 200) { printError(resp.data.error || "Error"); return; }
1326
+ printSuccess("Screenshot: " + resp.data.title);
1327
+ console.log(" Download: " + C.brightCyan + config.api.base_url + resp.data.screenshot + C.reset);
1328
+ console.log("");
1329
+ } catch(e) { printError(e.message); }
1330
+ }
1331
+
1332
+ async function cmdRender(args) {
1333
+ if (!args) { printError("Usage: /render <url>"); return; }
1334
+ try {
1335
+ printInfo("Rendering " + args + " with Playwright...");
1336
+ var resp = await apiCall("POST", "/render", { url: args });
1337
+ if (resp.status !== 200) { printError(resp.data.error || "Error"); return; }
1338
+ printSuccess("Rendered: " + resp.data.title + " (" + resp.data.html_length + " chars)");
1339
+ if (resp.data.screenshot) console.log(" Screenshot: " + C.brightCyan + resp.data.screenshot + C.reset);
1340
+ console.log("");
1341
+ } catch(e) { printError(e.message); }
1342
+ }
1343
+
1045
1344
  // ── Main Loop ──
1046
1345
  async function main() {
1047
1346
  // Handle CLI args
@@ -1081,6 +1380,7 @@ async function main() {
1081
1380
 
1082
1381
  // Interactive mode
1083
1382
  printHeader();
1383
+ checkForUpdates();
1084
1384
 
1085
1385
  // Health check
1086
1386
  try {
@@ -1092,10 +1392,25 @@ async function main() {
1092
1392
  printInfo("Run: blun setup — to configure");
1093
1393
  }
1094
1394
 
1395
+ var ALL_COMMANDS = [
1396
+ "/help", "/clear", "/skills", "/skill", "/search", "/learn", "/learn-url",
1397
+ "/generate", "/analyze", "/score", "/eval", "/settings", "/set",
1398
+ "/status", "/versions", "/health", "/watchdog", "/memory", "/files",
1399
+ "/sh", "/git", "/ssh", "/deploy", "/read", "/write", "/init",
1400
+ "/screenshot", "/render", "/agent", "/plugin", "/permissions", "/exit"
1401
+ ];
1402
+
1095
1403
  var rl = readline.createInterface({
1096
1404
  input: process.stdin,
1097
1405
  output: process.stdout,
1098
- prompt: C.blue + C.bold + "blun > " + C.reset
1406
+ prompt: "\n" + C.brightBlue + C.bold + " " + BOX.arrow + " " + C.reset,
1407
+ completer: function(line) {
1408
+ if (line.startsWith("/")) {
1409
+ var hits = ALL_COMMANDS.filter(function(c) { return c.startsWith(line); });
1410
+ return [hits.length ? hits : ALL_COMMANDS, line];
1411
+ }
1412
+ return [[], line];
1413
+ }
1099
1414
  });
1100
1415
 
1101
1416
  rl.prompt();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blun-king-cli",
3
- "version": "1.1.0",
3
+ "version": "1.3.0",
4
4
  "description": "BLUN King CLI — Premium KI Console",
5
5
  "bin": {
6
6
  "blun": "./bin/blun.js"