bumblebee-cli 0.1.0 → 0.1.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/bin/bb.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { execFileSync, execSync } from "node:child_process";
4
- import { existsSync } from "node:fs";
5
- import { dirname, join } from "node:path";
4
+ import { existsSync, readFileSync } from "node:fs";
5
+ import { dirname, join, resolve } from "node:path";
6
6
  import { fileURLToPath } from "node:url";
7
7
 
8
8
  const __dirname = dirname(fileURLToPath(import.meta.url));
@@ -13,20 +13,45 @@ const args = process.argv.slice(2);
13
13
  * Thin Node.js wrapper for the Bumblebee Python CLI.
14
14
  *
15
15
  * Resolution order:
16
- * 1. `bb` already on PATH (user installed via pip)
16
+ * 1. `bb` already on PATH (user installed via pip — not our own npm wrapper)
17
17
  * 2. Local .venv created by postinstall
18
18
  * 3. `python -m bb_cli` (fallback)
19
19
  */
20
20
 
21
+ function getNpmGlobalPrefix() {
22
+ try {
23
+ return execSync("npm prefix -g", { encoding: "utf8", stdio: "pipe" }).trim();
24
+ } catch {
25
+ return null;
26
+ }
27
+ }
28
+
29
+ function isOurOwnWrapper(bbPath) {
30
+ // Check if the found bb is inside our npm package or the npm global bin
31
+ const normalized = resolve(bbPath).toLowerCase();
32
+ if (normalized.includes("node_modules") && normalized.includes("bumblebee-cli")) {
33
+ return true;
34
+ }
35
+ // On Windows/Linux, npm global installs create shims in the npm prefix dir
36
+ const npmPrefix = getNpmGlobalPrefix();
37
+ if (npmPrefix && normalized.startsWith(resolve(npmPrefix).toLowerCase())) {
38
+ return true;
39
+ }
40
+ return false;
41
+ }
42
+
21
43
  // 1. Check if `bb` is already available on PATH (pip install)
22
44
  function trySystemBb() {
23
45
  try {
24
46
  const which = process.platform === "win32" ? "where" : "which";
25
47
  const result = execSync(`${which} bb`, { stdio: "pipe", encoding: "utf8" });
26
- const bbPath = result.trim().split("\n")[0];
27
- // Make sure it's not pointing back to ourselves
28
- if (bbPath && !bbPath.includes("npm-cli")) {
29
- return bbPath;
48
+ // On Windows, `where` may return multiple lines; check each
49
+ const paths = result.trim().split(/\r?\n/);
50
+ for (const bbPath of paths) {
51
+ const p = bbPath.trim();
52
+ if (p && !isOurOwnWrapper(p)) {
53
+ return p;
54
+ }
30
55
  }
31
56
  } catch {
32
57
  // not found
@@ -48,10 +73,11 @@ function tryLocalVenv() {
48
73
 
49
74
  // 3. Fallback to python -m bb_cli
50
75
  function tryPythonModule() {
51
- const pythonCmds = ["python3", "python"];
76
+ const pythonCmds =
77
+ process.platform === "win32" ? ["python", "python3"] : ["python3", "python"];
52
78
  for (const py of pythonCmds) {
53
79
  try {
54
- execSync(`${py} --version`, { stdio: "pipe" });
80
+ execSync(`${py} -c "import bb_cli"`, { stdio: "pipe" });
55
81
  return { python: py, module: true };
56
82
  } catch {
57
83
  // try next
@@ -95,8 +121,12 @@ if (pyFallback) {
95
121
  }
96
122
 
97
123
  console.error(
98
- "Error: Could not find Python or the Bumblebee CLI.\n" +
99
- "Install Python 3.12+ and run: pip install bumblebee-cli\n" +
100
- "Or reinstall this package: npm install -g bumblebee-cli"
124
+ "Error: Could not find the Bumblebee Python CLI.\n" +
125
+ "\n" +
126
+ "The npm package needs the Python CLI installed. Fix with ONE of:\n" +
127
+ " 1. pip install bumblebee-cli (install globally)\n" +
128
+ " 2. npm rebuild bumblebee-cli (retry postinstall setup)\n" +
129
+ "\n" +
130
+ "Requires Python 3.12+ — https://python.org"
101
131
  );
102
132
  process.exit(1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bumblebee-cli",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Bumblebee CLI — Dev task management + Claude Code automation",
5
5
  "license": "MIT",
6
6
  "bin": {
@@ -4,14 +4,14 @@
4
4
  * Postinstall script for bumblebee-cli
5
5
  *
6
6
  * - Checks for Python 3.12+
7
- * - Skips if `bb` is already on PATH (user installed via pip)
7
+ * - Skips if a real (pip-installed) `bb` is already on PATH
8
8
  * - Creates a local .venv and installs the Python CLI
9
9
  * - NEVER fails npm install — warns instead
10
10
  */
11
11
 
12
12
  import { execSync } from "node:child_process";
13
13
  import { existsSync } from "node:fs";
14
- import { dirname, join } from "node:path";
14
+ import { dirname, join, resolve } from "node:path";
15
15
  import { fileURLToPath } from "node:url";
16
16
 
17
17
  const __dirname = dirname(fileURLToPath(import.meta.url));
@@ -26,20 +26,45 @@ function warn(msg) {
26
26
  console.warn(`[bumblebee-cli] WARNING: ${msg}`);
27
27
  }
28
28
 
29
- // Check if bb is already available
30
- function isBbInstalled() {
29
+ // Check if a real (non-npm-wrapper) bb is already available
30
+ function isPipBbInstalled() {
31
31
  try {
32
+ // Try running bb --help and check if it's the Python CLI (not our wrapper)
32
33
  const which = process.platform === "win32" ? "where" : "which";
33
- execSync(`${which} bb`, { stdio: "pipe" });
34
- return true;
34
+ const result = execSync(`${which} bb`, { encoding: "utf8", stdio: "pipe" });
35
+ const paths = result.trim().split(/\r?\n/);
36
+
37
+ // Get npm global prefix to filter out our own wrapper
38
+ let npmPrefix = null;
39
+ try {
40
+ npmPrefix = execSync("npm prefix -g", { encoding: "utf8", stdio: "pipe" }).trim();
41
+ } catch {}
42
+
43
+ for (const bbPath of paths) {
44
+ const p = bbPath.trim();
45
+ if (!p) continue;
46
+ const normalized = resolve(p).toLowerCase();
47
+ // Skip if it's inside npm global prefix (that's our own wrapper)
48
+ if (npmPrefix && normalized.startsWith(resolve(npmPrefix).toLowerCase())) {
49
+ continue;
50
+ }
51
+ // Skip if it's inside node_modules
52
+ if (normalized.includes("node_modules") && normalized.includes("bumblebee-cli")) {
53
+ continue;
54
+ }
55
+ // Found a real bb (pip-installed)
56
+ return true;
57
+ }
35
58
  } catch {
36
- return false;
59
+ // not found
37
60
  }
61
+ return false;
38
62
  }
39
63
 
40
64
  // Find python and check version
41
65
  function findPython() {
42
- const candidates = ["python3", "python"];
66
+ const candidates =
67
+ process.platform === "win32" ? ["python", "python3"] : ["python3", "python"];
43
68
  for (const cmd of candidates) {
44
69
  try {
45
70
  const version = execSync(`${cmd} --version`, {
@@ -64,8 +89,8 @@ function findPython() {
64
89
 
65
90
  function main() {
66
91
  // Skip if bb already installed via pip
67
- if (isBbInstalled()) {
68
- log("'bb' command found on PATH — skipping Python setup.");
92
+ if (isPipBbInstalled()) {
93
+ log("'bb' command found on PATH (pip) — skipping Python setup.");
69
94
  return;
70
95
  }
71
96