@bike4mind/cli 0.6.0 → 0.6.1

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 CHANGED
@@ -384,18 +384,111 @@ tail -f ~/.bike4mind/debug/[session-id].txt
384
384
 
385
385
  ## Development
386
386
 
387
+ This section covers the contributor workflow for hacking on the CLI from a checkout of the monorepo. For end-user installation see [Installation](#installation) above.
388
+
389
+ ### How the bin resolves source vs. built code
390
+
391
+ `apps/cli/bin/bike4mind-cli.mjs` auto-detects which mode to run in:
392
+
393
+ - If `apps/cli/dist/index.mjs` exists → runs the bundled production build
394
+ - Otherwise → falls back to `tsx` and imports `src/index.tsx` directly
395
+
396
+ This means **you do not need to rebuild the CLI itself between source edits** — `tsx` reads `src/` live on every invocation. The rebuild burden is only on the workspace packages that the CLI imports (see below).
397
+
398
+ ### Quick start
399
+
400
+ From the repo root:
401
+
387
402
  ```bash
388
- # Run in development mode
403
+ # 1. Install all workspace dependencies
404
+ pnpm install
405
+
406
+ # 2. Build the @bike4mind/* core packages so the CLI can import their dist/ outputs
407
+ pnpm turbo:core:build
408
+
409
+ # 3. Make the `b4m` and `bike4mind` commands point at this checkout
389
410
  cd apps/cli
390
- pnpm dev
411
+ pnpm link --global
412
+
413
+ # 4. Verify
414
+ which b4m
415
+ b4m --version
416
+ ```
417
+
418
+ After step 3, running `b4m` anywhere on your system executes this working tree. Re-run `pnpm link --global` if you move or rename the repo.
419
+
420
+ ### Editing CLI source (`apps/cli/src/`)
421
+
422
+ Just run `b4m`. The bin's `tsx` fallback picks up your edits on the next invocation — no build step needed.
423
+
424
+ If you want to test the bundled production path (the same code an end user would run after `npm install -g @bike4mind/cli`):
425
+
426
+ ```bash
427
+ pnpm --filter @bike4mind/cli build
428
+ b4m # now uses dist/index.mjs
429
+ ```
430
+
431
+ To drop back into source mode, delete `dist/`:
432
+
433
+ ```bash
434
+ rm -rf apps/cli/dist
435
+ ```
391
436
 
392
- # Build for production
393
- pnpm build
437
+ ### Editing workspace dependencies (`b4m-core/*`)
394
438
 
395
- # Type check
439
+ The CLI imports `@bike4mind/agents`, `@bike4mind/services`, `@bike4mind/utils`, `@bike4mind/mcp`, and `@bike4mind/common` via pnpm symlinks that resolve to each package's `dist/` (per its `exports` field). Source edits in those packages require a rebuild before `b4m` will see them.
440
+
441
+ Rebuild only the package you touched:
442
+
443
+ ```bash
444
+ pnpm --filter @bike4mind/agents build
445
+ ```
446
+
447
+ Or rebuild the whole core graph (cached, near-instant if only one package changed):
448
+
449
+ ```bash
450
+ pnpm turbo:core:build
451
+ ```
452
+
453
+ The next `b4m` invocation picks up the change. The CLI itself does not need to be rebuilt.
454
+
455
+ ### Watch mode (optional)
456
+
457
+ Each core package exposes `"dev": "tsdown --watch"`. In a separate terminal:
458
+
459
+ ```bash
460
+ pnpm --filter @bike4mind/agents dev
461
+ ```
462
+
463
+ `dist/` rebuilds on save, so the next `b4m` invocation sees changes without a manual `build`.
464
+
465
+ Caveats:
466
+ - This does **not** hot-reload an already-running interactive `b4m` session — you still exit and re-run.
467
+ - Running multiple watchers in parallel (one per package you're touching) hasn't been load-tested in this repo. If watch seems to miss changes or feels unreliable, fall back to manual `pnpm --filter <pkg> build`.
468
+
469
+ ### Verification commands
470
+
471
+ ```bash
472
+ # Inside apps/cli
396
473
  pnpm typecheck
474
+ pnpm test
475
+ pnpm test:watch
476
+
477
+ # From repo root (cached, recommended)
478
+ pnpm turbo:typecheck
479
+ pnpm turbo:test
480
+
481
+ # Run with debug logs
482
+ b4m --verbose
397
483
  ```
398
484
 
485
+ ### Common pitfalls
486
+
487
+ - **Don't `pnpm --filter @bike4mind/cli build` after every CLI source edit.** It's wasted work — the `tsx` fallback already runs your source live.
488
+ - **Don't use `npm link`.** This repo is pnpm-only; mixing tools breaks symlink resolution.
489
+ - **A stale `apps/cli/dist/` will mask your source changes.** If `b4m` is showing old behavior, check whether `dist/index.mjs` exists — the bin will prefer it over `src/`. Delete `dist/` to drop back to source mode.
490
+ - **First-run native module errors** (`better-sqlite3`, `sharp`): see [Build Requirements](#build-requirements) above. The postinstall hook handles most cases automatically.
491
+
399
492
  ## Architecture
400
493
 
401
494
  ```
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { i as version, n as fetchLatestVersion, r as forceCheckForUpdate } from "../updateChecker-DZXWZfKF.mjs";
2
+ import { a as version, n as compareSemver, r as fetchLatestVersion } from "../updateChecker-D-xoVcN3.mjs";
3
3
  import { execSync } from "child_process";
4
4
  import { constants, existsSync, promises } from "fs";
5
5
  import { homedir } from "os";
@@ -25,29 +25,29 @@ async function handleDoctorCommand() {
25
25
  status: "fail",
26
26
  message: `${nodeVersion} (>= 18 required, please upgrade)`
27
27
  });
28
+ const currentVersion = version;
28
29
  const latestVersion = await fetchLatestVersion();
29
- if (latestVersion) results.push({
30
- name: "NPM registry",
31
- status: "pass",
32
- message: `Accessible (latest: v${latestVersion})`
33
- });
34
- else results.push({
30
+ if (latestVersion) {
31
+ results.push({
32
+ name: "NPM registry",
33
+ status: "pass",
34
+ message: `Accessible (latest: v${latestVersion})`
35
+ });
36
+ if (compareSemver(latestVersion, currentVersion) > 0) results.push({
37
+ name: "Version",
38
+ status: "warn",
39
+ message: `v${currentVersion} installed, v${latestVersion} available. Run: b4m update`
40
+ });
41
+ else results.push({
42
+ name: "Version",
43
+ status: "pass",
44
+ message: `v${currentVersion} (latest)`
45
+ });
46
+ } else results.push({
35
47
  name: "NPM registry",
36
48
  status: "fail",
37
49
  message: "Not accessible — check your internet connection"
38
50
  });
39
- const currentVersion = version;
40
- const updateResult = await forceCheckForUpdate(currentVersion);
41
- if (updateResult) if (updateResult.updateAvailable) results.push({
42
- name: "Version",
43
- status: "warn",
44
- message: `v${currentVersion} installed, v${updateResult.latestVersion} available. Run: b4m update`
45
- });
46
- else results.push({
47
- name: "Version",
48
- status: "pass",
49
- message: `v${currentVersion} (latest)`
50
- });
51
51
  try {
52
52
  const npmPrefix = execSync("npm config get prefix", {
53
53
  encoding: "utf-8",
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { A as getApiUrl, C as WebSocketLlmBackend, G as isReadOnlyTool, J as CheckpointStore, K as ReActAgent, M as PermissionManager, N as generateCliTools, S as FallbackLlmBackend, T as McpManager, U as buildCoreSystemPrompt, V as setWebSocketToolExecutor, X as SessionStore, _ as createSkillTool, b as WebSocketToolExecutor, c as createFindDefinitionTool, d as createCoordinateTaskTool, f as createBackgroundAgentTools, g as SubagentOrchestrator, h as AgentStore, k as loadContextFiles, l as createTodoStore, m as createAgentDelegateTool, p as BackgroundAgentManager, q as CustomCommandStore, s as createGetFileStructureTool, u as createWriteTodosTool, w as ServerLlmBackend, x as WebSocketConnectionManager, y as ApiClient } from "../tools-dIVxi-6-.mjs";
2
+ import { A as getApiUrl, C as WebSocketLlmBackend, G as isReadOnlyTool, J as CheckpointStore, K as ReActAgent, M as PermissionManager, N as generateCliTools, S as FallbackLlmBackend, T as McpManager, U as buildCoreSystemPrompt, V as setWebSocketToolExecutor, X as SessionStore, _ as createSkillTool, b as WebSocketToolExecutor, c as createFindDefinitionTool, d as createCoordinateTaskTool, f as createBackgroundAgentTools, g as SubagentOrchestrator, h as AgentStore, k as loadContextFiles, l as createTodoStore, m as createAgentDelegateTool, p as BackgroundAgentManager, q as CustomCommandStore, s as createGetFileStructureTool, u as createWriteTodosTool, w as ServerLlmBackend, x as WebSocketConnectionManager, y as ApiClient } from "../tools-BUs_OkJc.mjs";
3
3
  import { n as logger, t as ConfigStore } from "../ConfigStore-Dt6utdSA.mjs";
4
4
  import { t as DEFAULT_SANDBOX_CONFIG } from "../types-DBEjF9YS.mjs";
5
5
  import { t as createSandboxRuntime } from "../SandboxRuntimeAdapter-C1B4t20N.mjs";
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { i as version, r as forceCheckForUpdate } from "../updateChecker-DZXWZfKF.mjs";
2
+ import { a as version, i as forceCheckForUpdate } from "../updateChecker-D-xoVcN3.mjs";
3
3
  import { execSync } from "child_process";
4
4
  //#region src/commands/updateCommand.ts
5
5
  /**
package/dist/index.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import { n as useCliStore, t as selectActiveBackgroundAgents } from "./store-B7-LLvvx.mjs";
3
- import { $ as processFileReferences, A as getApiUrl, B as registerFeatureModuleTools, C as WebSocketLlmBackend, D as formatStep, E as substituteArguments, F as DEFAULT_AGENT_MODEL, G as isReadOnlyTool, H as OllamaBackend, I as DEFAULT_MAX_ITERATIONS, J as CheckpointStore, K as ReActAgent, L as DEFAULT_RETRY_CONFIG, M as PermissionManager, N as generateCliTools, O as extractCompactInstructions, P as ALWAYS_DENIED_FOR_AGENTS, Q as hasFileReferences, R as DEFAULT_THOROUGHNESS, S as FallbackLlmBackend, T as McpManager, U as buildCoreSystemPrompt, V as setWebSocketToolExecutor, W as buildSkillsPromptSection, X as SessionStore, Y as CommandHistoryStore, Z as OAuthClient, _ as createSkillTool, a as createDecisionStore, b as WebSocketToolExecutor, c as createFindDefinitionTool, d as createCoordinateTaskTool, et as searchCommands, f as createBackgroundAgentTools, g as SubagentOrchestrator, h as AgentStore, i as createDecisionLogTool, it as warmFileCache, j as getEnvironmentName, k as loadContextFiles, l as createTodoStore, m as createAgentDelegateTool, n as createBlockerTools, nt as formatFileSize, o as formatDecisionsOutput, p as BackgroundAgentManager, q as CustomCommandStore, r as formatBlockersOutput, rt as searchFiles, s as createGetFileStructureTool, t as createBlockerStore, tt as mergeCommands, u as createWriteTodosTool, v as parseAgentConfig, w as ServerLlmBackend, x as WebSocketConnectionManager, y as ApiClient, z as clearFeatureModuleTools } from "./tools-dIVxi-6-.mjs";
3
+ import { $ as processFileReferences, A as getApiUrl, B as registerFeatureModuleTools, C as WebSocketLlmBackend, D as formatStep, E as substituteArguments, F as DEFAULT_AGENT_MODEL, G as isReadOnlyTool, H as OllamaBackend, I as DEFAULT_MAX_ITERATIONS, J as CheckpointStore, K as ReActAgent, L as DEFAULT_RETRY_CONFIG, M as PermissionManager, N as generateCliTools, O as extractCompactInstructions, P as ALWAYS_DENIED_FOR_AGENTS, Q as hasFileReferences, R as DEFAULT_THOROUGHNESS, S as FallbackLlmBackend, T as McpManager, U as buildCoreSystemPrompt, V as setWebSocketToolExecutor, W as buildSkillsPromptSection, X as SessionStore, Y as CommandHistoryStore, Z as OAuthClient, _ as createSkillTool, a as createDecisionStore, b as WebSocketToolExecutor, c as createFindDefinitionTool, d as createCoordinateTaskTool, et as searchCommands, f as createBackgroundAgentTools, g as SubagentOrchestrator, h as AgentStore, i as createDecisionLogTool, it as warmFileCache, j as getEnvironmentName, k as loadContextFiles, l as createTodoStore, m as createAgentDelegateTool, n as createBlockerTools, nt as formatFileSize, o as formatDecisionsOutput, p as BackgroundAgentManager, q as CustomCommandStore, r as formatBlockersOutput, rt as searchFiles, s as createGetFileStructureTool, t as createBlockerStore, tt as mergeCommands, u as createWriteTodosTool, v as parseAgentConfig, w as ServerLlmBackend, x as WebSocketConnectionManager, y as ApiClient, z as clearFeatureModuleTools } from "./tools-BUs_OkJc.mjs";
4
4
  import { Mt as validateNotebookPath$1, g as ChatModels, jt as validateJupyterKernelName, m as CREDIT_DEDUCT_TRANSACTION_TYPES, n as logger, t as ConfigStore } from "./ConfigStore-Dt6utdSA.mjs";
5
- import { i as version, t as checkForUpdate } from "./updateChecker-DZXWZfKF.mjs";
5
+ import { a as version, t as checkForUpdate } from "./updateChecker-D-xoVcN3.mjs";
6
6
  import React, { useCallback, useEffect, useMemo, useReducer, useRef, useState } from "react";
7
7
  import { Box, Static, Text, render, useApp, useInput } from "ink";
8
8
  import { execSync } from "child_process";
@@ -5335,7 +5335,8 @@ function CliApp() {
5335
5335
  console.log("\n🔐 Welcome to B4M CLI! Authentication is required to get started.\n");
5336
5336
  setState((prev) => ({
5337
5337
  ...prev,
5338
- showLoginFlow: true
5338
+ showLoginFlow: true,
5339
+ config
5339
5340
  }));
5340
5341
  return;
5341
5342
  }
@@ -5345,7 +5346,8 @@ function CliApp() {
5345
5346
  await state.configStore.clearAuthTokens();
5346
5347
  setState((prev) => ({
5347
5348
  ...prev,
5348
- showLoginFlow: true
5349
+ showLoginFlow: true,
5350
+ config
5349
5351
  }));
5350
5352
  return;
5351
5353
  }
@@ -2906,7 +2906,7 @@ const TOOL_FILE_READ = "file_read";
2906
2906
  const TOOL_EDIT_LOCAL_FILE = "edit_local_file";
2907
2907
  const TOOL_CREATE_FILE = "create_file";
2908
2908
  const TOOL_BASH_EXECUTE = "bash_execute";
2909
- const TOOL_SUBAGENT_DELEGATE = "subagent_delegate";
2909
+ const TOOL_SUBAGENT_DELEGATE = "agent_delegate";
2910
2910
  const TOOL_WRITE_TODOS = "write_todos";
2911
2911
  const TOOL_CREATE_DYNAMIC_AGENT = "create_dynamic_agent";
2912
2912
  const EXPLORE_SUBAGENT_TYPE = "explore";
@@ -3025,7 +3025,7 @@ EXAMPLES:
3025
3025
  - "how about Japan?" → use weather tool for Japan (applying same question from context)
3026
3026
  - "enhance README" → ${TOOL_FILE_READ} → generate → ${TOOL_EDIT_LOCAL_FILE}
3027
3027
  - "what packages installed?" → ${TOOL_GLOB_FILES} "**/package.json" → ${TOOL_FILE_READ}
3028
- - "find all components using React hooks" → ${TOOL_SUBAGENT_DELEGATE}(task="find all components using React hooks", type="explore")
3028
+ - "find all components using React hooks" → ${TOOL_SUBAGENT_DELEGATE}(task="find all components using React hooks", agent="explore")
3029
3029
 
3030
3030
  Remember: Use context from previous messages to understand follow-up questions.
3031
3031
 
@@ -21995,7 +21995,7 @@ Describe the expected output format here.
21995
21995
  */
21996
21996
  getDirectoryContext() {
21997
21997
  if (this.agents.size === 0) return "No sub-agents are currently available.";
21998
- let context = "Use `subagent_delegate` for complex tasks requiring specialized analysis.\n";
21998
+ let context = "Use `agent_delegate` for complex tasks requiring specialized analysis.\n";
21999
21999
  for (const [name, def] of this.agents) context += ` - **${name}**: ${def.description}\n`;
22000
22000
  return context;
22001
22001
  }
@@ -4,7 +4,7 @@ import { homedir } from "os";
4
4
  import path from "path";
5
5
  import axios from "axios";
6
6
  //#region package.json
7
- var version = "0.6.0";
7
+ var version = "0.6.1";
8
8
  //#endregion
9
9
  //#region src/utils/updateChecker.ts
10
10
  /**
@@ -53,7 +53,7 @@ async function readCache() {
53
53
  try {
54
54
  const data = await promises.readFile(CACHE_FILE, "utf-8");
55
55
  const parsed = JSON.parse(data);
56
- if (parsed && typeof parsed.lastChecked === "string" && typeof parsed.latestVersion === "string") return parsed;
56
+ if (parsed && typeof parsed.lastChecked === "string" && typeof parsed.latestVersion === "string" && typeof parsed.currentVersion === "string") return parsed;
57
57
  return null;
58
58
  } catch {
59
59
  return null;
@@ -117,4 +117,4 @@ async function forceCheckForUpdate(currentVersion) {
117
117
  };
118
118
  }
119
119
  //#endregion
120
- export { version as i, fetchLatestVersion as n, forceCheckForUpdate as r, checkForUpdate as t };
120
+ export { version as a, forceCheckForUpdate as i, compareSemver as n, fetchLatestVersion as r, checkForUpdate as t };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bike4mind/cli",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "type": "module",
5
5
  "description": "Interactive CLI tool for Bike4Mind with ReAct agents",
6
6
  "license": "UNLICENSED",
@@ -103,7 +103,7 @@
103
103
  "yauzl": "^3.3.0",
104
104
  "zod": "^4.3.6",
105
105
  "zod-validation-error": "^5.0.0",
106
- "zustand": "^5.0.13"
106
+ "zustand": "^4.5.4"
107
107
  },
108
108
  "devDependencies": {
109
109
  "@types/better-sqlite3": "^7.6.13",
@@ -118,11 +118,11 @@
118
118
  "tsx": "^4.21.0",
119
119
  "typescript": "^5.9.3",
120
120
  "vitest": "^4.1.2",
121
- "@bike4mind/agents": "0.0.0-changeset-release-main-20260505221459",
122
- "@bike4mind/common": "0.0.0-changeset-release-main-20260505221459",
123
- "@bike4mind/mcp": "0.0.0-changeset-release-main-20260505221459",
124
- "@bike4mind/services": "0.0.0-changeset-release-main-20260505221459",
125
- "@bike4mind/utils": "0.0.0-changeset-release-main-20260505221459"
121
+ "@bike4mind/agents": "0.6.3",
122
+ "@bike4mind/common": "2.92.1",
123
+ "@bike4mind/mcp": "1.37.3",
124
+ "@bike4mind/services": "2.79.3",
125
+ "@bike4mind/utils": "2.19.3"
126
126
  },
127
127
  "optionalDependencies": {
128
128
  "@vscode/ripgrep": "^1.17.1"