@boxcrew/cli 0.1.3 → 0.1.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/dist/index.js +55 -57
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -16,6 +16,22 @@ var config = new Conf({
16
16
  }
17
17
  });
18
18
 
19
+ // src/auth.ts
20
+ function getAuthToken() {
21
+ if (process.env.BOXCREW_API_KEY) return process.env.BOXCREW_API_KEY;
22
+ return config.get("apiKey") ?? null;
23
+ }
24
+ function requireAuth() {
25
+ const token = getAuthToken();
26
+ if (!token) {
27
+ console.error(
28
+ "Not authenticated. Run `bx login` or set the BOXCREW_API_KEY environment variable."
29
+ );
30
+ process.exit(1);
31
+ }
32
+ return token;
33
+ }
34
+
19
35
  // src/commands/login.ts
20
36
  var DEFAULT_FRONTEND_URL = "https://boxcrew.ai";
21
37
  function registerLoginCommand(program2) {
@@ -28,32 +44,38 @@ function registerLoginCommand(program2) {
28
44
  if (options.apiUrl) {
29
45
  config.set("apiUrl", options.apiUrl);
30
46
  }
31
- const authUrl = `${options.frontendUrl}/cli-auth`;
32
- console.log("Opening browser to authenticate...");
33
- console.log(`If the browser doesn't open, visit: ${authUrl}
34
- `);
35
- open(authUrl).catch(() => {
36
- });
37
- const rl = createInterface({
38
- input: process.stdin,
39
- output: process.stdout
40
- });
41
- const apiKey = await new Promise((resolve) => {
42
- rl.question("Paste your API key: ", (answer) => {
43
- rl.close();
44
- resolve(answer.trim());
45
- });
46
- });
47
- if (!apiKey.startsWith("bxk_")) {
48
- console.error('Invalid API key. Keys should start with "bxk_".');
49
- process.exit(1);
50
- }
51
- config.set("apiKey", apiKey);
52
- console.log("\nAuthenticated successfully! Credentials stored.");
53
- console.log(`API URL: ${config.get("apiUrl")}`);
47
+ await ensureLoggedIn(options.frontendUrl);
54
48
  }
55
49
  );
56
50
  }
51
+ async function ensureLoggedIn(frontendUrl = DEFAULT_FRONTEND_URL) {
52
+ if (getAuthToken()) {
53
+ console.log("Already authenticated.");
54
+ return;
55
+ }
56
+ const authUrl = `${frontendUrl}/cli-auth`;
57
+ console.log("Opening browser to authenticate...");
58
+ console.log(`If the browser doesn't open, visit: ${authUrl}
59
+ `);
60
+ open(authUrl).catch(() => {
61
+ });
62
+ const rl = createInterface({
63
+ input: process.stdin,
64
+ output: process.stdout
65
+ });
66
+ const apiKey = await new Promise((resolve) => {
67
+ rl.question("Paste your API key: ", (answer) => {
68
+ rl.close();
69
+ resolve(answer.trim());
70
+ });
71
+ });
72
+ if (!apiKey.startsWith("bxk_")) {
73
+ console.error('Invalid API key. Keys should start with "bxk_".');
74
+ process.exit(1);
75
+ }
76
+ config.set("apiKey", apiKey);
77
+ console.log("Authenticated successfully!\n");
78
+ }
57
79
 
58
80
  // src/commands/logout.ts
59
81
  function registerLogoutCommand(program2) {
@@ -63,22 +85,6 @@ function registerLogoutCommand(program2) {
63
85
  });
64
86
  }
65
87
 
66
- // src/auth.ts
67
- function getAuthToken() {
68
- if (process.env.BOXCREW_API_KEY) return process.env.BOXCREW_API_KEY;
69
- return config.get("apiKey") ?? null;
70
- }
71
- function requireAuth() {
72
- const token = getAuthToken();
73
- if (!token) {
74
- console.error(
75
- "Not authenticated. Run `bx login` or set the BOXCREW_API_KEY environment variable."
76
- );
77
- process.exit(1);
78
- }
79
- return token;
80
- }
81
-
82
88
  // src/client.ts
83
89
  function getBaseUrl() {
84
90
  return process.env.BOXCREW_API_URL || config.get("apiUrl");
@@ -401,16 +407,18 @@ function parseStreamJsonLine(line) {
401
407
  return null;
402
408
  }
403
409
  function registerConnectCommand(program2) {
404
- program2.command("connect <agent-name>").description(
405
- "Connect a local Claude Code instance to a BoxCrew agent.\nRequires authentication \u2014 run `bx login` first."
406
- ).option("--claude-path <path>", "Path to claude CLI binary", "claude").action(async (agentName, options) => {
407
- console.log(`Fetching connection config for agent "${agentName}"...`);
410
+ program2.command("connect <agent-name>").description("Connect a local Claude Code instance to a BoxCrew agent.").option("--claude-path <path>", "Path to claude CLI binary", "claude").option(
411
+ "--frontend-url <url>",
412
+ "BoxCrew frontend URL",
413
+ process.env.BOXCREW_FRONTEND_URL || "https://boxcrew.ai"
414
+ ).action(async (agentName, options) => {
415
+ if (!getAuthToken()) {
416
+ await ensureLoggedIn(options.frontendUrl);
417
+ }
408
418
  const config2 = await apiFetchJson(
409
419
  `/agents/${encodeURIComponent(agentName)}/connection-config`
410
420
  );
411
421
  const wsUrl = config2.websocket_url;
412
- console.log(`Agent: ${config2.agent_name} (${config2.agent_id.slice(0, 8)}...)`);
413
- console.log(`Proxy: ${config2.proxy_base_url}`);
414
422
  const claudePath = options.claudePath;
415
423
  let activeProcess = null;
416
424
  let sendToServer = null;
@@ -422,8 +430,6 @@ function registerConnectCommand(program2) {
422
430
  activeProcess = null;
423
431
  }
424
432
  const { messageId, message, sessionId } = msg;
425
- console.log(`
426
- Chat ${messageId.slice(0, 8)}: ${message.slice(0, 120)}${message.length > 120 ? "..." : ""}`);
427
433
  const args = ["-p", message, "--output-format", "stream-json", "--verbose"];
428
434
  if (sessionId) args.push("--resume", sessionId);
429
435
  const childEnv = { ...process.env };
@@ -440,12 +446,6 @@ Chat ${messageId.slice(0, 8)}: ${message.slice(0, 120)}${message.length > 120 ?
440
446
  sendToServer({ type: "event", messageId, event });
441
447
  }
442
448
  });
443
- if (child.stderr) {
444
- const stderrRl = createInterface2({ input: child.stderr });
445
- stderrRl.on("line", (line) => {
446
- if (line.trim()) console.error(` [claude] ${line}`);
447
- });
448
- }
449
449
  child.on("exit", (code) => {
450
450
  if (activeProcess === child) activeProcess = null;
451
451
  if (sendToServer) {
@@ -462,7 +462,6 @@ Chat ${messageId.slice(0, 8)}: ${message.slice(0, 120)}${message.length > 120 ?
462
462
  });
463
463
  };
464
464
  const connect = () => {
465
- console.log("Connecting to BoxCrew...");
466
465
  const ws = new WebSocket(wsUrl);
467
466
  const send = (msg) => {
468
467
  if (ws.readyState === WebSocket.OPEN) {
@@ -472,7 +471,7 @@ Chat ${messageId.slice(0, 8)}: ${message.slice(0, 120)}${message.length > 120 ?
472
471
  ws.on("open", () => {
473
472
  reconnectAttempt = 0;
474
473
  sendToServer = send;
475
- console.log("Connected. Waiting for messages...");
474
+ console.log(`Agent "${config2.agent_name}" is online. Press Ctrl+C to disconnect.`);
476
475
  });
477
476
  ws.on("message", (data) => {
478
477
  let msg;
@@ -486,7 +485,6 @@ Chat ${messageId.slice(0, 8)}: ${message.slice(0, 120)}${message.length > 120 ?
486
485
  return;
487
486
  }
488
487
  if (msg.type === "stop" && activeProcess) {
489
- console.log(`Stopping chat ${msg.messageId.slice(0, 8)}...`);
490
488
  activeProcess.kill("SIGINT");
491
489
  return;
492
490
  }
@@ -511,7 +509,7 @@ Chat ${messageId.slice(0, 8)}: ${message.slice(0, 120)}${message.length > 120 ?
511
509
  }
512
510
  });
513
511
  ws.on("error", (err) => {
514
- console.error("WebSocket error:", err.message);
512
+ console.error("Connection error:", err.message);
515
513
  });
516
514
  const shutdown = () => {
517
515
  shouldReconnect = false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@boxcrew/cli",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "BoxCrew CLI — manage your agents from the terminal",
5
5
  "type": "module",
6
6
  "bin": {